diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java new file mode 100644 index 0000000..5c1c6f2 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java @@ -0,0 +1,29 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.casic.missiles.pojo.Msg; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubServerHandler + */ +@Service +public class SensorhubServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + System.out.println("Client->Server:" + obj.toString()); + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Client->Server:" + JSON.toJSONString(msg)); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + +} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java new file mode 100644 index 0000000..5c1c6f2 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java @@ -0,0 +1,29 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.casic.missiles.pojo.Msg; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubServerHandler + */ +@Service +public class SensorhubServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + System.out.println("Client->Server:" + obj.toString()); + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Client->Server:" + JSON.toJSONString(msg)); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java deleted file mode 100644 index 528dafc..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.casic.missiles.server; - -import com.casic.missiles.autoconfig.SensorhubProperties; -import com.casic.missiles.server.handler.SensorhubServerChannelInitialHandler; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.PreDestroy; - -/** - * SensorhubServer netty服务端 - */ -@Slf4j -@Service -public class SensorhubServer { - - /** - * sensorhub默认端口 - */ - public static int DEFAULT_PORT = 7091; - - // 多线程事件循环器 - EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss - EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker - - /** - * sensorhub属性参数 - */ - @Autowired - private SensorhubProperties sensorhubProperties; - @Autowired - private SensorhubServerChannelInitialHandler serverChannelInitialHandler; - - public SensorhubServer(SensorhubProperties sensorhubProperties) { - this.sensorhubProperties = sensorhubProperties; - } - - /** - * 获取sensorhub实例 - * - * @param sensorhubProperties - * @throws Exception - */ - public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { - SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); - sensorhubServer.startServer(); - return sensorhubServer; - } - - /** - * 启动sensorhub服务 - */ - public void startServer() { - new Thread(new Runnable() { - @Override - public void run() { - Integer port = sensorhubProperties.getPort(); - if (port == null) { - log.info("sensorhub服务端口不能为空"); - port = DEFAULT_PORT; - } - try { - // 启动NIO服务的引导程序类 - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) // 设置EventLoopGroup - .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 - .childHandler(serverChannelInitialHandler) // 指定ChannelHandler - .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 - .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 - // 绑定端口,开始接收进来的连接 - ChannelFuture f = b.bind(port).sync(); - log.info("sensorhub已启动,端口:" + port); - // 等待服务器 socket 关闭 。 - f.channel().closeFuture().sync(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - //优雅的关闭 - workerGroup.shutdownGracefully(); - bossGroup.shutdownGracefully(); - } - } - }).start(); - } - - @PreDestroy - public void destroy() { - this.bossGroup.shutdownGracefully(); - this.workerGroup.shutdownGracefully(); - log.info("关闭Netty"); - } - - - public static void main(String[] args) throws Exception { - SensorhubServer server = new SensorhubServer(new SensorhubProperties()); - server.startServer(); - } - -} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java new file mode 100644 index 0000000..5c1c6f2 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java @@ -0,0 +1,29 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.casic.missiles.pojo.Msg; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubServerHandler + */ +@Service +public class SensorhubServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + System.out.println("Client->Server:" + obj.toString()); + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Client->Server:" + JSON.toJSONString(msg)); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java deleted file mode 100644 index 528dafc..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.casic.missiles.server; - -import com.casic.missiles.autoconfig.SensorhubProperties; -import com.casic.missiles.server.handler.SensorhubServerChannelInitialHandler; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.PreDestroy; - -/** - * SensorhubServer netty服务端 - */ -@Slf4j -@Service -public class SensorhubServer { - - /** - * sensorhub默认端口 - */ - public static int DEFAULT_PORT = 7091; - - // 多线程事件循环器 - EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss - EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker - - /** - * sensorhub属性参数 - */ - @Autowired - private SensorhubProperties sensorhubProperties; - @Autowired - private SensorhubServerChannelInitialHandler serverChannelInitialHandler; - - public SensorhubServer(SensorhubProperties sensorhubProperties) { - this.sensorhubProperties = sensorhubProperties; - } - - /** - * 获取sensorhub实例 - * - * @param sensorhubProperties - * @throws Exception - */ - public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { - SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); - sensorhubServer.startServer(); - return sensorhubServer; - } - - /** - * 启动sensorhub服务 - */ - public void startServer() { - new Thread(new Runnable() { - @Override - public void run() { - Integer port = sensorhubProperties.getPort(); - if (port == null) { - log.info("sensorhub服务端口不能为空"); - port = DEFAULT_PORT; - } - try { - // 启动NIO服务的引导程序类 - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) // 设置EventLoopGroup - .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 - .childHandler(serverChannelInitialHandler) // 指定ChannelHandler - .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 - .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 - // 绑定端口,开始接收进来的连接 - ChannelFuture f = b.bind(port).sync(); - log.info("sensorhub已启动,端口:" + port); - // 等待服务器 socket 关闭 。 - f.channel().closeFuture().sync(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - //优雅的关闭 - workerGroup.shutdownGracefully(); - bossGroup.shutdownGracefully(); - } - } - }).start(); - } - - @PreDestroy - public void destroy() { - this.bossGroup.shutdownGracefully(); - this.workerGroup.shutdownGracefully(); - log.info("关闭Netty"); - } - - - public static void main(String[] args) throws Exception { - SensorhubServer server = new SensorhubServer(new SensorhubProperties()); - server.startServer(); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java deleted file mode 100644 index 4346058..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.casic.missiles.server.client; - -import com.casic.missiles.server.client.handler.SensorhubClientChannelInitialHandler; -import com.casic.missiles.pojo.Msg; -import com.casic.missiles.utils.MsgUtil; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClient 客户端 - */ -@Slf4j -@Service -public final class SensorhubClient { - - public static void main(String[] args) throws Exception { - String hostName = "localhost"; - int portNumber = Integer.parseInt("7091"); - - // 配置客户端 - EventLoopGroup group = new NioEventLoopGroup(); - try { - Bootstrap b = new Bootstrap(); - b.group(group) - .channel(NioSocketChannel.class) - .option(ChannelOption.TCP_NODELAY, true) - .handler(new SensorhubClientChannelInitialHandler()); - - // 连接到服务器 - ChannelFuture f = b.connect(hostName, portNumber).sync(); - - Channel channel = f.channel(); - channel.writeAndFlush(MsgUtil.getMsg()); - Msg msg = MsgUtil.getMsg(); - msg.setTransControlFlag(1); - channel.writeAndFlush(msg); -// ByteBuffer writeBuffer = ByteBuffer.allocate(32); -// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { -// String userInput; -// while ((userInput = stdIn.readLine()) != null) { -// writeBuffer.put(userInput.getBytes()); -// writeBuffer.flip(); -// writeBuffer.rewind(); -// -// // 转为ByteBuf -// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); -// -// // 写消息到管道 -// channel.writeAndFlush(buf); -// -// // 清理缓冲区 -// writeBuffer.clear(); -// } -// } catch (UnknownHostException e) { -// System.err.println("不明主机,主机名为: " + hostName); -// System.exit(1); -// } catch (IOException e) { -// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); -// System.exit(1); -// } - } finally { - // 优雅的关闭 - group.shutdownGracefully(); - } - } - - -} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java new file mode 100644 index 0000000..5c1c6f2 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java @@ -0,0 +1,29 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.casic.missiles.pojo.Msg; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubServerHandler + */ +@Service +public class SensorhubServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + System.out.println("Client->Server:" + obj.toString()); + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Client->Server:" + JSON.toJSONString(msg)); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java deleted file mode 100644 index 528dafc..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.casic.missiles.server; - -import com.casic.missiles.autoconfig.SensorhubProperties; -import com.casic.missiles.server.handler.SensorhubServerChannelInitialHandler; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.PreDestroy; - -/** - * SensorhubServer netty服务端 - */ -@Slf4j -@Service -public class SensorhubServer { - - /** - * sensorhub默认端口 - */ - public static int DEFAULT_PORT = 7091; - - // 多线程事件循环器 - EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss - EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker - - /** - * sensorhub属性参数 - */ - @Autowired - private SensorhubProperties sensorhubProperties; - @Autowired - private SensorhubServerChannelInitialHandler serverChannelInitialHandler; - - public SensorhubServer(SensorhubProperties sensorhubProperties) { - this.sensorhubProperties = sensorhubProperties; - } - - /** - * 获取sensorhub实例 - * - * @param sensorhubProperties - * @throws Exception - */ - public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { - SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); - sensorhubServer.startServer(); - return sensorhubServer; - } - - /** - * 启动sensorhub服务 - */ - public void startServer() { - new Thread(new Runnable() { - @Override - public void run() { - Integer port = sensorhubProperties.getPort(); - if (port == null) { - log.info("sensorhub服务端口不能为空"); - port = DEFAULT_PORT; - } - try { - // 启动NIO服务的引导程序类 - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) // 设置EventLoopGroup - .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 - .childHandler(serverChannelInitialHandler) // 指定ChannelHandler - .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 - .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 - // 绑定端口,开始接收进来的连接 - ChannelFuture f = b.bind(port).sync(); - log.info("sensorhub已启动,端口:" + port); - // 等待服务器 socket 关闭 。 - f.channel().closeFuture().sync(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - //优雅的关闭 - workerGroup.shutdownGracefully(); - bossGroup.shutdownGracefully(); - } - } - }).start(); - } - - @PreDestroy - public void destroy() { - this.bossGroup.shutdownGracefully(); - this.workerGroup.shutdownGracefully(); - log.info("关闭Netty"); - } - - - public static void main(String[] args) throws Exception { - SensorhubServer server = new SensorhubServer(new SensorhubProperties()); - server.startServer(); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java deleted file mode 100644 index 4346058..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.casic.missiles.server.client; - -import com.casic.missiles.server.client.handler.SensorhubClientChannelInitialHandler; -import com.casic.missiles.pojo.Msg; -import com.casic.missiles.utils.MsgUtil; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClient 客户端 - */ -@Slf4j -@Service -public final class SensorhubClient { - - public static void main(String[] args) throws Exception { - String hostName = "localhost"; - int portNumber = Integer.parseInt("7091"); - - // 配置客户端 - EventLoopGroup group = new NioEventLoopGroup(); - try { - Bootstrap b = new Bootstrap(); - b.group(group) - .channel(NioSocketChannel.class) - .option(ChannelOption.TCP_NODELAY, true) - .handler(new SensorhubClientChannelInitialHandler()); - - // 连接到服务器 - ChannelFuture f = b.connect(hostName, portNumber).sync(); - - Channel channel = f.channel(); - channel.writeAndFlush(MsgUtil.getMsg()); - Msg msg = MsgUtil.getMsg(); - msg.setTransControlFlag(1); - channel.writeAndFlush(msg); -// ByteBuffer writeBuffer = ByteBuffer.allocate(32); -// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { -// String userInput; -// while ((userInput = stdIn.readLine()) != null) { -// writeBuffer.put(userInput.getBytes()); -// writeBuffer.flip(); -// writeBuffer.rewind(); -// -// // 转为ByteBuf -// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); -// -// // 写消息到管道 -// channel.writeAndFlush(buf); -// -// // 清理缓冲区 -// writeBuffer.clear(); -// } -// } catch (UnknownHostException e) { -// System.err.println("不明主机,主机名为: " + hostName); -// System.exit(1); -// } catch (IOException e) { -// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); -// System.exit(1); -// } - } finally { - // 优雅的关闭 - group.shutdownGracefully(); - } - } - - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java deleted file mode 100644 index 0ec6d91..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientChannelInitialHandler - */ -@Service -public class SensorhubClientChannelInitialHandler extends ChannelInitializer { - - @Override - protected void initChannel(SocketChannel socketChannel){ - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new SensorhubDecoder()); -// pipeline.addLast(new SensorhubEncoder()); - pipeline.addLast(new SensorhubClientHandler()); - } - -} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java new file mode 100644 index 0000000..5c1c6f2 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java @@ -0,0 +1,29 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.casic.missiles.pojo.Msg; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubServerHandler + */ +@Service +public class SensorhubServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + System.out.println("Client->Server:" + obj.toString()); + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Client->Server:" + JSON.toJSONString(msg)); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java deleted file mode 100644 index 528dafc..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.casic.missiles.server; - -import com.casic.missiles.autoconfig.SensorhubProperties; -import com.casic.missiles.server.handler.SensorhubServerChannelInitialHandler; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.PreDestroy; - -/** - * SensorhubServer netty服务端 - */ -@Slf4j -@Service -public class SensorhubServer { - - /** - * sensorhub默认端口 - */ - public static int DEFAULT_PORT = 7091; - - // 多线程事件循环器 - EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss - EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker - - /** - * sensorhub属性参数 - */ - @Autowired - private SensorhubProperties sensorhubProperties; - @Autowired - private SensorhubServerChannelInitialHandler serverChannelInitialHandler; - - public SensorhubServer(SensorhubProperties sensorhubProperties) { - this.sensorhubProperties = sensorhubProperties; - } - - /** - * 获取sensorhub实例 - * - * @param sensorhubProperties - * @throws Exception - */ - public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { - SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); - sensorhubServer.startServer(); - return sensorhubServer; - } - - /** - * 启动sensorhub服务 - */ - public void startServer() { - new Thread(new Runnable() { - @Override - public void run() { - Integer port = sensorhubProperties.getPort(); - if (port == null) { - log.info("sensorhub服务端口不能为空"); - port = DEFAULT_PORT; - } - try { - // 启动NIO服务的引导程序类 - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) // 设置EventLoopGroup - .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 - .childHandler(serverChannelInitialHandler) // 指定ChannelHandler - .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 - .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 - // 绑定端口,开始接收进来的连接 - ChannelFuture f = b.bind(port).sync(); - log.info("sensorhub已启动,端口:" + port); - // 等待服务器 socket 关闭 。 - f.channel().closeFuture().sync(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - //优雅的关闭 - workerGroup.shutdownGracefully(); - bossGroup.shutdownGracefully(); - } - } - }).start(); - } - - @PreDestroy - public void destroy() { - this.bossGroup.shutdownGracefully(); - this.workerGroup.shutdownGracefully(); - log.info("关闭Netty"); - } - - - public static void main(String[] args) throws Exception { - SensorhubServer server = new SensorhubServer(new SensorhubProperties()); - server.startServer(); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java deleted file mode 100644 index 4346058..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.casic.missiles.server.client; - -import com.casic.missiles.server.client.handler.SensorhubClientChannelInitialHandler; -import com.casic.missiles.pojo.Msg; -import com.casic.missiles.utils.MsgUtil; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClient 客户端 - */ -@Slf4j -@Service -public final class SensorhubClient { - - public static void main(String[] args) throws Exception { - String hostName = "localhost"; - int portNumber = Integer.parseInt("7091"); - - // 配置客户端 - EventLoopGroup group = new NioEventLoopGroup(); - try { - Bootstrap b = new Bootstrap(); - b.group(group) - .channel(NioSocketChannel.class) - .option(ChannelOption.TCP_NODELAY, true) - .handler(new SensorhubClientChannelInitialHandler()); - - // 连接到服务器 - ChannelFuture f = b.connect(hostName, portNumber).sync(); - - Channel channel = f.channel(); - channel.writeAndFlush(MsgUtil.getMsg()); - Msg msg = MsgUtil.getMsg(); - msg.setTransControlFlag(1); - channel.writeAndFlush(msg); -// ByteBuffer writeBuffer = ByteBuffer.allocate(32); -// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { -// String userInput; -// while ((userInput = stdIn.readLine()) != null) { -// writeBuffer.put(userInput.getBytes()); -// writeBuffer.flip(); -// writeBuffer.rewind(); -// -// // 转为ByteBuf -// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); -// -// // 写消息到管道 -// channel.writeAndFlush(buf); -// -// // 清理缓冲区 -// writeBuffer.clear(); -// } -// } catch (UnknownHostException e) { -// System.err.println("不明主机,主机名为: " + hostName); -// System.exit(1); -// } catch (IOException e) { -// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); -// System.exit(1); -// } - } finally { - // 优雅的关闭 - group.shutdownGracefully(); - } - } - - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java deleted file mode 100644 index 0ec6d91..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientChannelInitialHandler - */ -@Service -public class SensorhubClientChannelInitialHandler extends ChannelInitializer { - - @Override - protected void initChannel(SocketChannel socketChannel){ - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new SensorhubDecoder()); -// pipeline.addLast(new SensorhubEncoder()); - pipeline.addLast(new SensorhubClientHandler()); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java deleted file mode 100644 index 8121d9e..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.pojo.Msg; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientHandler - */ -@Slf4j -@Service -public class SensorhubClientHandler extends SimpleChannelInboundHandler { - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { - Channel incoming = ctx.channel(); - - if (obj instanceof Msg) { - Msg msg = (Msg) obj; - System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); - } else { - System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); - } - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { -// Msg msg = new Msg(); -// msg.setPreamble("A3"); -// msg.setVersion("V2.0"); -// String tagList = "hello world"; -// int byteLeng = tagList.getBytes().length; -// msg.setLeng(byteLeng); -// msg.setDeviceId("122121"); -// msg.setConnType(1); -// msg.setOperateType(3); -// msg.setDeviceType(1); -// msg.setTransControlFlag(1); -// msg.setDestAddr("111111"); -// msg.setSeq(1); -// msg.setTagList(tagList); -// System.out.println("client发送msg:"); -// System.out.println(JSON.toJSONString(msg)); -// ctx.writeAndFlush(msg); - log.info("连接成功"); - } -} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java new file mode 100644 index 0000000..5c1c6f2 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java @@ -0,0 +1,29 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.casic.missiles.pojo.Msg; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubServerHandler + */ +@Service +public class SensorhubServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + System.out.println("Client->Server:" + obj.toString()); + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Client->Server:" + JSON.toJSONString(msg)); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java deleted file mode 100644 index 528dafc..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.casic.missiles.server; - -import com.casic.missiles.autoconfig.SensorhubProperties; -import com.casic.missiles.server.handler.SensorhubServerChannelInitialHandler; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.PreDestroy; - -/** - * SensorhubServer netty服务端 - */ -@Slf4j -@Service -public class SensorhubServer { - - /** - * sensorhub默认端口 - */ - public static int DEFAULT_PORT = 7091; - - // 多线程事件循环器 - EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss - EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker - - /** - * sensorhub属性参数 - */ - @Autowired - private SensorhubProperties sensorhubProperties; - @Autowired - private SensorhubServerChannelInitialHandler serverChannelInitialHandler; - - public SensorhubServer(SensorhubProperties sensorhubProperties) { - this.sensorhubProperties = sensorhubProperties; - } - - /** - * 获取sensorhub实例 - * - * @param sensorhubProperties - * @throws Exception - */ - public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { - SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); - sensorhubServer.startServer(); - return sensorhubServer; - } - - /** - * 启动sensorhub服务 - */ - public void startServer() { - new Thread(new Runnable() { - @Override - public void run() { - Integer port = sensorhubProperties.getPort(); - if (port == null) { - log.info("sensorhub服务端口不能为空"); - port = DEFAULT_PORT; - } - try { - // 启动NIO服务的引导程序类 - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) // 设置EventLoopGroup - .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 - .childHandler(serverChannelInitialHandler) // 指定ChannelHandler - .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 - .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 - // 绑定端口,开始接收进来的连接 - ChannelFuture f = b.bind(port).sync(); - log.info("sensorhub已启动,端口:" + port); - // 等待服务器 socket 关闭 。 - f.channel().closeFuture().sync(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - //优雅的关闭 - workerGroup.shutdownGracefully(); - bossGroup.shutdownGracefully(); - } - } - }).start(); - } - - @PreDestroy - public void destroy() { - this.bossGroup.shutdownGracefully(); - this.workerGroup.shutdownGracefully(); - log.info("关闭Netty"); - } - - - public static void main(String[] args) throws Exception { - SensorhubServer server = new SensorhubServer(new SensorhubProperties()); - server.startServer(); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java deleted file mode 100644 index 4346058..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.casic.missiles.server.client; - -import com.casic.missiles.server.client.handler.SensorhubClientChannelInitialHandler; -import com.casic.missiles.pojo.Msg; -import com.casic.missiles.utils.MsgUtil; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClient 客户端 - */ -@Slf4j -@Service -public final class SensorhubClient { - - public static void main(String[] args) throws Exception { - String hostName = "localhost"; - int portNumber = Integer.parseInt("7091"); - - // 配置客户端 - EventLoopGroup group = new NioEventLoopGroup(); - try { - Bootstrap b = new Bootstrap(); - b.group(group) - .channel(NioSocketChannel.class) - .option(ChannelOption.TCP_NODELAY, true) - .handler(new SensorhubClientChannelInitialHandler()); - - // 连接到服务器 - ChannelFuture f = b.connect(hostName, portNumber).sync(); - - Channel channel = f.channel(); - channel.writeAndFlush(MsgUtil.getMsg()); - Msg msg = MsgUtil.getMsg(); - msg.setTransControlFlag(1); - channel.writeAndFlush(msg); -// ByteBuffer writeBuffer = ByteBuffer.allocate(32); -// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { -// String userInput; -// while ((userInput = stdIn.readLine()) != null) { -// writeBuffer.put(userInput.getBytes()); -// writeBuffer.flip(); -// writeBuffer.rewind(); -// -// // 转为ByteBuf -// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); -// -// // 写消息到管道 -// channel.writeAndFlush(buf); -// -// // 清理缓冲区 -// writeBuffer.clear(); -// } -// } catch (UnknownHostException e) { -// System.err.println("不明主机,主机名为: " + hostName); -// System.exit(1); -// } catch (IOException e) { -// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); -// System.exit(1); -// } - } finally { - // 优雅的关闭 - group.shutdownGracefully(); - } - } - - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java deleted file mode 100644 index 0ec6d91..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientChannelInitialHandler - */ -@Service -public class SensorhubClientChannelInitialHandler extends ChannelInitializer { - - @Override - protected void initChannel(SocketChannel socketChannel){ - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new SensorhubDecoder()); -// pipeline.addLast(new SensorhubEncoder()); - pipeline.addLast(new SensorhubClientHandler()); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java deleted file mode 100644 index 8121d9e..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.pojo.Msg; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientHandler - */ -@Slf4j -@Service -public class SensorhubClientHandler extends SimpleChannelInboundHandler { - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { - Channel incoming = ctx.channel(); - - if (obj instanceof Msg) { - Msg msg = (Msg) obj; - System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); - } else { - System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); - } - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { -// Msg msg = new Msg(); -// msg.setPreamble("A3"); -// msg.setVersion("V2.0"); -// String tagList = "hello world"; -// int byteLeng = tagList.getBytes().length; -// msg.setLeng(byteLeng); -// msg.setDeviceId("122121"); -// msg.setConnType(1); -// msg.setOperateType(3); -// msg.setDeviceType(1); -// msg.setTransControlFlag(1); -// msg.setDestAddr("111111"); -// msg.setSeq(1); -// msg.setTagList(tagList); -// System.out.println("client发送msg:"); -// System.out.println(JSON.toJSONString(msg)); -// ctx.writeAndFlush(msg); - log.info("连接成功"); - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java deleted file mode 100644 index 662ca3f..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; - -import java.util.List; - -public class AbstractBeforeProccessCodec extends MessageToMessageDecoder { - - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - } -} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java new file mode 100644 index 0000000..5c1c6f2 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java @@ -0,0 +1,29 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.casic.missiles.pojo.Msg; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubServerHandler + */ +@Service +public class SensorhubServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + System.out.println("Client->Server:" + obj.toString()); + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Client->Server:" + JSON.toJSONString(msg)); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java deleted file mode 100644 index 528dafc..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.casic.missiles.server; - -import com.casic.missiles.autoconfig.SensorhubProperties; -import com.casic.missiles.server.handler.SensorhubServerChannelInitialHandler; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.PreDestroy; - -/** - * SensorhubServer netty服务端 - */ -@Slf4j -@Service -public class SensorhubServer { - - /** - * sensorhub默认端口 - */ - public static int DEFAULT_PORT = 7091; - - // 多线程事件循环器 - EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss - EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker - - /** - * sensorhub属性参数 - */ - @Autowired - private SensorhubProperties sensorhubProperties; - @Autowired - private SensorhubServerChannelInitialHandler serverChannelInitialHandler; - - public SensorhubServer(SensorhubProperties sensorhubProperties) { - this.sensorhubProperties = sensorhubProperties; - } - - /** - * 获取sensorhub实例 - * - * @param sensorhubProperties - * @throws Exception - */ - public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { - SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); - sensorhubServer.startServer(); - return sensorhubServer; - } - - /** - * 启动sensorhub服务 - */ - public void startServer() { - new Thread(new Runnable() { - @Override - public void run() { - Integer port = sensorhubProperties.getPort(); - if (port == null) { - log.info("sensorhub服务端口不能为空"); - port = DEFAULT_PORT; - } - try { - // 启动NIO服务的引导程序类 - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) // 设置EventLoopGroup - .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 - .childHandler(serverChannelInitialHandler) // 指定ChannelHandler - .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 - .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 - // 绑定端口,开始接收进来的连接 - ChannelFuture f = b.bind(port).sync(); - log.info("sensorhub已启动,端口:" + port); - // 等待服务器 socket 关闭 。 - f.channel().closeFuture().sync(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - //优雅的关闭 - workerGroup.shutdownGracefully(); - bossGroup.shutdownGracefully(); - } - } - }).start(); - } - - @PreDestroy - public void destroy() { - this.bossGroup.shutdownGracefully(); - this.workerGroup.shutdownGracefully(); - log.info("关闭Netty"); - } - - - public static void main(String[] args) throws Exception { - SensorhubServer server = new SensorhubServer(new SensorhubProperties()); - server.startServer(); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java deleted file mode 100644 index 4346058..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.casic.missiles.server.client; - -import com.casic.missiles.server.client.handler.SensorhubClientChannelInitialHandler; -import com.casic.missiles.pojo.Msg; -import com.casic.missiles.utils.MsgUtil; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClient 客户端 - */ -@Slf4j -@Service -public final class SensorhubClient { - - public static void main(String[] args) throws Exception { - String hostName = "localhost"; - int portNumber = Integer.parseInt("7091"); - - // 配置客户端 - EventLoopGroup group = new NioEventLoopGroup(); - try { - Bootstrap b = new Bootstrap(); - b.group(group) - .channel(NioSocketChannel.class) - .option(ChannelOption.TCP_NODELAY, true) - .handler(new SensorhubClientChannelInitialHandler()); - - // 连接到服务器 - ChannelFuture f = b.connect(hostName, portNumber).sync(); - - Channel channel = f.channel(); - channel.writeAndFlush(MsgUtil.getMsg()); - Msg msg = MsgUtil.getMsg(); - msg.setTransControlFlag(1); - channel.writeAndFlush(msg); -// ByteBuffer writeBuffer = ByteBuffer.allocate(32); -// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { -// String userInput; -// while ((userInput = stdIn.readLine()) != null) { -// writeBuffer.put(userInput.getBytes()); -// writeBuffer.flip(); -// writeBuffer.rewind(); -// -// // 转为ByteBuf -// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); -// -// // 写消息到管道 -// channel.writeAndFlush(buf); -// -// // 清理缓冲区 -// writeBuffer.clear(); -// } -// } catch (UnknownHostException e) { -// System.err.println("不明主机,主机名为: " + hostName); -// System.exit(1); -// } catch (IOException e) { -// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); -// System.exit(1); -// } - } finally { - // 优雅的关闭 - group.shutdownGracefully(); - } - } - - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java deleted file mode 100644 index 0ec6d91..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientChannelInitialHandler - */ -@Service -public class SensorhubClientChannelInitialHandler extends ChannelInitializer { - - @Override - protected void initChannel(SocketChannel socketChannel){ - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new SensorhubDecoder()); -// pipeline.addLast(new SensorhubEncoder()); - pipeline.addLast(new SensorhubClientHandler()); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java deleted file mode 100644 index 8121d9e..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.pojo.Msg; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientHandler - */ -@Slf4j -@Service -public class SensorhubClientHandler extends SimpleChannelInboundHandler { - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { - Channel incoming = ctx.channel(); - - if (obj instanceof Msg) { - Msg msg = (Msg) obj; - System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); - } else { - System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); - } - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { -// Msg msg = new Msg(); -// msg.setPreamble("A3"); -// msg.setVersion("V2.0"); -// String tagList = "hello world"; -// int byteLeng = tagList.getBytes().length; -// msg.setLeng(byteLeng); -// msg.setDeviceId("122121"); -// msg.setConnType(1); -// msg.setOperateType(3); -// msg.setDeviceType(1); -// msg.setTransControlFlag(1); -// msg.setDestAddr("111111"); -// msg.setSeq(1); -// msg.setTagList(tagList); -// System.out.println("client发送msg:"); -// System.out.println(JSON.toJSONString(msg)); -// ctx.writeAndFlush(msg); - log.info("连接成功"); - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java deleted file mode 100644 index 662ca3f..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; - -import java.util.List; - -public class AbstractBeforeProccessCodec extends MessageToMessageDecoder { - - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java deleted file mode 100644 index f63ee53..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.base64.Base64; -import io.netty.handler.codec.base64.Base64Dialect; -import io.netty.util.internal.ObjectUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.nio.charset.Charset; -import java.util.List; - -/** - * @description: 将从接口取到的数据编码 - * @author: cz - * @create: 2023-05-04 15:15 - **/ -@Slf4j -@Service -public class AepBeforeProccessCodec extends AbstractBeforeProccessCodec { - private final Base64Dialect dialect; - - public AepBeforeProccessCodec() { - this(Base64Dialect.STANDARD); - } - - public AepBeforeProccessCodec(Base64Dialect dialect) { - this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); - } - - //执行nb平台前的协议解析 预处理 - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - //aep平台处理 - if (msg.toString(Charset.defaultCharset()).contains("aep")) { - String httpContent = msg.toString(Charset.defaultCharset()); - log.info(" String : " + msg.toString(Charset.defaultCharset())); - String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); - String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); - log.info("----------------------------------" + values); - ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); - bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); - out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); - } - } - -} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java new file mode 100644 index 0000000..5c1c6f2 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java @@ -0,0 +1,29 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.casic.missiles.pojo.Msg; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubServerHandler + */ +@Service +public class SensorhubServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + System.out.println("Client->Server:" + obj.toString()); + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Client->Server:" + JSON.toJSONString(msg)); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java deleted file mode 100644 index 528dafc..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.casic.missiles.server; - -import com.casic.missiles.autoconfig.SensorhubProperties; -import com.casic.missiles.server.handler.SensorhubServerChannelInitialHandler; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.PreDestroy; - -/** - * SensorhubServer netty服务端 - */ -@Slf4j -@Service -public class SensorhubServer { - - /** - * sensorhub默认端口 - */ - public static int DEFAULT_PORT = 7091; - - // 多线程事件循环器 - EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss - EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker - - /** - * sensorhub属性参数 - */ - @Autowired - private SensorhubProperties sensorhubProperties; - @Autowired - private SensorhubServerChannelInitialHandler serverChannelInitialHandler; - - public SensorhubServer(SensorhubProperties sensorhubProperties) { - this.sensorhubProperties = sensorhubProperties; - } - - /** - * 获取sensorhub实例 - * - * @param sensorhubProperties - * @throws Exception - */ - public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { - SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); - sensorhubServer.startServer(); - return sensorhubServer; - } - - /** - * 启动sensorhub服务 - */ - public void startServer() { - new Thread(new Runnable() { - @Override - public void run() { - Integer port = sensorhubProperties.getPort(); - if (port == null) { - log.info("sensorhub服务端口不能为空"); - port = DEFAULT_PORT; - } - try { - // 启动NIO服务的引导程序类 - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) // 设置EventLoopGroup - .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 - .childHandler(serverChannelInitialHandler) // 指定ChannelHandler - .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 - .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 - // 绑定端口,开始接收进来的连接 - ChannelFuture f = b.bind(port).sync(); - log.info("sensorhub已启动,端口:" + port); - // 等待服务器 socket 关闭 。 - f.channel().closeFuture().sync(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - //优雅的关闭 - workerGroup.shutdownGracefully(); - bossGroup.shutdownGracefully(); - } - } - }).start(); - } - - @PreDestroy - public void destroy() { - this.bossGroup.shutdownGracefully(); - this.workerGroup.shutdownGracefully(); - log.info("关闭Netty"); - } - - - public static void main(String[] args) throws Exception { - SensorhubServer server = new SensorhubServer(new SensorhubProperties()); - server.startServer(); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java deleted file mode 100644 index 4346058..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.casic.missiles.server.client; - -import com.casic.missiles.server.client.handler.SensorhubClientChannelInitialHandler; -import com.casic.missiles.pojo.Msg; -import com.casic.missiles.utils.MsgUtil; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClient 客户端 - */ -@Slf4j -@Service -public final class SensorhubClient { - - public static void main(String[] args) throws Exception { - String hostName = "localhost"; - int portNumber = Integer.parseInt("7091"); - - // 配置客户端 - EventLoopGroup group = new NioEventLoopGroup(); - try { - Bootstrap b = new Bootstrap(); - b.group(group) - .channel(NioSocketChannel.class) - .option(ChannelOption.TCP_NODELAY, true) - .handler(new SensorhubClientChannelInitialHandler()); - - // 连接到服务器 - ChannelFuture f = b.connect(hostName, portNumber).sync(); - - Channel channel = f.channel(); - channel.writeAndFlush(MsgUtil.getMsg()); - Msg msg = MsgUtil.getMsg(); - msg.setTransControlFlag(1); - channel.writeAndFlush(msg); -// ByteBuffer writeBuffer = ByteBuffer.allocate(32); -// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { -// String userInput; -// while ((userInput = stdIn.readLine()) != null) { -// writeBuffer.put(userInput.getBytes()); -// writeBuffer.flip(); -// writeBuffer.rewind(); -// -// // 转为ByteBuf -// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); -// -// // 写消息到管道 -// channel.writeAndFlush(buf); -// -// // 清理缓冲区 -// writeBuffer.clear(); -// } -// } catch (UnknownHostException e) { -// System.err.println("不明主机,主机名为: " + hostName); -// System.exit(1); -// } catch (IOException e) { -// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); -// System.exit(1); -// } - } finally { - // 优雅的关闭 - group.shutdownGracefully(); - } - } - - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java deleted file mode 100644 index 0ec6d91..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientChannelInitialHandler - */ -@Service -public class SensorhubClientChannelInitialHandler extends ChannelInitializer { - - @Override - protected void initChannel(SocketChannel socketChannel){ - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new SensorhubDecoder()); -// pipeline.addLast(new SensorhubEncoder()); - pipeline.addLast(new SensorhubClientHandler()); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java deleted file mode 100644 index 8121d9e..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.pojo.Msg; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientHandler - */ -@Slf4j -@Service -public class SensorhubClientHandler extends SimpleChannelInboundHandler { - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { - Channel incoming = ctx.channel(); - - if (obj instanceof Msg) { - Msg msg = (Msg) obj; - System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); - } else { - System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); - } - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { -// Msg msg = new Msg(); -// msg.setPreamble("A3"); -// msg.setVersion("V2.0"); -// String tagList = "hello world"; -// int byteLeng = tagList.getBytes().length; -// msg.setLeng(byteLeng); -// msg.setDeviceId("122121"); -// msg.setConnType(1); -// msg.setOperateType(3); -// msg.setDeviceType(1); -// msg.setTransControlFlag(1); -// msg.setDestAddr("111111"); -// msg.setSeq(1); -// msg.setTagList(tagList); -// System.out.println("client发送msg:"); -// System.out.println(JSON.toJSONString(msg)); -// ctx.writeAndFlush(msg); - log.info("连接成功"); - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java deleted file mode 100644 index 662ca3f..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; - -import java.util.List; - -public class AbstractBeforeProccessCodec extends MessageToMessageDecoder { - - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java deleted file mode 100644 index f63ee53..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.base64.Base64; -import io.netty.handler.codec.base64.Base64Dialect; -import io.netty.util.internal.ObjectUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.nio.charset.Charset; -import java.util.List; - -/** - * @description: 将从接口取到的数据编码 - * @author: cz - * @create: 2023-05-04 15:15 - **/ -@Slf4j -@Service -public class AepBeforeProccessCodec extends AbstractBeforeProccessCodec { - private final Base64Dialect dialect; - - public AepBeforeProccessCodec() { - this(Base64Dialect.STANDARD); - } - - public AepBeforeProccessCodec(Base64Dialect dialect) { - this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); - } - - //执行nb平台前的协议解析 预处理 - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - //aep平台处理 - if (msg.toString(Charset.defaultCharset()).contains("aep")) { - String httpContent = msg.toString(Charset.defaultCharset()); - log.info(" String : " + msg.toString(Charset.defaultCharset())); - String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); - String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); - log.info("----------------------------------" + values); - ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); - bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); - out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); - } - } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java deleted file mode 100644 index 987e18a..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageDecoder; - -import java.util.List; - -public class MessageDecoder extends ByteToMessageDecoder { - @Override - protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { - System.out.println(ByteBufUtil.hexDump(byteBuf)); - } -} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java new file mode 100644 index 0000000..5c1c6f2 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java @@ -0,0 +1,29 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.casic.missiles.pojo.Msg; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubServerHandler + */ +@Service +public class SensorhubServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + System.out.println("Client->Server:" + obj.toString()); + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Client->Server:" + JSON.toJSONString(msg)); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java deleted file mode 100644 index 528dafc..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.casic.missiles.server; - -import com.casic.missiles.autoconfig.SensorhubProperties; -import com.casic.missiles.server.handler.SensorhubServerChannelInitialHandler; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.PreDestroy; - -/** - * SensorhubServer netty服务端 - */ -@Slf4j -@Service -public class SensorhubServer { - - /** - * sensorhub默认端口 - */ - public static int DEFAULT_PORT = 7091; - - // 多线程事件循环器 - EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss - EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker - - /** - * sensorhub属性参数 - */ - @Autowired - private SensorhubProperties sensorhubProperties; - @Autowired - private SensorhubServerChannelInitialHandler serverChannelInitialHandler; - - public SensorhubServer(SensorhubProperties sensorhubProperties) { - this.sensorhubProperties = sensorhubProperties; - } - - /** - * 获取sensorhub实例 - * - * @param sensorhubProperties - * @throws Exception - */ - public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { - SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); - sensorhubServer.startServer(); - return sensorhubServer; - } - - /** - * 启动sensorhub服务 - */ - public void startServer() { - new Thread(new Runnable() { - @Override - public void run() { - Integer port = sensorhubProperties.getPort(); - if (port == null) { - log.info("sensorhub服务端口不能为空"); - port = DEFAULT_PORT; - } - try { - // 启动NIO服务的引导程序类 - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) // 设置EventLoopGroup - .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 - .childHandler(serverChannelInitialHandler) // 指定ChannelHandler - .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 - .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 - // 绑定端口,开始接收进来的连接 - ChannelFuture f = b.bind(port).sync(); - log.info("sensorhub已启动,端口:" + port); - // 等待服务器 socket 关闭 。 - f.channel().closeFuture().sync(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - //优雅的关闭 - workerGroup.shutdownGracefully(); - bossGroup.shutdownGracefully(); - } - } - }).start(); - } - - @PreDestroy - public void destroy() { - this.bossGroup.shutdownGracefully(); - this.workerGroup.shutdownGracefully(); - log.info("关闭Netty"); - } - - - public static void main(String[] args) throws Exception { - SensorhubServer server = new SensorhubServer(new SensorhubProperties()); - server.startServer(); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java deleted file mode 100644 index 4346058..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.casic.missiles.server.client; - -import com.casic.missiles.server.client.handler.SensorhubClientChannelInitialHandler; -import com.casic.missiles.pojo.Msg; -import com.casic.missiles.utils.MsgUtil; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClient 客户端 - */ -@Slf4j -@Service -public final class SensorhubClient { - - public static void main(String[] args) throws Exception { - String hostName = "localhost"; - int portNumber = Integer.parseInt("7091"); - - // 配置客户端 - EventLoopGroup group = new NioEventLoopGroup(); - try { - Bootstrap b = new Bootstrap(); - b.group(group) - .channel(NioSocketChannel.class) - .option(ChannelOption.TCP_NODELAY, true) - .handler(new SensorhubClientChannelInitialHandler()); - - // 连接到服务器 - ChannelFuture f = b.connect(hostName, portNumber).sync(); - - Channel channel = f.channel(); - channel.writeAndFlush(MsgUtil.getMsg()); - Msg msg = MsgUtil.getMsg(); - msg.setTransControlFlag(1); - channel.writeAndFlush(msg); -// ByteBuffer writeBuffer = ByteBuffer.allocate(32); -// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { -// String userInput; -// while ((userInput = stdIn.readLine()) != null) { -// writeBuffer.put(userInput.getBytes()); -// writeBuffer.flip(); -// writeBuffer.rewind(); -// -// // 转为ByteBuf -// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); -// -// // 写消息到管道 -// channel.writeAndFlush(buf); -// -// // 清理缓冲区 -// writeBuffer.clear(); -// } -// } catch (UnknownHostException e) { -// System.err.println("不明主机,主机名为: " + hostName); -// System.exit(1); -// } catch (IOException e) { -// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); -// System.exit(1); -// } - } finally { - // 优雅的关闭 - group.shutdownGracefully(); - } - } - - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java deleted file mode 100644 index 0ec6d91..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientChannelInitialHandler - */ -@Service -public class SensorhubClientChannelInitialHandler extends ChannelInitializer { - - @Override - protected void initChannel(SocketChannel socketChannel){ - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new SensorhubDecoder()); -// pipeline.addLast(new SensorhubEncoder()); - pipeline.addLast(new SensorhubClientHandler()); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java deleted file mode 100644 index 8121d9e..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.pojo.Msg; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientHandler - */ -@Slf4j -@Service -public class SensorhubClientHandler extends SimpleChannelInboundHandler { - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { - Channel incoming = ctx.channel(); - - if (obj instanceof Msg) { - Msg msg = (Msg) obj; - System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); - } else { - System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); - } - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { -// Msg msg = new Msg(); -// msg.setPreamble("A3"); -// msg.setVersion("V2.0"); -// String tagList = "hello world"; -// int byteLeng = tagList.getBytes().length; -// msg.setLeng(byteLeng); -// msg.setDeviceId("122121"); -// msg.setConnType(1); -// msg.setOperateType(3); -// msg.setDeviceType(1); -// msg.setTransControlFlag(1); -// msg.setDestAddr("111111"); -// msg.setSeq(1); -// msg.setTagList(tagList); -// System.out.println("client发送msg:"); -// System.out.println(JSON.toJSONString(msg)); -// ctx.writeAndFlush(msg); - log.info("连接成功"); - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java deleted file mode 100644 index 662ca3f..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; - -import java.util.List; - -public class AbstractBeforeProccessCodec extends MessageToMessageDecoder { - - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java deleted file mode 100644 index f63ee53..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.base64.Base64; -import io.netty.handler.codec.base64.Base64Dialect; -import io.netty.util.internal.ObjectUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.nio.charset.Charset; -import java.util.List; - -/** - * @description: 将从接口取到的数据编码 - * @author: cz - * @create: 2023-05-04 15:15 - **/ -@Slf4j -@Service -public class AepBeforeProccessCodec extends AbstractBeforeProccessCodec { - private final Base64Dialect dialect; - - public AepBeforeProccessCodec() { - this(Base64Dialect.STANDARD); - } - - public AepBeforeProccessCodec(Base64Dialect dialect) { - this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); - } - - //执行nb平台前的协议解析 预处理 - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - //aep平台处理 - if (msg.toString(Charset.defaultCharset()).contains("aep")) { - String httpContent = msg.toString(Charset.defaultCharset()); - log.info(" String : " + msg.toString(Charset.defaultCharset())); - String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); - String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); - log.info("----------------------------------" + values); - ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); - bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); - out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); - } - } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java deleted file mode 100644 index 987e18a..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageDecoder; - -import java.util.List; - -public class MessageDecoder extends ByteToMessageDecoder { - @Override - protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { - System.out.println(ByteBufUtil.hexDump(byteBuf)); - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java deleted file mode 100644 index 4df654a..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -/** - * - */ -@Service -public class SensorhubServerChannelInitialHandler extends ChannelInitializer { - - @Autowired - private List proccessCodecList; - - @Override - protected void initChannel(SocketChannel socketChannel) { - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); -// for (int i = 0; i < proccessCodecList.size(); i++) { -// pipeline.addLast(proccessCodecList.get(0)); -// } -// pipeline.addLast(new MessageDecoder()); -// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new LengthFieldPrepender(2)); - pipeline.addLast(new SensorhubServerHandler()); -// //心跳续约 -// pipeline.addLast(this.heartBeatRespHandler); -// pipeline.addLast(this.loginAuthRespHandler); 登录验证 -// pipeline.addLast(this.chatRespHandler); 对话处理器 - } -} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java new file mode 100644 index 0000000..5c1c6f2 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java @@ -0,0 +1,29 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.casic.missiles.pojo.Msg; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubServerHandler + */ +@Service +public class SensorhubServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + System.out.println("Client->Server:" + obj.toString()); + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Client->Server:" + JSON.toJSONString(msg)); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java deleted file mode 100644 index 528dafc..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.casic.missiles.server; - -import com.casic.missiles.autoconfig.SensorhubProperties; -import com.casic.missiles.server.handler.SensorhubServerChannelInitialHandler; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.PreDestroy; - -/** - * SensorhubServer netty服务端 - */ -@Slf4j -@Service -public class SensorhubServer { - - /** - * sensorhub默认端口 - */ - public static int DEFAULT_PORT = 7091; - - // 多线程事件循环器 - EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss - EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker - - /** - * sensorhub属性参数 - */ - @Autowired - private SensorhubProperties sensorhubProperties; - @Autowired - private SensorhubServerChannelInitialHandler serverChannelInitialHandler; - - public SensorhubServer(SensorhubProperties sensorhubProperties) { - this.sensorhubProperties = sensorhubProperties; - } - - /** - * 获取sensorhub实例 - * - * @param sensorhubProperties - * @throws Exception - */ - public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { - SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); - sensorhubServer.startServer(); - return sensorhubServer; - } - - /** - * 启动sensorhub服务 - */ - public void startServer() { - new Thread(new Runnable() { - @Override - public void run() { - Integer port = sensorhubProperties.getPort(); - if (port == null) { - log.info("sensorhub服务端口不能为空"); - port = DEFAULT_PORT; - } - try { - // 启动NIO服务的引导程序类 - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) // 设置EventLoopGroup - .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 - .childHandler(serverChannelInitialHandler) // 指定ChannelHandler - .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 - .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 - // 绑定端口,开始接收进来的连接 - ChannelFuture f = b.bind(port).sync(); - log.info("sensorhub已启动,端口:" + port); - // 等待服务器 socket 关闭 。 - f.channel().closeFuture().sync(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - //优雅的关闭 - workerGroup.shutdownGracefully(); - bossGroup.shutdownGracefully(); - } - } - }).start(); - } - - @PreDestroy - public void destroy() { - this.bossGroup.shutdownGracefully(); - this.workerGroup.shutdownGracefully(); - log.info("关闭Netty"); - } - - - public static void main(String[] args) throws Exception { - SensorhubServer server = new SensorhubServer(new SensorhubProperties()); - server.startServer(); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java deleted file mode 100644 index 4346058..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.casic.missiles.server.client; - -import com.casic.missiles.server.client.handler.SensorhubClientChannelInitialHandler; -import com.casic.missiles.pojo.Msg; -import com.casic.missiles.utils.MsgUtil; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClient 客户端 - */ -@Slf4j -@Service -public final class SensorhubClient { - - public static void main(String[] args) throws Exception { - String hostName = "localhost"; - int portNumber = Integer.parseInt("7091"); - - // 配置客户端 - EventLoopGroup group = new NioEventLoopGroup(); - try { - Bootstrap b = new Bootstrap(); - b.group(group) - .channel(NioSocketChannel.class) - .option(ChannelOption.TCP_NODELAY, true) - .handler(new SensorhubClientChannelInitialHandler()); - - // 连接到服务器 - ChannelFuture f = b.connect(hostName, portNumber).sync(); - - Channel channel = f.channel(); - channel.writeAndFlush(MsgUtil.getMsg()); - Msg msg = MsgUtil.getMsg(); - msg.setTransControlFlag(1); - channel.writeAndFlush(msg); -// ByteBuffer writeBuffer = ByteBuffer.allocate(32); -// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { -// String userInput; -// while ((userInput = stdIn.readLine()) != null) { -// writeBuffer.put(userInput.getBytes()); -// writeBuffer.flip(); -// writeBuffer.rewind(); -// -// // 转为ByteBuf -// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); -// -// // 写消息到管道 -// channel.writeAndFlush(buf); -// -// // 清理缓冲区 -// writeBuffer.clear(); -// } -// } catch (UnknownHostException e) { -// System.err.println("不明主机,主机名为: " + hostName); -// System.exit(1); -// } catch (IOException e) { -// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); -// System.exit(1); -// } - } finally { - // 优雅的关闭 - group.shutdownGracefully(); - } - } - - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java deleted file mode 100644 index 0ec6d91..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientChannelInitialHandler - */ -@Service -public class SensorhubClientChannelInitialHandler extends ChannelInitializer { - - @Override - protected void initChannel(SocketChannel socketChannel){ - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new SensorhubDecoder()); -// pipeline.addLast(new SensorhubEncoder()); - pipeline.addLast(new SensorhubClientHandler()); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java deleted file mode 100644 index 8121d9e..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.pojo.Msg; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientHandler - */ -@Slf4j -@Service -public class SensorhubClientHandler extends SimpleChannelInboundHandler { - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { - Channel incoming = ctx.channel(); - - if (obj instanceof Msg) { - Msg msg = (Msg) obj; - System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); - } else { - System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); - } - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { -// Msg msg = new Msg(); -// msg.setPreamble("A3"); -// msg.setVersion("V2.0"); -// String tagList = "hello world"; -// int byteLeng = tagList.getBytes().length; -// msg.setLeng(byteLeng); -// msg.setDeviceId("122121"); -// msg.setConnType(1); -// msg.setOperateType(3); -// msg.setDeviceType(1); -// msg.setTransControlFlag(1); -// msg.setDestAddr("111111"); -// msg.setSeq(1); -// msg.setTagList(tagList); -// System.out.println("client发送msg:"); -// System.out.println(JSON.toJSONString(msg)); -// ctx.writeAndFlush(msg); - log.info("连接成功"); - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java deleted file mode 100644 index 662ca3f..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; - -import java.util.List; - -public class AbstractBeforeProccessCodec extends MessageToMessageDecoder { - - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java deleted file mode 100644 index f63ee53..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.base64.Base64; -import io.netty.handler.codec.base64.Base64Dialect; -import io.netty.util.internal.ObjectUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.nio.charset.Charset; -import java.util.List; - -/** - * @description: 将从接口取到的数据编码 - * @author: cz - * @create: 2023-05-04 15:15 - **/ -@Slf4j -@Service -public class AepBeforeProccessCodec extends AbstractBeforeProccessCodec { - private final Base64Dialect dialect; - - public AepBeforeProccessCodec() { - this(Base64Dialect.STANDARD); - } - - public AepBeforeProccessCodec(Base64Dialect dialect) { - this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); - } - - //执行nb平台前的协议解析 预处理 - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - //aep平台处理 - if (msg.toString(Charset.defaultCharset()).contains("aep")) { - String httpContent = msg.toString(Charset.defaultCharset()); - log.info(" String : " + msg.toString(Charset.defaultCharset())); - String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); - String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); - log.info("----------------------------------" + values); - ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); - bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); - out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); - } - } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java deleted file mode 100644 index 987e18a..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageDecoder; - -import java.util.List; - -public class MessageDecoder extends ByteToMessageDecoder { - @Override - protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { - System.out.println(ByteBufUtil.hexDump(byteBuf)); - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java deleted file mode 100644 index 4df654a..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -/** - * - */ -@Service -public class SensorhubServerChannelInitialHandler extends ChannelInitializer { - - @Autowired - private List proccessCodecList; - - @Override - protected void initChannel(SocketChannel socketChannel) { - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); -// for (int i = 0; i < proccessCodecList.size(); i++) { -// pipeline.addLast(proccessCodecList.get(0)); -// } -// pipeline.addLast(new MessageDecoder()); -// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new LengthFieldPrepender(2)); - pipeline.addLast(new SensorhubServerHandler()); -// //心跳续约 -// pipeline.addLast(this.heartBeatRespHandler); -// pipeline.addLast(this.loginAuthRespHandler); 登录验证 -// pipeline.addLast(this.chatRespHandler); 对话处理器 - } -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerHandler.java deleted file mode 100644 index 1f37eda..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.casic.missiles.pojo.Msg; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubServerHandler - */ -@Service -public class SensorhubServerHandler extends SimpleChannelInboundHandler { - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { - System.out.println("Client->Server:" + obj.toString()); - if (obj instanceof Msg) { - Msg msg = (Msg) obj; - System.out.println("Client->Server:" + JSON.toJSONString(msg)); - } - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - ctx.flush(); - } - -} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java new file mode 100644 index 0000000..5c1c6f2 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java @@ -0,0 +1,29 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.casic.missiles.pojo.Msg; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubServerHandler + */ +@Service +public class SensorhubServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + System.out.println("Client->Server:" + obj.toString()); + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Client->Server:" + JSON.toJSONString(msg)); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java deleted file mode 100644 index 528dafc..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.casic.missiles.server; - -import com.casic.missiles.autoconfig.SensorhubProperties; -import com.casic.missiles.server.handler.SensorhubServerChannelInitialHandler; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.PreDestroy; - -/** - * SensorhubServer netty服务端 - */ -@Slf4j -@Service -public class SensorhubServer { - - /** - * sensorhub默认端口 - */ - public static int DEFAULT_PORT = 7091; - - // 多线程事件循环器 - EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss - EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker - - /** - * sensorhub属性参数 - */ - @Autowired - private SensorhubProperties sensorhubProperties; - @Autowired - private SensorhubServerChannelInitialHandler serverChannelInitialHandler; - - public SensorhubServer(SensorhubProperties sensorhubProperties) { - this.sensorhubProperties = sensorhubProperties; - } - - /** - * 获取sensorhub实例 - * - * @param sensorhubProperties - * @throws Exception - */ - public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { - SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); - sensorhubServer.startServer(); - return sensorhubServer; - } - - /** - * 启动sensorhub服务 - */ - public void startServer() { - new Thread(new Runnable() { - @Override - public void run() { - Integer port = sensorhubProperties.getPort(); - if (port == null) { - log.info("sensorhub服务端口不能为空"); - port = DEFAULT_PORT; - } - try { - // 启动NIO服务的引导程序类 - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) // 设置EventLoopGroup - .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 - .childHandler(serverChannelInitialHandler) // 指定ChannelHandler - .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 - .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 - // 绑定端口,开始接收进来的连接 - ChannelFuture f = b.bind(port).sync(); - log.info("sensorhub已启动,端口:" + port); - // 等待服务器 socket 关闭 。 - f.channel().closeFuture().sync(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - //优雅的关闭 - workerGroup.shutdownGracefully(); - bossGroup.shutdownGracefully(); - } - } - }).start(); - } - - @PreDestroy - public void destroy() { - this.bossGroup.shutdownGracefully(); - this.workerGroup.shutdownGracefully(); - log.info("关闭Netty"); - } - - - public static void main(String[] args) throws Exception { - SensorhubServer server = new SensorhubServer(new SensorhubProperties()); - server.startServer(); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java deleted file mode 100644 index 4346058..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.casic.missiles.server.client; - -import com.casic.missiles.server.client.handler.SensorhubClientChannelInitialHandler; -import com.casic.missiles.pojo.Msg; -import com.casic.missiles.utils.MsgUtil; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClient 客户端 - */ -@Slf4j -@Service -public final class SensorhubClient { - - public static void main(String[] args) throws Exception { - String hostName = "localhost"; - int portNumber = Integer.parseInt("7091"); - - // 配置客户端 - EventLoopGroup group = new NioEventLoopGroup(); - try { - Bootstrap b = new Bootstrap(); - b.group(group) - .channel(NioSocketChannel.class) - .option(ChannelOption.TCP_NODELAY, true) - .handler(new SensorhubClientChannelInitialHandler()); - - // 连接到服务器 - ChannelFuture f = b.connect(hostName, portNumber).sync(); - - Channel channel = f.channel(); - channel.writeAndFlush(MsgUtil.getMsg()); - Msg msg = MsgUtil.getMsg(); - msg.setTransControlFlag(1); - channel.writeAndFlush(msg); -// ByteBuffer writeBuffer = ByteBuffer.allocate(32); -// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { -// String userInput; -// while ((userInput = stdIn.readLine()) != null) { -// writeBuffer.put(userInput.getBytes()); -// writeBuffer.flip(); -// writeBuffer.rewind(); -// -// // 转为ByteBuf -// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); -// -// // 写消息到管道 -// channel.writeAndFlush(buf); -// -// // 清理缓冲区 -// writeBuffer.clear(); -// } -// } catch (UnknownHostException e) { -// System.err.println("不明主机,主机名为: " + hostName); -// System.exit(1); -// } catch (IOException e) { -// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); -// System.exit(1); -// } - } finally { - // 优雅的关闭 - group.shutdownGracefully(); - } - } - - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java deleted file mode 100644 index 0ec6d91..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientChannelInitialHandler - */ -@Service -public class SensorhubClientChannelInitialHandler extends ChannelInitializer { - - @Override - protected void initChannel(SocketChannel socketChannel){ - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new SensorhubDecoder()); -// pipeline.addLast(new SensorhubEncoder()); - pipeline.addLast(new SensorhubClientHandler()); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java deleted file mode 100644 index 8121d9e..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.pojo.Msg; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientHandler - */ -@Slf4j -@Service -public class SensorhubClientHandler extends SimpleChannelInboundHandler { - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { - Channel incoming = ctx.channel(); - - if (obj instanceof Msg) { - Msg msg = (Msg) obj; - System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); - } else { - System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); - } - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { -// Msg msg = new Msg(); -// msg.setPreamble("A3"); -// msg.setVersion("V2.0"); -// String tagList = "hello world"; -// int byteLeng = tagList.getBytes().length; -// msg.setLeng(byteLeng); -// msg.setDeviceId("122121"); -// msg.setConnType(1); -// msg.setOperateType(3); -// msg.setDeviceType(1); -// msg.setTransControlFlag(1); -// msg.setDestAddr("111111"); -// msg.setSeq(1); -// msg.setTagList(tagList); -// System.out.println("client发送msg:"); -// System.out.println(JSON.toJSONString(msg)); -// ctx.writeAndFlush(msg); - log.info("连接成功"); - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java deleted file mode 100644 index 662ca3f..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; - -import java.util.List; - -public class AbstractBeforeProccessCodec extends MessageToMessageDecoder { - - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java deleted file mode 100644 index f63ee53..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.base64.Base64; -import io.netty.handler.codec.base64.Base64Dialect; -import io.netty.util.internal.ObjectUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.nio.charset.Charset; -import java.util.List; - -/** - * @description: 将从接口取到的数据编码 - * @author: cz - * @create: 2023-05-04 15:15 - **/ -@Slf4j -@Service -public class AepBeforeProccessCodec extends AbstractBeforeProccessCodec { - private final Base64Dialect dialect; - - public AepBeforeProccessCodec() { - this(Base64Dialect.STANDARD); - } - - public AepBeforeProccessCodec(Base64Dialect dialect) { - this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); - } - - //执行nb平台前的协议解析 预处理 - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - //aep平台处理 - if (msg.toString(Charset.defaultCharset()).contains("aep")) { - String httpContent = msg.toString(Charset.defaultCharset()); - log.info(" String : " + msg.toString(Charset.defaultCharset())); - String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); - String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); - log.info("----------------------------------" + values); - ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); - bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); - out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); - } - } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java deleted file mode 100644 index 987e18a..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageDecoder; - -import java.util.List; - -public class MessageDecoder extends ByteToMessageDecoder { - @Override - protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { - System.out.println(ByteBufUtil.hexDump(byteBuf)); - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java deleted file mode 100644 index 4df654a..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -/** - * - */ -@Service -public class SensorhubServerChannelInitialHandler extends ChannelInitializer { - - @Autowired - private List proccessCodecList; - - @Override - protected void initChannel(SocketChannel socketChannel) { - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); -// for (int i = 0; i < proccessCodecList.size(); i++) { -// pipeline.addLast(proccessCodecList.get(0)); -// } -// pipeline.addLast(new MessageDecoder()); -// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new LengthFieldPrepender(2)); - pipeline.addLast(new SensorhubServerHandler()); -// //心跳续约 -// pipeline.addLast(this.heartBeatRespHandler); -// pipeline.addLast(this.loginAuthRespHandler); 登录验证 -// pipeline.addLast(this.chatRespHandler); 对话处理器 - } -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerHandler.java deleted file mode 100644 index 1f37eda..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.casic.missiles.pojo.Msg; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubServerHandler - */ -@Service -public class SensorhubServerHandler extends SimpleChannelInboundHandler { - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { - System.out.println("Client->Server:" + obj.toString()); - if (obj instanceof Msg) { - Msg msg = (Msg) obj; - System.out.println("Client->Server:" + JSON.toJSONString(msg)); - } - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - ctx.flush(); - } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/nbBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/nbBeforeProccessCodec.java deleted file mode 100644 index 9a7a95b..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/nbBeforeProccessCodec.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.base64.Base64; -import io.netty.handler.codec.base64.Base64Dialect; -import io.netty.util.internal.ObjectUtil; -import lombok.extern.slf4j.Slf4j; - -import java.nio.charset.Charset; -import java.util.List; - -@Slf4j -public class nbBeforeProccessCodec extends AbstractBeforeProccessCodec{ - - private final Base64Dialect dialect; - - public nbBeforeProccessCodec() { - this(Base64Dialect.STANDARD); - } - - public nbBeforeProccessCodec(Base64Dialect dialect) { - this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); - } - - //执行nb平台前的协议解析 预处理 - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out){ - //aep平台处理 - if (msg.toString(Charset.defaultCharset()).contains("aep")) { - String httpContent = msg.toString(Charset.defaultCharset()); - log.info(" String : " + msg.toString(Charset.defaultCharset())); - String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); - String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); - log.info("----------------------------------" + values); - ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); - bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); - out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); - } - } - -} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java new file mode 100644 index 0000000..5c1c6f2 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java @@ -0,0 +1,29 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.casic.missiles.pojo.Msg; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubServerHandler + */ +@Service +public class SensorhubServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + System.out.println("Client->Server:" + obj.toString()); + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Client->Server:" + JSON.toJSONString(msg)); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java deleted file mode 100644 index 528dafc..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.casic.missiles.server; - -import com.casic.missiles.autoconfig.SensorhubProperties; -import com.casic.missiles.server.handler.SensorhubServerChannelInitialHandler; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.PreDestroy; - -/** - * SensorhubServer netty服务端 - */ -@Slf4j -@Service -public class SensorhubServer { - - /** - * sensorhub默认端口 - */ - public static int DEFAULT_PORT = 7091; - - // 多线程事件循环器 - EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss - EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker - - /** - * sensorhub属性参数 - */ - @Autowired - private SensorhubProperties sensorhubProperties; - @Autowired - private SensorhubServerChannelInitialHandler serverChannelInitialHandler; - - public SensorhubServer(SensorhubProperties sensorhubProperties) { - this.sensorhubProperties = sensorhubProperties; - } - - /** - * 获取sensorhub实例 - * - * @param sensorhubProperties - * @throws Exception - */ - public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { - SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); - sensorhubServer.startServer(); - return sensorhubServer; - } - - /** - * 启动sensorhub服务 - */ - public void startServer() { - new Thread(new Runnable() { - @Override - public void run() { - Integer port = sensorhubProperties.getPort(); - if (port == null) { - log.info("sensorhub服务端口不能为空"); - port = DEFAULT_PORT; - } - try { - // 启动NIO服务的引导程序类 - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) // 设置EventLoopGroup - .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 - .childHandler(serverChannelInitialHandler) // 指定ChannelHandler - .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 - .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 - // 绑定端口,开始接收进来的连接 - ChannelFuture f = b.bind(port).sync(); - log.info("sensorhub已启动,端口:" + port); - // 等待服务器 socket 关闭 。 - f.channel().closeFuture().sync(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - //优雅的关闭 - workerGroup.shutdownGracefully(); - bossGroup.shutdownGracefully(); - } - } - }).start(); - } - - @PreDestroy - public void destroy() { - this.bossGroup.shutdownGracefully(); - this.workerGroup.shutdownGracefully(); - log.info("关闭Netty"); - } - - - public static void main(String[] args) throws Exception { - SensorhubServer server = new SensorhubServer(new SensorhubProperties()); - server.startServer(); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java deleted file mode 100644 index 4346058..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.casic.missiles.server.client; - -import com.casic.missiles.server.client.handler.SensorhubClientChannelInitialHandler; -import com.casic.missiles.pojo.Msg; -import com.casic.missiles.utils.MsgUtil; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClient 客户端 - */ -@Slf4j -@Service -public final class SensorhubClient { - - public static void main(String[] args) throws Exception { - String hostName = "localhost"; - int portNumber = Integer.parseInt("7091"); - - // 配置客户端 - EventLoopGroup group = new NioEventLoopGroup(); - try { - Bootstrap b = new Bootstrap(); - b.group(group) - .channel(NioSocketChannel.class) - .option(ChannelOption.TCP_NODELAY, true) - .handler(new SensorhubClientChannelInitialHandler()); - - // 连接到服务器 - ChannelFuture f = b.connect(hostName, portNumber).sync(); - - Channel channel = f.channel(); - channel.writeAndFlush(MsgUtil.getMsg()); - Msg msg = MsgUtil.getMsg(); - msg.setTransControlFlag(1); - channel.writeAndFlush(msg); -// ByteBuffer writeBuffer = ByteBuffer.allocate(32); -// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { -// String userInput; -// while ((userInput = stdIn.readLine()) != null) { -// writeBuffer.put(userInput.getBytes()); -// writeBuffer.flip(); -// writeBuffer.rewind(); -// -// // 转为ByteBuf -// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); -// -// // 写消息到管道 -// channel.writeAndFlush(buf); -// -// // 清理缓冲区 -// writeBuffer.clear(); -// } -// } catch (UnknownHostException e) { -// System.err.println("不明主机,主机名为: " + hostName); -// System.exit(1); -// } catch (IOException e) { -// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); -// System.exit(1); -// } - } finally { - // 优雅的关闭 - group.shutdownGracefully(); - } - } - - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java deleted file mode 100644 index 0ec6d91..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientChannelInitialHandler - */ -@Service -public class SensorhubClientChannelInitialHandler extends ChannelInitializer { - - @Override - protected void initChannel(SocketChannel socketChannel){ - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new SensorhubDecoder()); -// pipeline.addLast(new SensorhubEncoder()); - pipeline.addLast(new SensorhubClientHandler()); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java deleted file mode 100644 index 8121d9e..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.pojo.Msg; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientHandler - */ -@Slf4j -@Service -public class SensorhubClientHandler extends SimpleChannelInboundHandler { - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { - Channel incoming = ctx.channel(); - - if (obj instanceof Msg) { - Msg msg = (Msg) obj; - System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); - } else { - System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); - } - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { -// Msg msg = new Msg(); -// msg.setPreamble("A3"); -// msg.setVersion("V2.0"); -// String tagList = "hello world"; -// int byteLeng = tagList.getBytes().length; -// msg.setLeng(byteLeng); -// msg.setDeviceId("122121"); -// msg.setConnType(1); -// msg.setOperateType(3); -// msg.setDeviceType(1); -// msg.setTransControlFlag(1); -// msg.setDestAddr("111111"); -// msg.setSeq(1); -// msg.setTagList(tagList); -// System.out.println("client发送msg:"); -// System.out.println(JSON.toJSONString(msg)); -// ctx.writeAndFlush(msg); - log.info("连接成功"); - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java deleted file mode 100644 index 662ca3f..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; - -import java.util.List; - -public class AbstractBeforeProccessCodec extends MessageToMessageDecoder { - - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java deleted file mode 100644 index f63ee53..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.base64.Base64; -import io.netty.handler.codec.base64.Base64Dialect; -import io.netty.util.internal.ObjectUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.nio.charset.Charset; -import java.util.List; - -/** - * @description: 将从接口取到的数据编码 - * @author: cz - * @create: 2023-05-04 15:15 - **/ -@Slf4j -@Service -public class AepBeforeProccessCodec extends AbstractBeforeProccessCodec { - private final Base64Dialect dialect; - - public AepBeforeProccessCodec() { - this(Base64Dialect.STANDARD); - } - - public AepBeforeProccessCodec(Base64Dialect dialect) { - this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); - } - - //执行nb平台前的协议解析 预处理 - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - //aep平台处理 - if (msg.toString(Charset.defaultCharset()).contains("aep")) { - String httpContent = msg.toString(Charset.defaultCharset()); - log.info(" String : " + msg.toString(Charset.defaultCharset())); - String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); - String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); - log.info("----------------------------------" + values); - ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); - bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); - out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); - } - } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java deleted file mode 100644 index 987e18a..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageDecoder; - -import java.util.List; - -public class MessageDecoder extends ByteToMessageDecoder { - @Override - protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { - System.out.println(ByteBufUtil.hexDump(byteBuf)); - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java deleted file mode 100644 index 4df654a..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -/** - * - */ -@Service -public class SensorhubServerChannelInitialHandler extends ChannelInitializer { - - @Autowired - private List proccessCodecList; - - @Override - protected void initChannel(SocketChannel socketChannel) { - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); -// for (int i = 0; i < proccessCodecList.size(); i++) { -// pipeline.addLast(proccessCodecList.get(0)); -// } -// pipeline.addLast(new MessageDecoder()); -// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new LengthFieldPrepender(2)); - pipeline.addLast(new SensorhubServerHandler()); -// //心跳续约 -// pipeline.addLast(this.heartBeatRespHandler); -// pipeline.addLast(this.loginAuthRespHandler); 登录验证 -// pipeline.addLast(this.chatRespHandler); 对话处理器 - } -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerHandler.java deleted file mode 100644 index 1f37eda..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.casic.missiles.pojo.Msg; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubServerHandler - */ -@Service -public class SensorhubServerHandler extends SimpleChannelInboundHandler { - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { - System.out.println("Client->Server:" + obj.toString()); - if (obj instanceof Msg) { - Msg msg = (Msg) obj; - System.out.println("Client->Server:" + JSON.toJSONString(msg)); - } - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - ctx.flush(); - } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/nbBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/nbBeforeProccessCodec.java deleted file mode 100644 index 9a7a95b..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/nbBeforeProccessCodec.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.base64.Base64; -import io.netty.handler.codec.base64.Base64Dialect; -import io.netty.util.internal.ObjectUtil; -import lombok.extern.slf4j.Slf4j; - -import java.nio.charset.Charset; -import java.util.List; - -@Slf4j -public class nbBeforeProccessCodec extends AbstractBeforeProccessCodec{ - - private final Base64Dialect dialect; - - public nbBeforeProccessCodec() { - this(Base64Dialect.STANDARD); - } - - public nbBeforeProccessCodec(Base64Dialect dialect) { - this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); - } - - //执行nb平台前的协议解析 预处理 - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out){ - //aep平台处理 - if (msg.toString(Charset.defaultCharset()).contains("aep")) { - String httpContent = msg.toString(Charset.defaultCharset()); - log.info(" String : " + msg.toString(Charset.defaultCharset())); - String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); - String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); - log.info("----------------------------------" + values); - ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); - bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); - out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); - } - } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/utils/ApplicationContextUtil.java b/sensorhub-core/src/main/java/com/casic/missiles/utils/ApplicationContextUtil.java deleted file mode 100644 index 4baa500..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/utils/ApplicationContextUtil.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.casic.missiles.utils; - -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.stereotype.Component; - -/** - * @Auther: cz - * @Date: 2021-10-26 - * 配置类,解决定时任务无法注入的问题 - */ -@Component -public class ApplicationContextUtil implements ApplicationContextAware { - - private static ApplicationContext applicationContext; - - public static ApplicationContext getApplicationContext() { - return applicationContext; - } - - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - ApplicationContextUtil.applicationContext = applicationContext; - - } - - - public static Object getBean(String beanName) { - return applicationContext.getBean(beanName); - } -} diff --git a/pom.xml b/pom.xml index 21fc7b1..96a11a0 100644 --- a/pom.xml +++ b/pom.xml @@ -23,11 +23,9 @@ 2.0.0.alpha 2.0.0.alpha - 2.0.0.alpha 3.5.2 - diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java new file mode 100644 index 0000000..1c22b3f --- /dev/null +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/ApplicationContextUtil.java @@ -0,0 +1,33 @@ +package com.casic.missiles.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Auther: cz + * @Date: 2021-10-26 + * 配置类,解决定时任务无法注入的问题 + */ +@Component +public class ApplicationContextUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + ApplicationContextUtil.applicationContext = applicationContext; + + } + + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } +} diff --git a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java index f15a0cb..828daa0 100644 --- a/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java +++ b/sensorbub-common/src/main/java/com/casic/missiles/util/RedisCommon.java @@ -19,9 +19,9 @@ @Autowired protected RedisTemplate redisTemplate; - @Value("${smartcity.device.redis.invalid-time}") + @Value("${casic.device.redis.invalid-time}") private String invalidTime; - @Value("${smartcity.device.redis.config-prefix}") + @Value("${casic.device.redis.config-prefix}") private String configPrefix; diff --git a/sensorhub-core/pom.xml b/sensorhub-core/pom.xml index df05b97..8cf9520 100644 --- a/sensorhub-core/pom.xml +++ b/sensorhub-core/pom.xml @@ -30,7 +30,6 @@ 2.4.5 - org.projectlombok lombok @@ -78,6 +77,12 @@ jar + + sensorhub + com.casic + 0.0.1-SNAPSHOT + + diff --git a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java index 235529c..24b1e76 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/SensorhubServerApplication.java @@ -1,18 +1,17 @@ package com.casic.missiles; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.ComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; -@ComponentScan({"com.casic.missiles.mapper","com.casic.missiles.autoconfig","com.casic.missiles.utils","com.casic.missiles.factory", - "com.casic.missiles.codec","com.casic.missiles.server"}) -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "com.casic.missiles") +@MapperScan(basePackages = {"com.casic.missiles.**.dao", "com.casic.missiles.**.mapper"}) @EnableTransactionManagement(proxyTargetClass = true) @Slf4j public class SensorhubServerApplication implements CommandLineRunner { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java index 519c062..624ed4f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/autoconfig/SensorhubServerAutoConfiguration.java @@ -1,6 +1,6 @@ package com.casic.missiles.autoconfig; -import com.casic.missiles.server.SensorhubServer; +import com.casic.missiles.netty.SensorhubServer; import io.netty.bootstrap.ServerBootstrap; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java index 96afa7d..87decbc 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/SensorhubCodec.java @@ -7,16 +7,11 @@ import com.casic.missiles.codec.encoder.SensorhubEncoder; import io.netty.channel.CombinedChannelDuplexHandler; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - /** - * SensorhubCodec 编解码器 + * SensorhubCodec 自定义组合协议编解码器(废弃) */ public class SensorhubCodec extends CombinedChannelDuplexHandler { + public SensorhubCodec() { super(new SensorhubDecoder(), new SensorhubEncoder()); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java index cf24b39..e90fab7 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/SensorhubDecoder.java @@ -1,7 +1,7 @@ package com.casic.missiles.codec.decoder; import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.Msg; import com.casic.missiles.enums.FrameAttributeEnums; import com.casic.missiles.enums.FrameStructEnum; @@ -29,9 +29,11 @@ @Override protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List list) throws Exception { // 可读长度必须大于帧的最小长度 - if (buffer.readableBytes() >= MIN_FRAME_LEN){ - // 记录包头开始的index + if (buffer.readableBytes() >= MIN_FRAME_LEN) { + System.out.println(ByteBufUtil.hexDump(buffer)); + //这里可以增加一些前置处理,例如判断拆包合包等网络流的操作 ProtocolSelector protocolSelector = (ProtocolSelector) ApplicationContextUtil.getBean("defaultProtocolSelector"); + // 记录包头开始的index Boolean protocolFlag = protocolSelector.doParseProtocol(buffer); } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java index bab1b46..aeeea2f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/processor/GeneralProcessor.java @@ -7,7 +7,7 @@ import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; import com.casic.missiles.pojo.DatagramEventConfig; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.ProtocolConfig; import com.casic.missiles.pojo.RuleConfig; @@ -38,7 +38,8 @@ * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 */ - public boolean codeGenerator(ByteBuf buffer, ProtocolConfig protocolConfig) { + @Deprecated + public boolean parseWholeDatagram(ByteBuf buffer, ProtocolConfig protocolConfig) { try { String protocolId = String.valueOf(protocolConfig.getId()); //统一固定字段解析 @@ -54,9 +55,9 @@ //解析业务字段 Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText,protocolId); //构建发送解析任务 - Map senderDataMap = dataBuilder(datagramEventConfig, bizDataMap, protocolId); - - dataSender(datagramEventConfig, senderDataMap, protocolId); + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); return true; } catch (Exception ex) { log.debug("选定流程出现异常,异常数据报文内容{},协议内容{},异常信息为{}", @@ -80,15 +81,14 @@ } //数据发送 - private void dataSender(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); } //数据构建 - private Map dataBuilder(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { - DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getDataBuilderBean()); + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { //加上固定字段的数据 bizDataMap.putAll(getFixedField(protocolId)); return bizDataMap; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java index b5b5857..80ec65c 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/ByteMergeProvider.java @@ -25,7 +25,7 @@ public String resolveByteMerge(List valueList, String ruletypeId, String vaildRange) { String values = ""; RuleEvaluator fieldRuleEngine = new RuleEvaluator(); - Map vaildMap = getVaildRangeMap(vaildRange); + Map vaildMap = getValidRangeMap(vaildRange); try { fieldRuleEngine = fieldRuleEngineMapper.selectById(ruletypeId); if (ObjectUtil.isEmpty(fieldRuleEngine)) { @@ -45,7 +45,7 @@ } } - private Map getVaildRangeMap(String vaildRange) { + private Map getValidRangeMap(String vaildRange) { String[] range = vaildRange.split(","); Map vaildMap = new HashMap(); for (int i = 0; i < range.length; i++) { diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java index 3524fbb..9b95b9f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/decoder/resolver/FieldResolverManger.java @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.casic.missiles.pojo.FieldConfig; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.ByteResolverParam; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -30,22 +30,24 @@ //1、字段截取 => 2、简单的字节解析和复杂的字节解析 public Object filedParserManger(ByteBuf byteBuf, FieldConfig fieldConfig, Integer maxFixedPosition) { Integer orignPosition = Integer.valueOf(fieldConfig.getOrignPosition()); + //最大固定位置不为空, if (!ObjectUtil.isEmpty(maxFixedPosition)) { orignPosition -= maxFixedPosition; } Object fieldValue = 0; + //待优化 if (fieldConfig.getOffsetLength() == 1 || fieldConfig.getOffsetUnit().equals("bit")) { fieldValue = bitToResolver(byteBuf, fieldConfig); } else { ByteBuf fieldBytes = byteBuf.slice(orignPosition, fieldConfig.getOffsetLength()); - fieldValue = fieldsResolveManger(fieldBytes, fieldConfig.getRuleJson()); + fieldValue = parsingFields(fieldBytes, fieldConfig.getRuleJson()); } return fieldValue; } //存在rule_json走自定义的规则设置,没有则支持默认配置的规则设置, //目前默认配置的规则设置暂不支持配置化,由实现完成 - private Object fieldsResolveManger(ByteBuf byteBuf, String ruleJson) { + private Object parsingFields(ByteBuf byteBuf, String ruleJson) { Object fieldsResolveValue = null; List ruleMapList = JSONArray.parseArray(ruleJson, Map.class); if (ObjectUtil.isEmpty(ruleMapList)) { @@ -112,7 +114,7 @@ } System.out.println(JSON.toJSON(customizeResolveValue)); return customizeResolveValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("自定义字段解析byte位出现异常,解析规则内容为{},异常信息为{}", JSONObject.toJSON(ruleMapList), ex.getMessage()); return null; } @@ -162,7 +164,7 @@ } System.out.println(JSON.toJSON(fieldValue)); return fieldValue; - } catch (Exception ex) { + } catch (RuntimeException ex) { log.error("字段解析bit位出现异常,解析内容为{},解析规则内容为{},异常信息为{}", fieldValue, JSONObject.toJSON(fieldConfig), ex.getMessage()); return null; } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java index da63217..5dfe6dd 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/CommandDelivery.java @@ -3,7 +3,7 @@ import cn.hutool.core.util.ObjectUtil; import com.casic.missiles.codec.decoder.safe.SafeStrategy; import com.casic.missiles.codec.encoder.delivery.service.ComandeEventService; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.mapper.dao.FieldConfigDao; import com.casic.missiles.pojo.FieldConfig; import io.netty.buffer.ByteBuf; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java index 0deef2e..a7c0459 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/codec/encoder/delivery/FieldDecoratorManger.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson.JSONArray; import com.casic.missiles.codec.encoder.delivery.decorator.ByteDecorator; -import com.casic.missiles.utils.ApplicationContextUtil; +import com.casic.missiles.util.ApplicationContextUtil; import com.casic.missiles.pojo.RuleDict; import com.casic.missiles.mapper.dao.RuleDictDao; import com.casic.missiles.pojo.NodeDecoratorParm; diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java index 8ef70d8..b066f10 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/DatagramFactory.java @@ -6,7 +6,10 @@ import java.util.List; /** - * 对基本配置进行缓存,同时保证数据的使用便捷性 + * 数据库访问优化(暂时未做) + *

+ * 1、初始化协议解析配置,并存放到处存放缓存,对协议基本配置进行管理 + * 2、其中流程中所有的配置都经过此类进行管理,进行调用获取,增强解析速度 */ public interface DatagramFactory { @@ -26,8 +29,9 @@ public List filer(); /** - * 保证数据的唯一性选择器 + * 保证数据的唯一性选择器 */ public List selectOne(); + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java index c107266..3c27f94 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/FrameStructMatcher.java @@ -3,8 +3,14 @@ import com.casic.missiles.pojo.ProtocolConfig; import io.netty.buffer.ByteBuf; +/** + * 分析匹配情况 + * 1、匹配成功,直接返回帧结构,截取完整的数据,可以进行下次匹配。 + * 2、匹配不成功,有后续帧,可以进行下次匹配。 + * 3、匹配不成功,无后续帧,可以进行丢弃。 + */ public interface FrameStructMatcher{ - Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig); + ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig); } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java new file mode 100644 index 0000000..88e00c0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/GenericProtocolParser.java @@ -0,0 +1,141 @@ +package com.casic.missiles.factory; + +import com.casic.missiles.codec.decoder.processor.ProcessorSelector; +import com.casic.missiles.codec.decoder.resolver.FieldParser; +import com.casic.missiles.codec.decoder.rule.RulerProvider; +import com.casic.missiles.codec.decoder.safe.SafeStrategy; +import com.casic.missiles.codec.decoder.sender.DataSubscribeProvider; +import com.casic.missiles.mapper.dao.FieldConfigDao; +import com.casic.missiles.pojo.DatagramEventConfig; +import com.casic.missiles.pojo.FieldConfig; +import com.casic.missiles.pojo.ProtocolConfig; +import com.casic.missiles.pojo.RuleConfig; +import com.casic.missiles.util.ApplicationContextUtil; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("defaultProtocolSelector") +@Slf4j +@AllArgsConstructor +public class GenericProtocolParser implements ProtocolSelector { + + private final LeadingCodeMatcher leadingCodeMatcher; + private final List frameStructDispenserList; + private final FieldConfigDao fieldConfigDao; + private final ProcessorSelector processorSelector; + private final RulerProvider rulerProvider; + private final FieldParser fieldParser; + + // 匹配首字母前导码=> 帧结构匹配前导码=> + // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 + // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 + @Override + public Boolean doParseProtocol(ByteBuf byteBuf) { + String protocolContent = ByteBufUtil.hexDump(byteBuf); + //匹配前导码 + List preCodeConfigs = leadingCodeMatcher.matchLeadingCode(protocolContent); + //如果匹配不到前导码,则重置byteByf,判断是否是二次拆包发送,进行再次匹配 + if (preCodeConfigs.size() == 0) { + return rematch(byteBuf,protocolContent); + } + //暂时先取第一个 + ProtocolConfig protocolConfig = preCodeConfigs.get(0); + ByteBuf wholeDatagramByte = null; + //通过匹配帧结构获取完整的数据包 + for (FrameStructMatcher frameStructMatcher : frameStructDispenserList) { + //帧结构该协议,经过帧结构判断选定帧协议完整的数据报文 + if ((wholeDatagramByte = frameStructMatcher.getWholeDatagram(byteBuf, preCodeConfigs.get(0))) != null) { + break; + } + } + //没有匹配成功 + if (wholeDatagramByte == null) { + return false; + } + /** + * 统一固定字段解析=>进行规则的查询的判断 + * 计算固定字段业务值及对应管理=> 规则解析,规则循环匹配 =>选取规则对应的流程=>选定业务字段内容=>执行加密/解密=> 选定业务数据包内容 + * =>业务字段解析=> 数据验证=>数据构建=> 数据发送 + */ + String protocolId = String.valueOf(protocolConfig.getId()); + //统一固定字段解析 + Map fixDataMap = fieldParser.fixDataParser(protocolId, wholeDatagramByte); + //规则解析,规则循环匹配 + RuleConfig ruleConfig = rulerProvider.RulerBuilder(fixDataMap, protocolId); + //选取规则对应的流程= + DatagramEventConfig datagramEventConfig = processorSelector.ProcessorProvider(String.valueOf(ruleConfig.getId())); + //选定业务字段内容 + ByteBuf bizDataContent = fieldParser.getDataContent(protocolConfig, wholeDatagramByte); + //密文解析 + String lightText = getSafeDatagram(datagramEventConfig, bizDataContent); + //解析业务字段 + Map bizDataMap = fieldParser.dataParser(ruleConfig, lightText, protocolId); + //构建发送解析任务 + Map senderDataMap = buildStoreData(datagramEventConfig, bizDataMap, protocolId); + //数据发送 + storeData(datagramEventConfig, senderDataMap, protocolId); + return true; + } + + private Boolean rematch(ByteBuf byteBuf,String protocolContent) { + //重置位判断 + byteBuf.resetReaderIndex(); + //判断重置是否前移,如果没有前移,则直接判为匹配失败 + if (protocolContent.equals(ByteBufUtil.hexDump(byteBuf))) { + return false; + } else { + return doParseProtocol(byteBuf); + } + } + + + // 是否有动态bean,没有去设置的bean,有则取之=>bean不为空,进行解密操作,否则返回原文 + private String getSafeDatagram(DatagramEventConfig datagramEventConfig, ByteBuf bizDataContent) { + String safeName = StringUtils.isEmpty(datagramEventConfig.getSafeFieldId()) ? datagramEventConfig.getSafeBean() + : fieldConfigDao.getFieldConfigById(datagramEventConfig.getSafeFieldId()).getFieldName(); + if (!StringUtils.isEmpty(safeName)) { + //需要加密 + SafeStrategy safeStrategy = (SafeStrategy) ApplicationContextUtil.getBean(safeName); + String lightText = ""; +// String lightText = safeStrategy.decryption(bizDataContent.toString(Charset.forName("ISO-8859-1"))); + return lightText; + } + return bizDataContent.toString(Charset.forName("ISO-8859-1")); + } + + //数据发送 + private void storeData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + DataSubscribeProvider dataSubscribeProvider = (DataSubscribeProvider) ApplicationContextUtil.getBean(datagramEventConfig.getSubscribeBean()); + dataSubscribeProvider.dataSenderSubscribe(bizDataMap, protocolId); + + } + + //数据构建 + private Map buildStoreData(DatagramEventConfig datagramEventConfig, Map bizDataMap, String protocolId) { + //加上固定字段的数据 + bizDataMap.putAll(getFixedField(protocolId)); + return bizDataMap; + } + + //获取固定字段 + private Map getFixedField(String protocolId) { + Map fixedDataMap = new HashMap<>(); + List fieldConfigList = fieldConfigDao.getFieldConfigs(protocolId, 1); + fieldConfigList.stream().forEach( + fieldConfig -> { + fixedDataMap.put(fieldConfig.getFieldName(), ""); + } + ); + return fixedDataMap; + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java new file mode 100644 index 0000000..8d3e559 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/LeadingCodeMatcher.java @@ -0,0 +1,38 @@ +package com.casic.missiles.factory; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.casic.missiles.mapper.ProtocolConfigMapper; +import com.casic.missiles.pojo.ProtocolConfig; +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.stream.Collectors; + +@Component +@AllArgsConstructor +public class LeadingCodeMatcher { + + private final ProtocolConfigMapper protocolMapper; + + //** 1、首字母匹配前导码, + // 2、以匹配出的前导码是否在报文中条件进行前导码的匹配二次筛选 + public List matchLeadingCode(String protocolContent){ + List initialConfigs = initialMatch(protocolContent); + List preCodeConfigs = initialConfigs.stream() + .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) + .collect(Collectors.toList()); + return preCodeConfigs; + } + + //初始化匹配前导码内容 + private List initialMatch(String protocolContent) { + String protocolStr = protocolContent.charAt(0) + ""; + QueryWrapper queryWrapper = new QueryWrapper() + .likeRight("pre_fix", protocolStr); + List protocolConfigList = protocolMapper.selectList(queryWrapper); + return protocolConfigList; + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java index d9929bf..55e9f6f 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameLengthMatcher.java @@ -23,27 +23,29 @@ //超过长度 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { String dataGramContent = ByteBufUtil.hexDump(byteBuf); - if (StringUtils.isEmpty(protocolConfig.getUnpackId())&&StringUtils.isEmpty(protocolConfig.getTailStr())) { + if (StringUtils.isEmpty(protocolConfig.getUnpackId()) && StringUtils.isEmpty(protocolConfig.getTailStr())) { Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); if (ObjectUtil.isEmpty(totalLength)) { if (dataGramContent.length() >= totalLength) {//等于长度返回true,超出长度,切断 - this.cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); - return false; + ByteBuf wholeDatagramByte = this.doGetWholeDatagramByte(byteBuf, protocolConfig, totalLength); + return wholeDatagramByte; } else { - return true; + //读的标志位前移舍弃 + byteBuf.markReaderIndex(); + return null; } } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + private ByteBuf doGetWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { byteBuf.readBytes(totalLength); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent = byteBuf.slice(0, totalLength - 1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, totalLength - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java index b4a34ff..60484de 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameMarkMatcher.java @@ -34,7 +34,7 @@ //帧后续标志=>结束,进行帧的重组=>有后续,1、帧移位判别 2、继续接收帧 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig) { + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig UnpackConfig = StringUtils.isEmpty(protocolConfig.getUnpackId()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getUnpackId()); Integer totalLength = fieldParser.getTotalLength(protocolConfig, byteBuf); @@ -45,7 +45,7 @@ //是否存在后续位 if (upback == 1) {//使用esayRule //表示可以截取 - cutOffPackageBuilder(byteBuf, protocolConfig, totalLength); + ByteBuf mergeWholeFrameByte = getWholeDatagramByte(byteBuf, protocolConfig, totalLength); if (byteBuf.hasArray()) { upback = 0; } else { @@ -56,24 +56,22 @@ } } if (upback == 1) { - return true; - } else { - return false; + return null; } } - return true; + return null; } //选取第一个帧,将业务内容和后面部分分开 //计算数据报文-业务内容 - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { - //切割 + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer totalLength) { + //截取完整报文 byteBuf.readBytes(totalLength); ByteBuf byteBufContent = byteBuf.slice(0, byteBuf.readerIndex()); byteBuf.markReaderIndex();//读的标志位前移 //重置 byteBufContent.resetReaderIndex(); - ByteBuf mergeFrameByte = ByteBufAllocator.DEFAULT.buffer(); + ByteBuf mergeWholeFrameByte = ByteBufAllocator.DEFAULT.buffer(); String mergeFrameStr = ""; String tail = ""; System.out.println(ByteBufUtil.hexDump(byteBufContent)); @@ -97,9 +95,9 @@ } } mergeFrameStr += tail; - mergeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); - System.out.println(ByteBufUtil.hexDump(mergeFrameByte)); - generalProcessor.codeGenerator(mergeFrameByte, protocolConfig); + mergeWholeFrameByte.writeBytes(mergeFrameStr.getBytes(Charset.forName("ISO-8859-1"))); + System.out.println(ByteBufUtil.hexDump(mergeWholeFrameByte)); + return mergeWholeFrameByte; } /** diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java index c298d40..df2d119 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/factory/matcher/FrameTailMatcher.java @@ -26,7 +26,7 @@ //结尾标志位后面还有数据怎么办 @Override - public Boolean intactValidator(ByteBuf byteBuf, ProtocolConfig protocolConfig){ + public ByteBuf getWholeDatagram(ByteBuf byteBuf, ProtocolConfig protocolConfig) { FieldConfig tailFieldConfig = StringUtils.isEmpty(protocolConfig.getTailStr()) ? null : fieldConfigDao.getFieldConfigById(protocolConfig.getTailStr()); if (!ObjectUtil.isEmpty(tailFieldConfig)) { @@ -34,21 +34,21 @@ String dataGramContent = ByteBufUtil.hexDump(byteBuf); Boolean tailFlag = ByteBufUtil.hexDump(byteBuf).contains(tailStr); if (!tailFlag) { //使用esayRule - return false; - }else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { - Integer length=dataGramContent.indexOf(tailStr)+tailStr.length(); - cutOffPackageBuilder(byteBuf,protocolConfig,length); - return true; //存在粘包 + return null; + } else if (dataGramContent.indexOf(tailStr) < dataGramContent.length() - tailStr.length()) { + Integer length = dataGramContent.indexOf(tailStr) + tailStr.length(); + ByteBuf wholeDatagramByte = getWholeDatagramByte(byteBuf, protocolConfig, length); + return wholeDatagramByte; //存在粘包 } } - return true; + return null; } - private void cutOffPackageBuilder(ByteBuf byteBuf, ProtocolConfig protocolConfig,Integer length) { + private ByteBuf getWholeDatagramByte(ByteBuf byteBuf, ProtocolConfig protocolConfig, Integer length) { byteBuf.readBytes(length); byteBuf.markReaderIndex();//读的标志位前移 - ByteBuf byteBufContent=byteBuf.slice(0,length-1); - generalProcessor.codeGenerator(byteBufContent, protocolConfig); + ByteBuf wholeDatagramByte = byteBuf.slice(0, length - 1); + return wholeDatagramByte; } } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java b/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java deleted file mode 100644 index cba0681..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/factory/selector/DefaultProtocolSelector.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.casic.missiles.factory.selector; - -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.casic.missiles.factory.FrameStructMatcher; -import com.casic.missiles.factory.ProtocolSelector; -import com.casic.missiles.mapper.ProtocolConfigMapper; -import com.casic.missiles.pojo.ProtocolConfig; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.util.List; -import java.util.stream.Collectors; - -@Service("defaultProtocolSelector") -@Slf4j -public class DefaultProtocolSelector implements ProtocolSelector { - - @Resource - private ProtocolConfigMapper protocolMapper; - @Autowired - List frameStructDispenserList; - - // 匹配首字母前导码=> 帧结构匹配前导码=> - // 1、如果没有该协议,会存在拆包问题,缓存数组重置,经过帧结构判断进行数据分发 - // 2、存在该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - @Override - public Boolean doParseProtocol(ByteBuf byteBuf) { - String protocolContent = ByteBufUtil.hexDump(byteBuf); - - List protocolConfigList = initialMatch(protocolContent); - List protocolFilterList = protocolConfigList.stream() - .filter(protocolConfig -> protocolContent.contains(protocolConfig.getPreFix().toLowerCase())) - .collect(Collectors.toList()); - - //如果不存在前导码,则需要判断是否拆包 - if (protocolFilterList.size() == 0) { - //error - byteBuf.resetReaderIndex();//重置位判断 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } else {//判断拆包、封包 - return frameDispenserManger(byteBuf, protocolFilterList.get(0)); - } - } - - private List initialMatch(String protocolContent) { - String protocolStr = protocolContent.charAt(0) + ""; - QueryWrapper queryWrapper = new QueryWrapper() - .likeLeft("pre_fix", protocolStr); - List protocolConfigList = protocolMapper.selectList(queryWrapper); - return protocolConfigList; - } - - private Boolean frameDispenserManger(ByteBuf byteBuf, ProtocolConfig protocolConfig) { - Boolean frameValidatorFlag = true; - for (int i = 0; i < frameStructDispenserList.size()&&frameValidatorFlag; i++) { - //帧结构判断该协议,经过帧结构判断选定帧协议,进行数据报文的解析 - frameValidatorFlag = frameValidatorFlag && frameStructDispenserList.get(i).intactValidator(byteBuf, protocolConfig); - } - return frameValidatorFlag; - } - -// public void serialEvent(SerialPortEvent event) { -// switch (event.getEventType()) { -// case SerialPortEvent.BI: // 通讯中断 -// case SerialPortEvent.OE: // 溢位错误 -// case SerialPortEvent.FE: // 帧错误 -// case SerialPortEvent.PE: // 奇偶校验错误 -// case SerialPortEvent.CD: // 载波检测 -// case SerialPortEvent.CTS: // 清除发送 -// case SerialPortEvent.DSR: // 数据设备准备好 -// case SerialPortEvent.RI: // 响铃侦测 -// case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 输出缓冲区已清空 -// break; -// case SerialPortEvent.DATA_AVAILABLE: // 有数据到达 -// // 调用读取数据的方法 -// data = this.readFromPort(); -// break; -// default: -// break; -// } -// } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java index 2df07e0..fff28d0 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/listeners/event/DataGramLifeCycleEvent.java @@ -1,9 +1,8 @@ package com.casic.missiles.listeners.event; - +/** + * 观察者监听器 + */ public class DataGramLifeCycleEvent { - - - } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java index 99f0149..597c306 100644 --- a/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java +++ b/sensorhub-core/src/main/java/com/casic/missiles/mapper/FieldConfigMapper.java @@ -4,6 +4,6 @@ import com.casic.missiles.pojo.FieldConfig; import org.apache.ibatis.annotations.Mapper; -@Mapper public interface FieldConfigMapper extends BaseMapper { + } diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java new file mode 100644 index 0000000..1e3e9fb --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/SensorhubServer.java @@ -0,0 +1,106 @@ +package com.casic.missiles.netty; + +import com.casic.missiles.autoconfig.SensorhubProperties; +import com.casic.missiles.netty.handler.SensorhubServerChannelInitialHandler; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; + +/** + * SensorhubServer netty服务端 + */ +@Slf4j +@Service +public class SensorhubServer { + + /** + * sensorhub默认端口 + */ + public static int DEFAULT_PORT = 7091; + + // 多线程事件循环器 + EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss + EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker + + /** + * sensorhub属性参数 + */ + @Autowired + private SensorhubProperties sensorhubProperties; + @Autowired + private SensorhubServerChannelInitialHandler serverChannelInitialHandler; + + public SensorhubServer(SensorhubProperties sensorhubProperties) { + this.sensorhubProperties = sensorhubProperties; + } + + /** + * 获取sensorhub实例 + * + * @param sensorhubProperties + * @throws Exception + */ + public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { + SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); + sensorhubServer.startServer(); + return sensorhubServer; + } + + /** + * 启动sensorhub服务 + */ + public void startServer() { + new Thread(new Runnable() { + @Override + public void run() { + Integer port = sensorhubProperties.getPort(); + if (port == null) { + log.info("sensorhub服务端口不能为空"); + port = DEFAULT_PORT; + } + try { + // 启动NIO服务的引导程序类 + ServerBootstrap b = new ServerBootstrap(); + b.group(bossGroup, workerGroup) // 设置EventLoopGroup + .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 + .childHandler(serverChannelInitialHandler) // 指定ChannelHandler + .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 + .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 + // 绑定端口,开始接收进来的连接 + ChannelFuture f = b.bind(port).sync(); + log.info("sensorhub已启动,端口:" + port); + // 等待服务器 socket 关闭 。 + f.channel().closeFuture().sync(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + //优雅的关闭 + workerGroup.shutdownGracefully(); + bossGroup.shutdownGracefully(); + } + } + }).start(); + } + + @PreDestroy + public void destroy() { + this.bossGroup.shutdownGracefully(); + this.workerGroup.shutdownGracefully(); + log.info("关闭Netty"); + } + + + public static void main(String[] args) throws Exception { + SensorhubServer server = new SensorhubServer(new SensorhubProperties()); + server.startServer(); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java new file mode 100644 index 0000000..eba0311 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/SensorhubClient.java @@ -0,0 +1,75 @@ +package com.casic.missiles.netty.client; + +import com.casic.missiles.netty.client.handler.SensorhubClientChannelInitialHandler; +import com.casic.missiles.pojo.Msg; +import com.casic.missiles.utils.MsgUtil; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.nio.NioSocketChannel; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClient 客户端 + */ +@Slf4j +@Service +public final class SensorhubClient { + + public static void main(String[] args) throws Exception { + String hostName = "localhost"; + int portNumber = Integer.parseInt("7091"); + + // 配置客户端 + EventLoopGroup group = new NioEventLoopGroup(); + try { + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.TCP_NODELAY, true) + .handler(new SensorhubClientChannelInitialHandler()); + + // 连接到服务器 + ChannelFuture f = b.connect(hostName, portNumber).sync(); + + Channel channel = f.channel(); + channel.writeAndFlush(MsgUtil.getMsg()); + Msg msg = MsgUtil.getMsg(); + msg.setTransControlFlag(1); + channel.writeAndFlush(msg); +// ByteBuffer writeBuffer = ByteBuffer.allocate(32); +// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { +// String userInput; +// while ((userInput = stdIn.readLine()) != null) { +// writeBuffer.put(userInput.getBytes()); +// writeBuffer.flip(); +// writeBuffer.rewind(); +// +// // 转为ByteBuf +// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); +// +// // 写消息到管道 +// channel.writeAndFlush(buf); +// +// // 清理缓冲区 +// writeBuffer.clear(); +// } +// } catch (UnknownHostException e) { +// System.err.println("不明主机,主机名为: " + hostName); +// System.exit(1); +// } catch (IOException e) { +// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); +// System.exit(1); +// } + } finally { + // 优雅的关闭 + group.shutdownGracefully(); + } + } + + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java new file mode 100644 index 0000000..9774be0 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientChannelInitialHandler.java @@ -0,0 +1,27 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientChannelInitialHandler + */ +@Service +public class SensorhubClientChannelInitialHandler extends ChannelInitializer { + + @Override + protected void initChannel(SocketChannel socketChannel){ + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + pipeline.addLast("codec", new SensorhubCodec()); +// pipeline.addLast(new SensorhubDecoder()); +// pipeline.addLast(new SensorhubEncoder()); + pipeline.addLast(new SensorhubClientHandler()); + } + +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java new file mode 100644 index 0000000..346f4b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/client/handler/SensorhubClientHandler.java @@ -0,0 +1,50 @@ +package com.casic.missiles.netty.client.handler; + +import com.casic.missiles.pojo.Msg; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * SensorhubClientHandler + */ +@Slf4j +@Service +public class SensorhubClientHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + Channel incoming = ctx.channel(); + + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); + } else { + System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); + } + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { +// Msg msg = new Msg(); +// msg.setPreamble("A3"); +// msg.setVersion("V2.0"); +// String tagList = "hello world"; +// int byteLeng = tagList.getBytes().length; +// msg.setLeng(byteLeng); +// msg.setDeviceId("122121"); +// msg.setConnType(1); +// msg.setOperateType(3); +// msg.setDeviceType(1); +// msg.setTransControlFlag(1); +// msg.setDestAddr("111111"); +// msg.setSeq(1); +// msg.setTagList(tagList); +// System.out.println("client发送msg:"); +// System.out.println(JSON.toJSONString(msg)); +// ctx.writeAndFlush(msg); + log.info("连接成功"); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java new file mode 100644 index 0000000..33042a3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AbstractPreprocessingCodec.java @@ -0,0 +1,14 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; + +import java.util.List; + +public class AbstractPreprocessingCodec extends MessageToMessageDecoder { + + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java new file mode 100644 index 0000000..b1ee6c4 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/AepPreprocessingCodec.java @@ -0,0 +1,51 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.nio.charset.Charset; +import java.util.List; + +/** + * @description: 将从接口取到的数据编码 + * @author: cz + * @create: 2023-05-04 15:15 + **/ +@Slf4j +@Service +public class AepPreprocessingCodec extends AbstractPreprocessingCodec { + private final Base64Dialect dialect; + + public AepPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public AepPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析 预处理 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java new file mode 100644 index 0000000..6e781b3 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/MessageDecoder.java @@ -0,0 +1,15 @@ +package com.casic.missiles.netty.handler; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +public class MessageDecoder extends ByteToMessageDecoder { + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { + System.out.println(ByteBufUtil.hexDump(byteBuf)); + } +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java new file mode 100644 index 0000000..062df5f --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/NbPreprocessingCodec.java @@ -0,0 +1,45 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.base64.Base64; +import io.netty.handler.codec.base64.Base64Dialect; +import io.netty.util.internal.ObjectUtil; +import lombok.extern.slf4j.Slf4j; + +import java.nio.charset.Charset; +import java.util.List; + +@Slf4j +public class NbPreprocessingCodec extends AbstractPreprocessingCodec { + + private final Base64Dialect dialect; + + public NbPreprocessingCodec() { + this(Base64Dialect.STANDARD); + } + + public NbPreprocessingCodec(Base64Dialect dialect) { + this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); + } + + //执行nb平台前的协议解析,预处理base编码 + @Override + public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { + //aep平台处理 + if (msg.toString(Charset.defaultCharset()).contains("aep")) { + String httpContent = msg.toString(Charset.defaultCharset()); + log.info(" String : " + msg.toString(Charset.defaultCharset())); + String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); + String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); + log.info("----------------------------------" + values); + ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); + bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); + out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); + } + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java new file mode 100644 index 0000000..c37d7cc --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerChannelInitialHandler.java @@ -0,0 +1,42 @@ +package com.casic.missiles.netty.handler; + +import com.casic.missiles.codec.SensorhubCodec; +import com.casic.missiles.codec.decoder.SensorhubDecoder; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.socket.SocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * @author cz + * @date 2023-06-05 + */ +@Service +public class SensorhubServerChannelInitialHandler extends ChannelInitializer { + + @Autowired + private List proccessCodecList; + + @Override + protected void initChannel(SocketChannel socketChannel) { + ChannelPipeline pipeline = socketChannel.pipeline(); + pipeline.addLast(new LoggingHandler(LogLevel.INFO)); + for (AbstractPreprocessingCodec abstractPreprocessingCodec : proccessCodecList) { + pipeline.addLast(abstractPreprocessingCodec); + } +// pipeline.addLast(new MessageDecoder()); +// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); +// pipeline.addLast("codec", new SensorhubCodec()); + pipeline.addLast(new SensorhubDecoder()); + pipeline.addLast(new SensorhubServerHandler()); +// 心跳续约 +// pipeline.addLast(this.heartBeatRespHandler); +// pipeline.addLast(this.loginAuthRespHandler); 登录验证 +// pipeline.addLast(this.chatRespHandler); 对话处理器 + } +} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java new file mode 100644 index 0000000..5c1c6f2 --- /dev/null +++ b/sensorhub-core/src/main/java/com/casic/missiles/netty/handler/SensorhubServerHandler.java @@ -0,0 +1,29 @@ +package com.casic.missiles.netty.handler; + +import com.alibaba.fastjson.JSON; +import com.casic.missiles.pojo.Msg; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.springframework.stereotype.Service; + +/** + * SensorhubServerHandler + */ +@Service +public class SensorhubServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { + System.out.println("Client->Server:" + obj.toString()); + if (obj instanceof Msg) { + Msg msg = (Msg) obj; + System.out.println("Client->Server:" + JSON.toJSONString(msg)); + } + } + + @Override + public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + ctx.flush(); + } + +} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java b/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java deleted file mode 100644 index 528dafc..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/SensorhubServer.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.casic.missiles.server; - -import com.casic.missiles.autoconfig.SensorhubProperties; -import com.casic.missiles.server.handler.SensorhubServerChannelInitialHandler; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import javax.annotation.PreDestroy; - -/** - * SensorhubServer netty服务端 - */ -@Slf4j -@Service -public class SensorhubServer { - - /** - * sensorhub默认端口 - */ - public static int DEFAULT_PORT = 7091; - - // 多线程事件循环器 - EventLoopGroup bossGroup = new NioEventLoopGroup(4); // boss - EventLoopGroup workerGroup = new NioEventLoopGroup(32); // worker - - /** - * sensorhub属性参数 - */ - @Autowired - private SensorhubProperties sensorhubProperties; - @Autowired - private SensorhubServerChannelInitialHandler serverChannelInitialHandler; - - public SensorhubServer(SensorhubProperties sensorhubProperties) { - this.sensorhubProperties = sensorhubProperties; - } - - /** - * 获取sensorhub实例 - * - * @param sensorhubProperties - * @throws Exception - */ - public static SensorhubServer getInstance(SensorhubProperties sensorhubProperties) throws Exception { - SensorhubServer sensorhubServer = new SensorhubServer(sensorhubProperties); - sensorhubServer.startServer(); - return sensorhubServer; - } - - /** - * 启动sensorhub服务 - */ - public void startServer() { - new Thread(new Runnable() { - @Override - public void run() { - Integer port = sensorhubProperties.getPort(); - if (port == null) { - log.info("sensorhub服务端口不能为空"); - port = DEFAULT_PORT; - } - try { - // 启动NIO服务的引导程序类 - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) // 设置EventLoopGroup - .channel(NioServerSocketChannel.class) // 指明新的Channel的类型 - .childHandler(serverChannelInitialHandler) // 指定ChannelHandler - .option(ChannelOption.SO_BACKLOG, 1024) // 设置的ServerChannel的一些选项 - .childOption(ChannelOption.SO_KEEPALIVE, true); // 当SO_KEEPALIVE=true的时候,服务端可以探测客户端的连接是否还存活着,如果客户端关闭了,那么服务端的连接可以关闭掉,释放资源 - // 绑定端口,开始接收进来的连接 - ChannelFuture f = b.bind(port).sync(); - log.info("sensorhub已启动,端口:" + port); - // 等待服务器 socket 关闭 。 - f.channel().closeFuture().sync(); - } catch (InterruptedException e) { - e.printStackTrace(); - } finally { - //优雅的关闭 - workerGroup.shutdownGracefully(); - bossGroup.shutdownGracefully(); - } - } - }).start(); - } - - @PreDestroy - public void destroy() { - this.bossGroup.shutdownGracefully(); - this.workerGroup.shutdownGracefully(); - log.info("关闭Netty"); - } - - - public static void main(String[] args) throws Exception { - SensorhubServer server = new SensorhubServer(new SensorhubProperties()); - server.startServer(); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java deleted file mode 100644 index 4346058..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/SensorhubClient.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.casic.missiles.server.client; - -import com.casic.missiles.server.client.handler.SensorhubClientChannelInitialHandler; -import com.casic.missiles.pojo.Msg; -import com.casic.missiles.utils.MsgUtil; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioSocketChannel; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClient 客户端 - */ -@Slf4j -@Service -public final class SensorhubClient { - - public static void main(String[] args) throws Exception { - String hostName = "localhost"; - int portNumber = Integer.parseInt("7091"); - - // 配置客户端 - EventLoopGroup group = new NioEventLoopGroup(); - try { - Bootstrap b = new Bootstrap(); - b.group(group) - .channel(NioSocketChannel.class) - .option(ChannelOption.TCP_NODELAY, true) - .handler(new SensorhubClientChannelInitialHandler()); - - // 连接到服务器 - ChannelFuture f = b.connect(hostName, portNumber).sync(); - - Channel channel = f.channel(); - channel.writeAndFlush(MsgUtil.getMsg()); - Msg msg = MsgUtil.getMsg(); - msg.setTransControlFlag(1); - channel.writeAndFlush(msg); -// ByteBuffer writeBuffer = ByteBuffer.allocate(32); -// try (BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) { -// String userInput; -// while ((userInput = stdIn.readLine()) != null) { -// writeBuffer.put(userInput.getBytes()); -// writeBuffer.flip(); -// writeBuffer.rewind(); -// -// // 转为ByteBuf -// ByteBuf buf = Unpooled.copiedBuffer(writeBuffer); -// -// // 写消息到管道 -// channel.writeAndFlush(buf); -// -// // 清理缓冲区 -// writeBuffer.clear(); -// } -// } catch (UnknownHostException e) { -// System.err.println("不明主机,主机名为: " + hostName); -// System.exit(1); -// } catch (IOException e) { -// System.err.println("不能从主机中获取I/O,主机名为:" + hostName); -// System.exit(1); -// } - } finally { - // 优雅的关闭 - group.shutdownGracefully(); - } - } - - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java deleted file mode 100644 index 0ec6d91..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientChannelInitialHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientChannelInitialHandler - */ -@Service -public class SensorhubClientChannelInitialHandler extends ChannelInitializer { - - @Override - protected void initChannel(SocketChannel socketChannel){ - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new SensorhubDecoder()); -// pipeline.addLast(new SensorhubEncoder()); - pipeline.addLast(new SensorhubClientHandler()); - } - -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java deleted file mode 100644 index 8121d9e..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/client/handler/SensorhubClientHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.casic.missiles.server.client.handler; - -import com.casic.missiles.pojo.Msg; -import io.netty.channel.Channel; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * SensorhubClientHandler - */ -@Slf4j -@Service -public class SensorhubClientHandler extends SimpleChannelInboundHandler { - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { - Channel incoming = ctx.channel(); - - if (obj instanceof Msg) { - Msg msg = (Msg) obj; - System.out.println("Server->Client:" + incoming.remoteAddress() + msg.getTagList()); - } else { - System.out.println("Server->Client:" + incoming.remoteAddress() + obj.toString()); - } - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { -// Msg msg = new Msg(); -// msg.setPreamble("A3"); -// msg.setVersion("V2.0"); -// String tagList = "hello world"; -// int byteLeng = tagList.getBytes().length; -// msg.setLeng(byteLeng); -// msg.setDeviceId("122121"); -// msg.setConnType(1); -// msg.setOperateType(3); -// msg.setDeviceType(1); -// msg.setTransControlFlag(1); -// msg.setDestAddr("111111"); -// msg.setSeq(1); -// msg.setTagList(tagList); -// System.out.println("client发送msg:"); -// System.out.println(JSON.toJSONString(msg)); -// ctx.writeAndFlush(msg); - log.info("连接成功"); - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java deleted file mode 100644 index 662ca3f..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AbstractBeforeProccessCodec.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToMessageDecoder; - -import java.util.List; - -public class AbstractBeforeProccessCodec extends MessageToMessageDecoder { - - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java deleted file mode 100644 index f63ee53..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/AepBeforeProccessCodec.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.base64.Base64; -import io.netty.handler.codec.base64.Base64Dialect; -import io.netty.util.internal.ObjectUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.nio.charset.Charset; -import java.util.List; - -/** - * @description: 将从接口取到的数据编码 - * @author: cz - * @create: 2023-05-04 15:15 - **/ -@Slf4j -@Service -public class AepBeforeProccessCodec extends AbstractBeforeProccessCodec { - private final Base64Dialect dialect; - - public AepBeforeProccessCodec() { - this(Base64Dialect.STANDARD); - } - - public AepBeforeProccessCodec(Base64Dialect dialect) { - this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); - } - - //执行nb平台前的协议解析 预处理 - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) { - //aep平台处理 - if (msg.toString(Charset.defaultCharset()).contains("aep")) { - String httpContent = msg.toString(Charset.defaultCharset()); - log.info(" String : " + msg.toString(Charset.defaultCharset())); - String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); - String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); - log.info("----------------------------------" + values); - ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); - bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); - out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); - } - } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java deleted file mode 100644 index 987e18a..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/MessageDecoder.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.missiles.server.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageDecoder; - -import java.util.List; - -public class MessageDecoder extends ByteToMessageDecoder { - @Override - protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { - System.out.println(ByteBufUtil.hexDump(byteBuf)); - } -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java deleted file mode 100644 index 4df654a..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerChannelInitialHandler.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.casic.missiles.codec.SensorhubCodec; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -/** - * - */ -@Service -public class SensorhubServerChannelInitialHandler extends ChannelInitializer { - - @Autowired - private List proccessCodecList; - - @Override - protected void initChannel(SocketChannel socketChannel) { - ChannelPipeline pipeline = socketChannel.pipeline(); - pipeline.addLast(new LoggingHandler(LogLevel.INFO)); -// for (int i = 0; i < proccessCodecList.size(); i++) { -// pipeline.addLast(proccessCodecList.get(0)); -// } -// pipeline.addLast(new MessageDecoder()); -// pipeline.addLast(new LengthFieldBasedFrameDecoder(1024*100, 0, 2, 0, 2)); - pipeline.addLast("codec", new SensorhubCodec()); -// pipeline.addLast(new LengthFieldPrepender(2)); - pipeline.addLast(new SensorhubServerHandler()); -// //心跳续约 -// pipeline.addLast(this.heartBeatRespHandler); -// pipeline.addLast(this.loginAuthRespHandler); 登录验证 -// pipeline.addLast(this.chatRespHandler); 对话处理器 - } -} \ No newline at end of file diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerHandler.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerHandler.java deleted file mode 100644 index 1f37eda..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/SensorhubServerHandler.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.casic.missiles.pojo.Msg; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import org.springframework.stereotype.Service; - -/** - * SensorhubServerHandler - */ -@Service -public class SensorhubServerHandler extends SimpleChannelInboundHandler { - - @Override - protected void channelRead0(ChannelHandlerContext ctx, Object obj) throws Exception { - System.out.println("Client->Server:" + obj.toString()); - if (obj instanceof Msg) { - Msg msg = (Msg) obj; - System.out.println("Client->Server:" + JSON.toJSONString(msg)); - } - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - ctx.flush(); - } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/nbBeforeProccessCodec.java b/sensorhub-core/src/main/java/com/casic/missiles/server/handler/nbBeforeProccessCodec.java deleted file mode 100644 index 9a7a95b..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/server/handler/nbBeforeProccessCodec.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.casic.missiles.server.handler; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.base64.Base64; -import io.netty.handler.codec.base64.Base64Dialect; -import io.netty.util.internal.ObjectUtil; -import lombok.extern.slf4j.Slf4j; - -import java.nio.charset.Charset; -import java.util.List; - -@Slf4j -public class nbBeforeProccessCodec extends AbstractBeforeProccessCodec{ - - private final Base64Dialect dialect; - - public nbBeforeProccessCodec() { - this(Base64Dialect.STANDARD); - } - - public nbBeforeProccessCodec(Base64Dialect dialect) { - this.dialect = ObjectUtil.checkNotNull(dialect, "dialect"); - } - - //执行nb平台前的协议解析 预处理 - @Override - public void decode(ChannelHandlerContext ctx, ByteBuf msg, List out){ - //aep平台处理 - if (msg.toString(Charset.defaultCharset()).contains("aep")) { - String httpContent = msg.toString(Charset.defaultCharset()); - log.info(" String : " + msg.toString(Charset.defaultCharset())); - String majorContent = httpContent.substring(httpContent.indexOf("{"), httpContent.lastIndexOf("}") + 1); - String values = String.valueOf(((JSONObject) ((JSONObject) JSON.parseObject(majorContent).get("payload")).get("serviceData")).get("Value")); - log.info("----------------------------------" + values); - ByteBuf bufferContent = ByteBufAllocator.DEFAULT.buffer(); - bufferContent.writeBytes(values.getBytes(Charset.forName("ISO-8859-1"))); - out.add(Base64.decode(bufferContent, bufferContent.readerIndex(), bufferContent.readableBytes(), this.dialect)); - } - } - -} diff --git a/sensorhub-core/src/main/java/com/casic/missiles/utils/ApplicationContextUtil.java b/sensorhub-core/src/main/java/com/casic/missiles/utils/ApplicationContextUtil.java deleted file mode 100644 index 4baa500..0000000 --- a/sensorhub-core/src/main/java/com/casic/missiles/utils/ApplicationContextUtil.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.casic.missiles.utils; - -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.stereotype.Component; - -/** - * @Auther: cz - * @Date: 2021-10-26 - * 配置类,解决定时任务无法注入的问题 - */ -@Component -public class ApplicationContextUtil implements ApplicationContextAware { - - private static ApplicationContext applicationContext; - - public static ApplicationContext getApplicationContext() { - return applicationContext; - } - - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - ApplicationContextUtil.applicationContext = applicationContext; - - } - - - public static Object getBean(String beanName) { - return applicationContext.getBean(beanName); - } -} diff --git a/sensorhub-core/src/main/resources/config/application.yml b/sensorhub-core/src/main/resources/config/application.yml index c3fce06..ae89f9d 100644 --- a/sensorhub-core/src/main/resources/config/application.yml +++ b/sensorhub-core/src/main/resources/config/application.yml @@ -12,12 +12,14 @@ mybatis-plus: global-config: enable-sql-runner: true + #关闭配置数据库下划线字段转驼峰 configuration: + map-underscore-to-camel-case: true # 配置结果集属性为空时 是否映射返回结果 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句,调试用 - mapper-locations: classpath:mapper/*.xml + mapper-locations: classpath*:mapper/*.xml mybatis: - mapper-locations: classpath:mapper/*.xml + mapper-locations: classpath*:mapper/*.xml #mybatis-plus: # sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector casic: