From 2e5af8e220bf370d062ab1b2cd2fa6d8b1643963 Mon Sep 17 00:00:00 2001 From: rouchen <3133657697@qq.com> Date: Sun, 16 Jun 2024 22:32:17 +0800 Subject: [PATCH] =?UTF-8?q?feat=20kafka=E7=9A=84=E6=B6=88=E8=B4=B9?= =?UTF-8?q?=E8=80=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 33 + db/vehicleSimulationDataBaseFile.mv.db | Bin 0 -> 24576 bytes logs/vehicle.log | 240 +++++ pom.xml | 269 ++++++ src/main/java/com/muyu/IotDbApplication.java | 15 + .../java/com/muyu/demos/model/HttpStatus.java | 93 ++ .../com/muyu/demos/model/PositionModel.java | 35 + .../java/com/muyu/demos/model/Result.java | 101 ++ .../com/muyu/demos/web/BasicController.java | 67 ++ .../demos/web/PathVariableController.java | 44 + src/main/java/com/muyu/demos/web/User.java | 43 + .../demos/web/config/ExceptionAdvice.java | 26 + .../demos/web/config/MyMetaObjectHandler.java | 29 + .../demos/web/config/MybatisPlusConfig.java | 34 + .../muyu/demos/web/config/RedisConfig.java | 40 + .../web/config/SecondaryDataSourceConfig.java | 43 + .../muyu/iotDB/config/IotDBSessionConfig.java | 198 ++++ .../iotDB/controller/IotDbController.java | 61 ++ .../muyu/iotDB/data/ErrorResponseData.java | 71 ++ .../java/com/muyu/iotDB/data/IotDbParam.java | 40 + .../java/com/muyu/iotDB/data/IotDbResult.java | 33 + .../com/muyu/iotDB/data/ResponseData.java | 212 +++++ .../muyu/iotDB/data/SuccessResponseData.java | 23 + .../com/muyu/iotDB/service/IotDbServer.java | 20 + .../iotDB/service/impl/IotDbServerImpl.java | 108 +++ .../com/muyu/kafka/SimpleKafkaConsumer.java | 68 ++ .../com/muyu/mqtt/MessageCallbackService.java | 94 ++ src/main/java/com/muyu/mqtt/MqttFactory.java | 46 + .../java/com/muyu/mqtt/MqttProperties.java | 40 + src/main/java/com/muyu/mqtt/MsgHandler.java | 37 + .../com/muyu/mqtt/config/RabbitConfig.java | 47 + .../java/com/muyu/mqtt/dao/MessageData.java | 215 +++++ .../muyu/rabbitmq/SubscriptionHandler.java | 35 + .../muyu/rabbitmq/confilg/RabbitmqConfig.java | 53 ++ .../com/muyu/utils/CalculateCheckDigit.java | 44 + .../java/com/muyu/utils/ConversionUtil.java | 354 +++++++ src/main/java/com/muyu/utils/Convert.java | 893 ++++++++++++++++++ src/main/java/com/muyu/utils/MD5Util.java | 71 ++ .../java/com/muyu/utils/ReflectUtils.java | 314 ++++++ .../java/com/muyu/utils/VehicleUtils.java | 93 ++ src/main/resources/application.yml | 88 ++ src/main/resources/static/index.html | 6 + .../java/com/muyu/IotDbApplicationTests.java | 13 + 43 files changed, 4389 insertions(+) create mode 100644 .gitignore create mode 100644 db/vehicleSimulationDataBaseFile.mv.db create mode 100644 logs/vehicle.log create mode 100644 pom.xml create mode 100644 src/main/java/com/muyu/IotDbApplication.java create mode 100644 src/main/java/com/muyu/demos/model/HttpStatus.java create mode 100644 src/main/java/com/muyu/demos/model/PositionModel.java create mode 100644 src/main/java/com/muyu/demos/model/Result.java create mode 100644 src/main/java/com/muyu/demos/web/BasicController.java create mode 100644 src/main/java/com/muyu/demos/web/PathVariableController.java create mode 100644 src/main/java/com/muyu/demos/web/User.java create mode 100644 src/main/java/com/muyu/demos/web/config/ExceptionAdvice.java create mode 100644 src/main/java/com/muyu/demos/web/config/MyMetaObjectHandler.java create mode 100644 src/main/java/com/muyu/demos/web/config/MybatisPlusConfig.java create mode 100644 src/main/java/com/muyu/demos/web/config/RedisConfig.java create mode 100644 src/main/java/com/muyu/demos/web/config/SecondaryDataSourceConfig.java create mode 100644 src/main/java/com/muyu/iotDB/config/IotDBSessionConfig.java create mode 100644 src/main/java/com/muyu/iotDB/controller/IotDbController.java create mode 100644 src/main/java/com/muyu/iotDB/data/ErrorResponseData.java create mode 100644 src/main/java/com/muyu/iotDB/data/IotDbParam.java create mode 100644 src/main/java/com/muyu/iotDB/data/IotDbResult.java create mode 100644 src/main/java/com/muyu/iotDB/data/ResponseData.java create mode 100644 src/main/java/com/muyu/iotDB/data/SuccessResponseData.java create mode 100644 src/main/java/com/muyu/iotDB/service/IotDbServer.java create mode 100644 src/main/java/com/muyu/iotDB/service/impl/IotDbServerImpl.java create mode 100644 src/main/java/com/muyu/kafka/SimpleKafkaConsumer.java create mode 100644 src/main/java/com/muyu/mqtt/MessageCallbackService.java create mode 100644 src/main/java/com/muyu/mqtt/MqttFactory.java create mode 100644 src/main/java/com/muyu/mqtt/MqttProperties.java create mode 100644 src/main/java/com/muyu/mqtt/MsgHandler.java create mode 100644 src/main/java/com/muyu/mqtt/config/RabbitConfig.java create mode 100644 src/main/java/com/muyu/mqtt/dao/MessageData.java create mode 100644 src/main/java/com/muyu/rabbitmq/SubscriptionHandler.java create mode 100644 src/main/java/com/muyu/rabbitmq/confilg/RabbitmqConfig.java create mode 100644 src/main/java/com/muyu/utils/CalculateCheckDigit.java create mode 100644 src/main/java/com/muyu/utils/ConversionUtil.java create mode 100644 src/main/java/com/muyu/utils/Convert.java create mode 100644 src/main/java/com/muyu/utils/MD5Util.java create mode 100644 src/main/java/com/muyu/utils/ReflectUtils.java create mode 100644 src/main/java/com/muyu/utils/VehicleUtils.java create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/static/index.html create mode 100644 src/test/java/com/muyu/IotDbApplicationTests.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/db/vehicleSimulationDataBaseFile.mv.db b/db/vehicleSimulationDataBaseFile.mv.db new file mode 100644 index 0000000000000000000000000000000000000000..9ae401077124bb9408877b8699ec95a3e7774c0c GIT binary patch literal 24576 zcmeI4O;6)S9L5u%t+d-W4tuR!DlHc`n(@1R%aT+e1-2rgT25$UPaxW0M~Smq^#kLlAl*WIJ#8@8A5f^gQznhk>CFCrS7=u!?vc1Co=$sKH=F^|23Nip4h$*Oc4Z#`TI0*^eMaKbMfXZNz%X&2?6mi zI5qTie9Z&H3@yKm0eJd!93Lc$I1PxlhKI-$Z2h%$+4#EgS$+jATkajXcRvx=(4zU) z%(qs)wezi$Z@tfBcFkLpWY}RTd#;`wvuSyJ%11Bq*OMua2QwDWS(u8P!@T%v%7zo( zB46eoS;SG&ODsvLbpBf`y*vj!QhJuA+?tOqOoe^1?~%CD=uwbU&J z>CZ;Iz1^UO+1TCrR(tuT-yLWNr``6Td-3Y*sMpbiN3pxJr|o_5OS5=gJL`8(wWA-j zlh*^S`{t-W=xck&XXj^oTEE>JX#2KFEH5-TcTJC)MzpUTw)=V zRllav)~Em3lhXhHY+qG*hBC(>eE{$A_yEghkqQs|*KB?11KcM%AYu(!KNT5=D%RkY z9aeXk9$}6^Srg02n!8}#GjCI7Kt2qs9>>{)H6ia7S+wCJ?~C{t2!H?xfB*=900@8p z2s}jsh5oPfx6=Q$|D(q}q5s{r>i^{ccBTI_J#sUQetXnf)m_h0uS59D-3K!_cDv&3!GGP-UxwZ@dI{7Ky>v2sW i00JNY0w4eaAOHd&Q0V_ke^)xXod1t9{co*F|Nje=WJBEm literal 0 HcmV?d00001 diff --git a/logs/vehicle.log b/logs/vehicle.log new file mode 100644 index 0000000..977184e --- /dev/null +++ b/logs/vehicle.log @@ -0,0 +1,240 @@ +2024-06-16 22:05:14.436 [main] INFO com.muyu.IotDbApplication:55 - Starting IotDbApplication using Java 17.0.10 on xiaoxin with PID 15576 (D:\work\IotDB\target\classes started by 86157 in D:\work\IotDB) +2024-06-16 22:05:14.438 [main] DEBUG com.muyu.IotDbApplication:56 - Running with Spring Boot v2.6.13, Spring v5.3.23 +2024-06-16 22:05:14.439 [main] INFO com.muyu.IotDbApplication:645 - No active profile set, falling back to 1 default profile: "default" +2024-06-16 22:05:15.061 [main] INFO o.s.d.r.config.RepositoryConfigurationDelegate:262 - Multiple Spring Data modules found, entering strict repository configuration mode +2024-06-16 22:05:15.063 [main] INFO o.s.d.r.config.RepositoryConfigurationDelegate:132 - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +2024-06-16 22:05:15.089 [main] INFO o.s.d.r.config.RepositoryConfigurationDelegate:201 - Finished Spring Data repository scanning in 10 ms. Found 0 Redis repository interfaces. +2024-06-16 22:05:15.197 [main] WARN org.mybatis.spring.mapper.ClassPathMapperScanner:44 - No MyBatis mapper was found in '[com.muyu]' package. Please check your configuration. +2024-06-16 22:05:15.344 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'com.dtflys.forest.springboot.ForestAutoConfiguration' of type [com.dtflys.forest.springboot.ForestAutoConfiguration$$EnhancerBySpringCGLIB$$2d515412] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:05:15.467 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestProperties' of type [com.dtflys.forest.config.SpringForestProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:05:15.469 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestObjectFactory' of type [com.dtflys.forest.reflection.SpringForestObjectFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:05:15.471 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestInterceptorFactory' of type [com.dtflys.forest.interceptor.SpringInterceptorFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:05:15.485 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forest-com.dtflys.forest.springboot.properties.ForestConfigurationProperties' of type [com.dtflys.forest.springboot.properties.ForestConfigurationProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:05:15.529 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestConfiguration' of type [com.dtflys.forest.config.ForestConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:05:15.535 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestConverterBeanListener' of type [com.dtflys.forest.spring.ConverterBeanListener] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:05:15.787 [main] INFO o.s.boot.web.embedded.tomcat.TomcatWebServer:108 - Tomcat initialized with port(s): 8855 (http) +2024-06-16 22:05:15.796 [main] INFO org.apache.catalina.core.StandardService:173 - Starting service [Tomcat] +2024-06-16 22:05:15.796 [main] INFO org.apache.catalina.core.StandardEngine:173 - Starting Servlet engine: [Apache Tomcat/9.0.68] +2024-06-16 22:05:15.915 [main] INFO o.a.c.core.ContainerBase.[Tomcat].[localhost].[/]:173 - Initializing Spring embedded WebApplicationContext +2024-06-16 22:05:15.915 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext:290 - Root WebApplicationContext: initialization completed in 1438 ms +2024-06-16 22:05:15.944 [main] INFO com.zaxxer.hikari.HikariDataSource:110 - HikariPool-1 - Starting... +2024-06-16 22:05:16.155 [main] INFO com.zaxxer.hikari.HikariDataSource:123 - HikariPool-1 - Start completed. +2024-06-16 22:05:16.162 [main] INFO o.s.b.autoconfigure.h2.H2ConsoleAutoConfiguration:100 - H2 console available at '/h2-console'. Database available at 'jdbc:h2:file:./db/vehicleSimulationDataBaseFile' +2024-06-16 22:05:16.576 [main] INFO com.muyu.iotDB.config.IotDBSessionConfig:38 - 正在连接iotdb....... +2024-06-16 22:05:16.592 [main] WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext:591 - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getSession' defined in class path resource [com/muyu/iotDB/config/IotDBSessionConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.iotdb.session.Session]: Factory method 'getSession' threw exception; nested exception is org.apache.iotdb.rpc.IoTDBConnectionException: org.apache.thrift.transport.TTransportException: java.net.ConnectException: Connection refused: connect +2024-06-16 22:05:16.608 [main] INFO com.zaxxer.hikari.HikariDataSource:350 - HikariPool-1 - Shutdown initiated... +2024-06-16 22:05:16.610 [main] INFO com.zaxxer.hikari.HikariDataSource:352 - HikariPool-1 - Shutdown completed. +2024-06-16 22:05:16.612 [main] INFO org.apache.catalina.core.StandardService:173 - Stopping service [Tomcat] +2024-06-16 22:05:16.618 [main] INFO o.s.b.a.l.ConditionEvaluationReportLoggingListener:136 - + +Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. +2024-06-16 22:05:16.633 [main] ERROR org.springframework.boot.SpringApplication:835 - Application run failed +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getSession' defined in class path resource [com/muyu/iotDB/config/IotDBSessionConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.iotdb.session.Session]: Factory method 'getSession' threw exception; nested exception is org.apache.iotdb.rpc.IoTDBConnectionException: org.apache.thrift.transport.TTransportException: java.net.ConnectException: Connection refused: connect + at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:745) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:420) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1317) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) + at com.muyu.IotDbApplication.main(IotDbApplication.java:10) +Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.iotdb.session.Session]: Factory method 'getSession' threw exception; nested exception is org.apache.iotdb.rpc.IoTDBConnectionException: org.apache.thrift.transport.TTransportException: java.net.ConnectException: Connection refused: connect + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) + at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) + ... 19 common frames omitted +Caused by: org.apache.iotdb.rpc.IoTDBConnectionException: org.apache.thrift.transport.TTransportException: java.net.ConnectException: Connection refused: connect + at org.apache.iotdb.session.SessionConnection.init(SessionConnection.java:117) + at org.apache.iotdb.session.SessionConnection.(SessionConnection.java:97) + at org.apache.iotdb.session.Session.constructSessionConnection(Session.java:434) + at org.apache.iotdb.session.Session.open(Session.java:402) + at org.apache.iotdb.session.Session.open(Session.java:391) + at com.muyu.iotDB.config.IotDBSessionConfig.getSession(IotDBSessionConfig.java:40) + at com.muyu.iotDB.config.IotDBSessionConfig$$EnhancerBySpringCGLIB$$11fb9d90.CGLIB$getSession$1() + at com.muyu.iotDB.config.IotDBSessionConfig$$EnhancerBySpringCGLIB$$11fb9d90$$FastClassBySpringCGLIB$$f52196fe.invoke() + at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) + at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) + at com.muyu.iotDB.config.IotDBSessionConfig$$EnhancerBySpringCGLIB$$11fb9d90.getSession() + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:568) + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) + ... 20 common frames omitted +Caused by: org.apache.thrift.transport.TTransportException: java.net.ConnectException: Connection refused: connect + at org.apache.thrift.transport.TSocket.open(TSocket.java:243) + at org.apache.iotdb.rpc.TElasticFramedTransport.open(TElasticFramedTransport.java:91) + at org.apache.iotdb.session.SessionConnection.init(SessionConnection.java:115) + ... 35 common frames omitted +Caused by: java.net.ConnectException: Connection refused: connect + at java.base/sun.nio.ch.Net.connect0(Native Method) + at java.base/sun.nio.ch.Net.connect(Net.java:579) + at java.base/sun.nio.ch.Net.connect(Net.java:568) + at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:593) + at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) + at java.base/java.net.Socket.connect(Socket.java:633) + at org.apache.thrift.transport.TSocket.open(TSocket.java:238) + ... 37 common frames omitted +2024-06-16 22:06:37.153 [main] INFO com.muyu.IotDbApplication:55 - Starting IotDbApplication using Java 17.0.10 on xiaoxin with PID 22372 (D:\work\IotDB\target\classes started by 86157 in D:\work\IotDB) +2024-06-16 22:06:37.155 [main] DEBUG com.muyu.IotDbApplication:56 - Running with Spring Boot v2.6.13, Spring v5.3.23 +2024-06-16 22:06:37.156 [main] INFO com.muyu.IotDbApplication:645 - No active profile set, falling back to 1 default profile: "default" +2024-06-16 22:06:37.695 [main] INFO o.s.d.r.config.RepositoryConfigurationDelegate:262 - Multiple Spring Data modules found, entering strict repository configuration mode +2024-06-16 22:06:37.697 [main] INFO o.s.d.r.config.RepositoryConfigurationDelegate:132 - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +2024-06-16 22:06:37.715 [main] INFO o.s.d.r.config.RepositoryConfigurationDelegate:201 - Finished Spring Data repository scanning in 8 ms. Found 0 Redis repository interfaces. +2024-06-16 22:06:37.810 [main] WARN org.mybatis.spring.mapper.ClassPathMapperScanner:44 - No MyBatis mapper was found in '[com.muyu]' package. Please check your configuration. +2024-06-16 22:06:37.940 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'com.dtflys.forest.springboot.ForestAutoConfiguration' of type [com.dtflys.forest.springboot.ForestAutoConfiguration$$EnhancerBySpringCGLIB$$673eaa44] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:06:38.021 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestProperties' of type [com.dtflys.forest.config.SpringForestProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:06:38.022 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestObjectFactory' of type [com.dtflys.forest.reflection.SpringForestObjectFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:06:38.024 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestInterceptorFactory' of type [com.dtflys.forest.interceptor.SpringInterceptorFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:06:38.036 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forest-com.dtflys.forest.springboot.properties.ForestConfigurationProperties' of type [com.dtflys.forest.springboot.properties.ForestConfigurationProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:06:38.067 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestConfiguration' of type [com.dtflys.forest.config.ForestConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:06:38.072 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestConverterBeanListener' of type [com.dtflys.forest.spring.ConverterBeanListener] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:06:38.288 [main] INFO o.s.boot.web.embedded.tomcat.TomcatWebServer:108 - Tomcat initialized with port(s): 8855 (http) +2024-06-16 22:06:38.296 [main] INFO org.apache.catalina.core.StandardService:173 - Starting service [Tomcat] +2024-06-16 22:06:38.297 [main] INFO org.apache.catalina.core.StandardEngine:173 - Starting Servlet engine: [Apache Tomcat/9.0.68] +2024-06-16 22:06:38.410 [main] INFO o.a.c.core.ContainerBase.[Tomcat].[localhost].[/]:173 - Initializing Spring embedded WebApplicationContext +2024-06-16 22:06:38.410 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext:290 - Root WebApplicationContext: initialization completed in 1209 ms +2024-06-16 22:06:38.439 [main] INFO com.zaxxer.hikari.HikariDataSource:110 - HikariPool-1 - Starting... +2024-06-16 22:06:38.627 [main] INFO com.zaxxer.hikari.HikariDataSource:123 - HikariPool-1 - Start completed. +2024-06-16 22:06:38.634 [main] INFO o.s.b.autoconfigure.h2.H2ConsoleAutoConfiguration:100 - H2 console available at '/h2-console'. Database available at 'jdbc:h2:file:./db/vehicleSimulationDataBaseFile' +2024-06-16 22:06:38.969 [main] INFO com.muyu.iotDB.config.IotDBSessionConfig:38 - 正在连接iotdb....... +2024-06-16 22:06:39.103 [main] INFO com.muyu.iotDB.config.IotDBSessionConfig:42 - iotdb连接成功~ +2024-06-16 22:06:39.835 [main] WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext:591 - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: No schema scripts found at location 'classpath:schema.sql' +2024-06-16 22:06:39.854 [main] INFO com.zaxxer.hikari.HikariDataSource:350 - HikariPool-1 - Shutdown initiated... +2024-06-16 22:06:39.855 [main] INFO com.zaxxer.hikari.HikariDataSource:352 - HikariPool-1 - Shutdown completed. +2024-06-16 22:06:39.857 [main] INFO org.apache.catalina.core.StandardService:173 - Stopping service [Tomcat] +2024-06-16 22:06:39.864 [main] INFO o.s.b.a.l.ConditionEvaluationReportLoggingListener:136 - + +Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. +2024-06-16 22:06:39.874 [main] ERROR org.springframework.boot.SpringApplication:835 - Application run failed +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: No schema scripts found at location 'classpath:schema.sql' + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:745) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:420) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1317) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) + at com.muyu.IotDbApplication.main(IotDbApplication.java:10) +Caused by: java.lang.IllegalStateException: No schema scripts found at location 'classpath:schema.sql' + at org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer.getScripts(AbstractScriptDatabaseInitializer.java:128) + at org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer.applyScripts(AbstractScriptDatabaseInitializer.java:105) + at org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer.applySchemaScripts(AbstractScriptDatabaseInitializer.java:97) + at org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer.initializeDatabase(AbstractScriptDatabaseInitializer.java:75) + at org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer.afterPropertiesSet(AbstractScriptDatabaseInitializer.java:65) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) + ... 18 common frames omitted +2024-06-16 22:07:40.641 [main] INFO com.muyu.IotDbApplication:55 - Starting IotDbApplication using Java 17.0.10 on xiaoxin with PID 5328 (D:\work\IotDB\target\classes started by 86157 in D:\work\IotDB) +2024-06-16 22:07:40.643 [main] DEBUG com.muyu.IotDbApplication:56 - Running with Spring Boot v2.6.13, Spring v5.3.23 +2024-06-16 22:07:40.643 [main] INFO com.muyu.IotDbApplication:645 - No active profile set, falling back to 1 default profile: "default" +2024-06-16 22:07:41.124 [main] INFO o.s.d.r.config.RepositoryConfigurationDelegate:262 - Multiple Spring Data modules found, entering strict repository configuration mode +2024-06-16 22:07:41.126 [main] INFO o.s.d.r.config.RepositoryConfigurationDelegate:132 - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +2024-06-16 22:07:41.146 [main] INFO o.s.d.r.config.RepositoryConfigurationDelegate:201 - Finished Spring Data repository scanning in 9 ms. Found 0 Redis repository interfaces. +2024-06-16 22:07:41.259 [main] WARN org.mybatis.spring.mapper.ClassPathMapperScanner:44 - No MyBatis mapper was found in '[com.muyu]' package. Please check your configuration. +2024-06-16 22:07:41.404 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'com.dtflys.forest.springboot.ForestAutoConfiguration' of type [com.dtflys.forest.springboot.ForestAutoConfiguration$$EnhancerBySpringCGLIB$$8b69fa64] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:07:41.498 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestProperties' of type [com.dtflys.forest.config.SpringForestProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:07:41.499 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestObjectFactory' of type [com.dtflys.forest.reflection.SpringForestObjectFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:07:41.502 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestInterceptorFactory' of type [com.dtflys.forest.interceptor.SpringInterceptorFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:07:41.517 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forest-com.dtflys.forest.springboot.properties.ForestConfigurationProperties' of type [com.dtflys.forest.springboot.properties.ForestConfigurationProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:07:41.552 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestConfiguration' of type [com.dtflys.forest.config.ForestConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:07:41.556 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestConverterBeanListener' of type [com.dtflys.forest.spring.ConverterBeanListener] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:07:41.776 [main] INFO o.s.boot.web.embedded.tomcat.TomcatWebServer:108 - Tomcat initialized with port(s): 8855 (http) +2024-06-16 22:07:41.782 [main] INFO org.apache.catalina.core.StandardService:173 - Starting service [Tomcat] +2024-06-16 22:07:41.783 [main] INFO org.apache.catalina.core.StandardEngine:173 - Starting Servlet engine: [Apache Tomcat/9.0.68] +2024-06-16 22:07:41.884 [main] INFO o.a.c.core.ContainerBase.[Tomcat].[localhost].[/]:173 - Initializing Spring embedded WebApplicationContext +2024-06-16 22:07:41.884 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext:290 - Root WebApplicationContext: initialization completed in 1207 ms +2024-06-16 22:07:41.912 [main] INFO com.zaxxer.hikari.HikariDataSource:110 - HikariPool-1 - Starting... +2024-06-16 22:07:42.091 [main] INFO com.zaxxer.hikari.HikariDataSource:123 - HikariPool-1 - Start completed. +2024-06-16 22:07:42.099 [main] INFO o.s.b.autoconfigure.h2.H2ConsoleAutoConfiguration:100 - H2 console available at '/h2-console'. Database available at 'jdbc:h2:file:./db/vehicleSimulationDataBaseFile' +2024-06-16 22:07:42.422 [main] INFO com.muyu.iotDB.config.IotDBSessionConfig:38 - 正在连接iotdb....... +2024-06-16 22:07:42.492 [main] INFO com.muyu.iotDB.config.IotDBSessionConfig:42 - iotdb连接成功~ +2024-06-16 22:07:43.122 [main] WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext:591 - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: No schema scripts found at location 'classpath:schema.sql' +2024-06-16 22:07:43.137 [main] INFO com.zaxxer.hikari.HikariDataSource:350 - HikariPool-1 - Shutdown initiated... +2024-06-16 22:07:43.139 [main] INFO com.zaxxer.hikari.HikariDataSource:352 - HikariPool-1 - Shutdown completed. +2024-06-16 22:07:43.140 [main] INFO org.apache.catalina.core.StandardService:173 - Stopping service [Tomcat] +2024-06-16 22:07:43.147 [main] INFO o.s.b.a.l.ConditionEvaluationReportLoggingListener:136 - + +Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. +2024-06-16 22:07:43.157 [main] ERROR org.springframework.boot.SpringApplication:835 - Application run failed +org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: No schema scripts found at location 'classpath:schema.sql' + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1804) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) + at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:745) + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:420) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1317) + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1306) + at com.muyu.IotDbApplication.main(IotDbApplication.java:10) +Caused by: java.lang.IllegalStateException: No schema scripts found at location 'classpath:schema.sql' + at org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer.getScripts(AbstractScriptDatabaseInitializer.java:128) + at org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer.applyScripts(AbstractScriptDatabaseInitializer.java:105) + at org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer.applySchemaScripts(AbstractScriptDatabaseInitializer.java:97) + at org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer.initializeDatabase(AbstractScriptDatabaseInitializer.java:75) + at org.springframework.boot.sql.init.AbstractScriptDatabaseInitializer.afterPropertiesSet(AbstractScriptDatabaseInitializer.java:65) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1863) + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1800) + ... 18 common frames omitted +2024-06-16 22:11:29.888 [main] INFO com.muyu.IotDbApplication:55 - Starting IotDbApplication using Java 17.0.10 on xiaoxin with PID 3044 (D:\work\IotDB\target\classes started by 86157 in D:\work\IotDB) +2024-06-16 22:11:29.891 [main] DEBUG com.muyu.IotDbApplication:56 - Running with Spring Boot v2.6.13, Spring v5.3.23 +2024-06-16 22:11:29.891 [main] INFO com.muyu.IotDbApplication:645 - No active profile set, falling back to 1 default profile: "default" +2024-06-16 22:11:30.527 [main] INFO o.s.d.r.config.RepositoryConfigurationDelegate:262 - Multiple Spring Data modules found, entering strict repository configuration mode +2024-06-16 22:11:30.529 [main] INFO o.s.d.r.config.RepositoryConfigurationDelegate:132 - Bootstrapping Spring Data Redis repositories in DEFAULT mode. +2024-06-16 22:11:30.552 [main] INFO o.s.d.r.config.RepositoryConfigurationDelegate:201 - Finished Spring Data repository scanning in 9 ms. Found 0 Redis repository interfaces. +2024-06-16 22:11:30.660 [main] WARN org.mybatis.spring.mapper.ClassPathMapperScanner:44 - No MyBatis mapper was found in '[com.muyu]' package. Please check your configuration. +2024-06-16 22:11:30.783 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'com.dtflys.forest.springboot.ForestAutoConfiguration' of type [com.dtflys.forest.springboot.ForestAutoConfiguration$$EnhancerBySpringCGLIB$$b8577d82] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:11:30.901 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestProperties' of type [com.dtflys.forest.config.SpringForestProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:11:30.902 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestObjectFactory' of type [com.dtflys.forest.reflection.SpringForestObjectFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:11:30.904 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestInterceptorFactory' of type [com.dtflys.forest.interceptor.SpringInterceptorFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:11:30.917 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forest-com.dtflys.forest.springboot.properties.ForestConfigurationProperties' of type [com.dtflys.forest.springboot.properties.ForestConfigurationProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:11:30.949 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestConfiguration' of type [com.dtflys.forest.config.ForestConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:11:30.956 [main] INFO o.s.c.s.PostProcessorRegistrationDelegate$BeanPostProcessorChecker:376 - Bean 'forestConverterBeanListener' of type [com.dtflys.forest.spring.ConverterBeanListener] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) +2024-06-16 22:11:31.177 [main] INFO o.s.boot.web.embedded.tomcat.TomcatWebServer:108 - Tomcat initialized with port(s): 8855 (http) +2024-06-16 22:11:31.184 [main] INFO org.apache.catalina.core.StandardService:173 - Starting service [Tomcat] +2024-06-16 22:11:31.184 [main] INFO org.apache.catalina.core.StandardEngine:173 - Starting Servlet engine: [Apache Tomcat/9.0.68] +2024-06-16 22:11:31.289 [main] INFO o.a.c.core.ContainerBase.[Tomcat].[localhost].[/]:173 - Initializing Spring embedded WebApplicationContext +2024-06-16 22:11:31.289 [main] INFO o.s.b.w.s.c.ServletWebServerApplicationContext:290 - Root WebApplicationContext: initialization completed in 1347 ms +2024-06-16 22:11:31.658 [main] INFO com.muyu.iotDB.config.IotDBSessionConfig:38 - 正在连接iotdb....... +2024-06-16 22:11:31.726 [main] INFO com.muyu.iotDB.config.IotDBSessionConfig:42 - iotdb连接成功~ +2024-06-16 22:11:32.580 [main] INFO o.s.boot.web.embedded.tomcat.TomcatWebServer:220 - Tomcat started on port(s): 8855 (http) with context path '' +2024-06-16 22:11:32.582 [main] INFO o.s.a.rabbit.connection.CachingConnectionFactory:638 - Attempting to connect to: [101.34.243.166:5672] +2024-06-16 22:11:32.693 [main] INFO o.s.a.rabbit.connection.CachingConnectionFactory:589 - Created new connection: rabbitConnectionFactory#5c3007d:0/SimpleConnection@731d0d5c [delegate=amqp://guest@101.34.243.166:5672/, localPort= 63686] +2024-06-16 22:11:32.963 [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] INFO com.muyu.mqtt.MsgHandler:22 - 接收到消息:47.100.60.64,47.102.213.144 +2024-06-16 22:11:32.967 [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] ERROR com.muyu.mqtt.MsgHandler:30 - 接收到消息初始化信息:MqttProperties(broker=tcp://47.100.60.64:1883, topic=test1, username=null, password=null, clientid=protocol-parsing) +2024-06-16 22:11:33.101 [main] INFO com.muyu.IotDbApplication:61 - Started IotDbApplication in 3.613 seconds (JVM running for 4.163) +2024-06-16 22:11:33.367 [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] ERROR com.muyu.mqtt.MsgHandler:32 - client创建成功:protocol-parsing +2024-06-16 22:11:33.367 [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] ERROR com.muyu.mqtt.MsgHandler:30 - 接收到消息初始化信息:MqttProperties(broker=tcp://47.102.213.144:1883, topic=test1, username=null, password=null, clientid=protocol-parsing) +2024-06-16 22:11:33.754 [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] ERROR com.muyu.mqtt.MsgHandler:32 - client创建成功:protocol-parsing diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..1cf3272 --- /dev/null +++ b/pom.xml @@ -0,0 +1,269 @@ + + + 4.0.0 + com.muyu + IotDB + 0.0.1-SNAPSHOT + IotDB + Demo project for Spring Boot + + 17 + UTF-8 + UTF-8 + 2.6.13 + + + + + com.dtflys.forest + forest-spring-boot-starter + 1.5.33 + + + + com.alibaba + fastjson + 1.2.73 + + + + + com.baomidou + mybatis-plus-boot-starter + 3.5.1 + + + com.baomidou + mybatis-plus-generator + 3.5.1 + + + org.freemarker + freemarker + + + + + org.apache.iotdb + iotdb-session + 0.14.0-preview1 + + + + cn.hutool + hutool-all + 5.6.3 + + + + com.alibaba + fastjson + 1.2.83 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + org.springframework.kafka + spring-kafka + 2.8.11 + + + org.apache.kafka + kafka-clients + 2.8.0 + + + + org.springframework.boot + spring-boot-starter-amqp + + + + org.springframework.boot + spring-boot-starter-web + + + + com.aliyun + ecs20140526 + 5.1.8 + + + com.aliyun + tea-openapi + 0.3.2 + + + com.aliyun + tea-openapi + 0.3.2 + + + com.aliyun + tea-console + 0.0.1 + + + com.aliyun + openapiutil + 0.2.1 + + + com.aliyun + tea-util + 0.2.21 + + + + com.aliyun + ecs20140526 + 5.1.8 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + 1.2.5 + + + + + org.projectlombok + lombok + + + + + com.h2database + h2 + + + + com.alibaba.fastjson2 + fastjson2 + 2.0.42 + + + + + com.dtflys.forest + forest-spring-boot-starter + 1.5.33 + + + + com.alibaba + fastjson + 1.2.73 + + + + + org.apache.commons + commons-lang3 + + + org.projectlombok + lombok + RELEASE + provided + + + org.projectlombok + lombok + 1.18.32 + provided + + + + org.springframework.boot + spring-boot-starter-data-redis + 2.7.13 + + + org.springframework.boot + spring-boot-starter-web + 2.7.13 + + + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + 1.2.5 + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 17 + 17 + UTF-8 + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + com.muyu.IotDbApplication + true + + + + repackage + + repackage + + + + + + + + diff --git a/src/main/java/com/muyu/IotDbApplication.java b/src/main/java/com/muyu/IotDbApplication.java new file mode 100644 index 0000000..86a3731 --- /dev/null +++ b/src/main/java/com/muyu/IotDbApplication.java @@ -0,0 +1,15 @@ +package com.muyu; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@EnableScheduling +public class IotDbApplication { + + public static void main(String[] args) { + SpringApplication.run(IotDbApplication.class, args); + } + +} diff --git a/src/main/java/com/muyu/demos/model/HttpStatus.java b/src/main/java/com/muyu/demos/model/HttpStatus.java new file mode 100644 index 0000000..37a0721 --- /dev/null +++ b/src/main/java/com/muyu/demos/model/HttpStatus.java @@ -0,0 +1,93 @@ +package com.muyu.demos.model; + +/** + * 返回状态码 + * + * @author ruoyi + */ +public class HttpStatus { + /** + * 操作成功 + */ + public static final int SUCCESS = 200; + + /** + * 对象创建成功 + */ + public static final int CREATED = 201; + + /** + * 请求已经被接受 + */ + public static final int ACCEPTED = 202; + + /** + * 操作已经执行成功,但是没有返回数据 + */ + public static final int NO_CONTENT = 204; + + /** + * 资源已被移除 + */ + public static final int MOVED_PERM = 301; + + /** + * 重定向 + */ + public static final int SEE_OTHER = 303; + + /** + * 资源没有被修改 + */ + public static final int NOT_MODIFIED = 304; + + /** + * 参数列表错误(缺少,格式不匹配) + */ + public static final int BAD_REQUEST = 400; + + /** + * 未授权 + */ + public static final int UNAUTHORIZED = 401; + + /** + * 访问受限,授权过期 + */ + public static final int FORBIDDEN = 403; + + /** + * 资源,服务未找到 + */ + public static final int NOT_FOUND = 404; + + /** + * 不允许的http方法 + */ + public static final int BAD_METHOD = 405; + + /** + * 资源冲突,或者资源被锁 + */ + public static final int CONFLICT = 409; + + /** + * 不支持的数据,媒体类型 + */ + public static final int UNSUPPORTED_TYPE = 415; + + /** + * 系统内部错误 + */ + public static final int ERROR = 500; + + /** + * 接口未实现 + */ + public static final int NOT_IMPLEMENTED = 501; + + /** + * 系统警告消息 + */ + public static final int WARN = 601; +} diff --git a/src/main/java/com/muyu/demos/model/PositionModel.java b/src/main/java/com/muyu/demos/model/PositionModel.java new file mode 100644 index 0000000..6164563 --- /dev/null +++ b/src/main/java/com/muyu/demos/model/PositionModel.java @@ -0,0 +1,35 @@ +package com.muyu.demos.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author DongZl + * @description: 位置模型 + * @Date 2023-11-20 上午 09:36 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class PositionModel { + /** + * 经度 + */ + private String longitude; + + /** + * 维度 + */ + private String latitude; + + public static PositionModel strBuild (String positionStr) { + String[] split = positionStr.split(","); + return PositionModel.builder() + .longitude(split[0]) + .latitude(split[1]) + .build(); + } +} diff --git a/src/main/java/com/muyu/demos/model/Result.java b/src/main/java/com/muyu/demos/model/Result.java new file mode 100644 index 0000000..bba5f46 --- /dev/null +++ b/src/main/java/com/muyu/demos/model/Result.java @@ -0,0 +1,101 @@ +package com.muyu.demos.model; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 响应信息主体 + * + * @author ruoyi + */ +@Data +public class Result implements Serializable { + /** + * 成功 + */ + public static final int SUCCESS = HttpStatus.SUCCESS; + /** + * 失败 + */ + public static final int FAIL = HttpStatus.ERROR; + private static final long serialVersionUID = 1L; + /** + * 系统警告消息 + */ + private static final int WARN = HttpStatus.WARN; + + private int code; + + private String msg; + + private T data; + + public static Result success () { + return restResult(null, SUCCESS, "操作成功"); + } + + public static Result success (T data) { + return restResult(data, SUCCESS, "操作成功"); + } + + public static Result success (T data, String msg) { + return restResult(data, SUCCESS, msg); + } + + public static Result error () { + return restResult(null, FAIL, "操作失败"); + } + + public static Result error (String msg) { + return restResult(null, FAIL, msg); + } + + public static Result error (T data) { + return restResult(data, FAIL, "操作失败"); + } + + public static Result error (T data, String msg) { + return restResult(data, FAIL, msg); + } + + public static Result error (int code, String msg) { + return restResult(null, code, msg); + } + + public static Result warn () { + return restResult(null, WARN, "操作失败"); + } + + public static Result warn (String msg) { + return restResult(null, WARN, msg); + } + + public static Result warn (T data) { + return restResult(data, WARN, "操作失败"); + } + + public static Result warn (T data, String msg) { + return restResult(data, WARN, msg); + } + + public static Result warn (int code, String msg) { + return restResult(null, code, msg); + } + + private static Result restResult (T data, int code, String msg) { + Result apiResult = new Result<>(); + apiResult.setCode(code); + apiResult.setData(data); + apiResult.setMsg(msg); + return apiResult; + } + + public static Boolean isError (Result ret) { + return !isSuccess(ret); + } + + public static Boolean isSuccess (Result ret) { + return Result.SUCCESS == ret.getCode(); + } +} diff --git a/src/main/java/com/muyu/demos/web/BasicController.java b/src/main/java/com/muyu/demos/web/BasicController.java new file mode 100644 index 0000000..65e8908 --- /dev/null +++ b/src/main/java/com/muyu/demos/web/BasicController.java @@ -0,0 +1,67 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.muyu.demos.web; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * @author theonefx + */ +@Controller +public class BasicController { + + // http://127.0.0.1:8080/hello?name=lisi + @RequestMapping("/hello") + @ResponseBody + public String hello(@RequestParam(name = "name", defaultValue = "unknown user") String name) { + return "Hello " + name; + } + + // http://127.0.0.1:8080/user + @RequestMapping("/user") + @ResponseBody + public User user() { + User user = new User(); + user.setName("theonefx"); + user.setAge(666); + return user; + } + + // http://127.0.0.1:8080/save_user?name=newName&age=11 + @RequestMapping("/save_user") + @ResponseBody + public String saveUser(User u) { + return "user will save: name=" + u.getName() + ", age=" + u.getAge(); + } + + // http://127.0.0.1:8080/html + @RequestMapping("/html") + public String html(){ + return "index.html"; + } + + @ModelAttribute + public void parseUser(@RequestParam(name = "name", defaultValue = "unknown user") String name + , @RequestParam(name = "age", defaultValue = "12") Integer age, User user) { + user.setName("zhangsan"); + user.setAge(18); + } +} diff --git a/src/main/java/com/muyu/demos/web/PathVariableController.java b/src/main/java/com/muyu/demos/web/PathVariableController.java new file mode 100644 index 0000000..e3024a9 --- /dev/null +++ b/src/main/java/com/muyu/demos/web/PathVariableController.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.muyu.demos.web; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * @author theonefx + */ +@Controller +public class PathVariableController { + + // http://127.0.0.1:8080/user/123/roles/222 + @RequestMapping(value = "/user/{userId}/roles/{roleId}", method = RequestMethod.GET) + @ResponseBody + public String getLogin(@PathVariable("userId") String userId, @PathVariable("roleId") String roleId) { + return "User Id : " + userId + " Role Id : " + roleId; + } + + // http://127.0.0.1:8080/javabeat/somewords + @RequestMapping(value = "/javabeat/{regexp1:[a-z-]+}", method = RequestMethod.GET) + @ResponseBody + public String getRegExp(@PathVariable("regexp1") String regexp1) { + return "URI Part : " + regexp1; + } +} diff --git a/src/main/java/com/muyu/demos/web/User.java b/src/main/java/com/muyu/demos/web/User.java new file mode 100644 index 0000000..8e07afb --- /dev/null +++ b/src/main/java/com/muyu/demos/web/User.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.muyu.demos.web; + +/** + * @author theonefx + */ +public class User { + + private String name; + + private Integer age; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } +} diff --git a/src/main/java/com/muyu/demos/web/config/ExceptionAdvice.java b/src/main/java/com/muyu/demos/web/config/ExceptionAdvice.java new file mode 100644 index 0000000..0c8cb57 --- /dev/null +++ b/src/main/java/com/muyu/demos/web/config/ExceptionAdvice.java @@ -0,0 +1,26 @@ +package com.muyu.demos.web.config; + + +import com.muyu.demos.model.Result; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * @author DongZeLiang + * @version 1.0 + * @description 异常类 + * @date 2023/11/15 + */ +@RestControllerAdvice +public class ExceptionAdvice { + + /** + * 运行时异常拦截 + * @param runtimeException 运行时异常 + * @return 公共返回结果 + */ + @ExceptionHandler(value = RuntimeException.class) + public Result runtimeExceptionHandler(RuntimeException runtimeException){ + return Result.error(runtimeException.getMessage()); + } +} diff --git a/src/main/java/com/muyu/demos/web/config/MyMetaObjectHandler.java b/src/main/java/com/muyu/demos/web/config/MyMetaObjectHandler.java new file mode 100644 index 0000000..9f3e24f --- /dev/null +++ b/src/main/java/com/muyu/demos/web/config/MyMetaObjectHandler.java @@ -0,0 +1,29 @@ +package com.muyu.demos.web.config; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +import java.util.Date; + +/** + * 填充公共字段 + * + */ +@Slf4j +@Component +public class MyMetaObjectHandler implements MetaObjectHandler { + @Override + public void insertFill(MetaObject metaObject) { + log.info("start insert fill..."); + this.setFieldValByName("createTime", new Date(), metaObject); + this.setFieldValByName("updateTime", new Date(), metaObject); + } + + @Override + public void updateFill(MetaObject metaObject) { + log.info("start update fill..."); + this.setFieldValByName("updateTime", new Date(), metaObject); + } +} diff --git a/src/main/java/com/muyu/demos/web/config/MybatisPlusConfig.java b/src/main/java/com/muyu/demos/web/config/MybatisPlusConfig.java new file mode 100644 index 0000000..137c57a --- /dev/null +++ b/src/main/java/com/muyu/demos/web/config/MybatisPlusConfig.java @@ -0,0 +1,34 @@ +package com.muyu.demos.web.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * mybatisplus 配置 + */ +@Configuration +public class MybatisPlusConfig { + /** + * 老版本,目前已失效 + * @return + */ + /**@Bean + public PaginationInterceptor paginationInterceptor() { + PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); + return paginationInterceptor; + }*/ + + + /** + * 新的分页插件,一缓和二缓遵循mybatis的规则, + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2)); + return interceptor; + } +} diff --git a/src/main/java/com/muyu/demos/web/config/RedisConfig.java b/src/main/java/com/muyu/demos/web/config/RedisConfig.java new file mode 100644 index 0000000..dd4da95 --- /dev/null +++ b/src/main/java/com/muyu/demos/web/config/RedisConfig.java @@ -0,0 +1,40 @@ +package com.muyu.demos.web.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +public class RedisConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new + Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + + return template; + } +} diff --git a/src/main/java/com/muyu/demos/web/config/SecondaryDataSourceConfig.java b/src/main/java/com/muyu/demos/web/config/SecondaryDataSourceConfig.java new file mode 100644 index 0000000..5c915e9 --- /dev/null +++ b/src/main/java/com/muyu/demos/web/config/SecondaryDataSourceConfig.java @@ -0,0 +1,43 @@ +package com.muyu.demos.web.config;//package com.muyu.config; +// +//import org.springframework.beans.factory.annotation.Value; +//import org.springframework.boot.context.properties.ConfigurationProperties; +//import org.springframework.boot.jdbc.DataSourceBuilder; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +// +//import javax.sql.DataSource; +// +///** +// * 第二个数据源 SecondaryDataSourceConfig +// * +// * @author Yangle +// * Date 2024/6/2 22:03 +// */ +//@Configuration +//public class SecondaryDataSourceConfig { +// +// @Value("${datasource.secondary.url}") +// private String url; +// +// @Value("${datasource.secondary.username}") +// private String username; +// +// @Value("${datasource.secondary.password}") +// private String password; +// +// @Value("${datasource.secondary.driver-class-name}") +// private String driverClassName; +// +// @Bean(name = "secondaryDataSource") +// @ConfigurationProperties(prefix = "datasource.secondary") +// public DataSource secondaryDataSource() { +// return DataSourceBuilder.create() +// .url(url) +// .username(username) +// .password(password) +// .driverClassName(driverClassName) +// .build(); +// } +// +//} \ No newline at end of file diff --git a/src/main/java/com/muyu/iotDB/config/IotDBSessionConfig.java b/src/main/java/com/muyu/iotDB/config/IotDBSessionConfig.java new file mode 100644 index 0000000..863e947 --- /dev/null +++ b/src/main/java/com/muyu/iotDB/config/IotDBSessionConfig.java @@ -0,0 +1,198 @@ +package com.muyu.iotDB.config; + +import lombok.extern.log4j.Log4j2; +import org.apache.iotdb.rpc.IoTDBConnectionException; +import org.apache.iotdb.rpc.StatementExecutionException; +import org.apache.iotdb.session.Session; +import org.apache.iotdb.session.SessionDataSet; +import org.apache.iotdb.session.util.Version; +import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType; +import org.apache.iotdb.tsfile.write.record.Tablet; +import org.apache.iotdb.tsfile.write.schema.MeasurementSchema; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; + +import java.rmi.ServerException; +import java.util.ArrayList; +import java.util.List; + +/** + * IoTDB配置 IotDBSessionConfig + * + * @author Yangle + * Date 2024/6/16 10:37 + */ + +@Log4j2 +@Component +@Configuration +public class IotDBSessionConfig { + + private static Session session; + private static final String LOCAL_HOST = "127.0.0.1"; + + @Bean + public Session getSession() throws IoTDBConnectionException, StatementExecutionException { + if (session == null) { + log.info("正在连接iotdb......."); + session = new Session.Builder().host(LOCAL_HOST).port(6667).username("root").password("root").version(Version.V_0_13).build(); + session.open(false); + session.setFetchSize(100); + log.info("iotdb连接成功~"); + // 设置时区 + session.setTimeZone("+08:00"); + } + return session; + } + + /** + * description: 带有数据类型的添加操作 - insertRecord没有指定类型 + * author: zhouhong + * + * @param * @param deviceId:节点路径如:root.a1eaKSRpRty.CA3013A303A25467 + * time:时间戳 + * measurementsList:物理量 即:属性 + * type:数据类型: BOOLEAN((byte)0), INT32((byte)1),INT64((byte)2),FLOAT((byte)3),DOUBLE((byte)4),TEXT((byte)5),VECTOR((byte)6); + * valuesList:属性值 --- 属性必须与属性值一一对应 + * @return + */ + public void insertRecordType(String deviceId, Long time, List measurementsList, TSDataType type, List valuesList) throws StatementExecutionException, IoTDBConnectionException, ServerException { + if (measurementsList.size() != valuesList.size()) { + throw new ServerException("measurementsList 与 valuesList 值不对应"); + } + List types = new ArrayList<>(); + measurementsList.forEach(item -> { + types.add(type); + }); + session.insertRecord(deviceId, time, measurementsList, types, valuesList); + } + + /** + * description: 带有数据类型的添加操作 - insertRecord没有指定类型 + * author: zhouhong + * + * @param deviceId:节点路径如:root.a1eaKSRpRty.CA3013A303A25467 + * @param time:时间戳 + * @param measurementsList:物理量 即:属性 + * @param valuesList:属性值 --- 属性必须与属性值一一对应 + * @return + */ + public void insertRecord(String deviceId, Long time, List measurementsList, List valuesList) throws StatementExecutionException, IoTDBConnectionException, ServerException { + if (measurementsList.size() == valuesList.size()) { + session.insertRecord(deviceId, time, measurementsList, valuesList); + } else { + log.error("measurementsList 与 valuesList 值不对应"); + } + } + + /** + * description: 批量插入 + * author: zhouhong + */ + public void insertRecords(List deviceIdList, List timeList, List> measurementsList, List> valuesList) throws StatementExecutionException, IoTDBConnectionException, ServerException { + if (measurementsList.size() == valuesList.size()) { + session.insertRecords(deviceIdList, timeList, measurementsList, valuesList); + } else { + log.error("measurementsList 与 valuesList 值不对应"); + } + } + + /** + * description: 插入操作 + * author: zhouhong + * + * @param deviceId:节点路径如:root.a1eaKSRpRty.CA3013A303A25467 + * @param time:时间戳 + * @param schemaList: 属性值 + 数据类型 例子: List schemaList = new ArrayList<>(); schemaList.add(new MeasurementSchema("breath", TSDataType.INT64)); + * @param maxRowNumber: + * @return + */ + public void insertTablet(String deviceId, Long time, List schemaList, List valueList, int maxRowNumber) throws StatementExecutionException, IoTDBConnectionException { + + Tablet tablet = new Tablet(deviceId, schemaList, maxRowNumber); + // 向iotdb里面添加数据 + int rowIndex = tablet.rowSize++; + tablet.addTimestamp(rowIndex, time); + for (int i = 0; i < valueList.size(); i++) { + tablet.addValue(schemaList.get(i).getMeasurementId(), rowIndex, valueList.get(i)); + } + if (tablet.rowSize == tablet.getMaxRowNumber()) { + session.insertTablet(tablet, true); + tablet.reset(); + } + if (tablet.rowSize != 0) { + session.insertTablet(tablet); + tablet.reset(); + } + } + + /** + * description: 根据SQL查询 + * author: zhouhong + */ + public SessionDataSet query(String sql) throws StatementExecutionException, IoTDBConnectionException { + return session.executeQueryStatement(sql); + } + + /** + * description: 删除分组 如 root.a1eaKSRpRty + * author: zhouhong + * + * @param groupName:分组名称 + * @return + */ + public void deleteStorageGroup(String groupName) throws StatementExecutionException, IoTDBConnectionException { + session.deleteStorageGroup(groupName); + } + + /** + * description: 根据Timeseries删除 如:root.a1eaKSRpRty.CA3013A303A25467.breath (个人理解:为具体的物理量) + * author: zhouhong + */ + public void deleteTimeseries(String timeseries) throws StatementExecutionException, IoTDBConnectionException { + session.deleteTimeseries(timeseries); + } + + /** + * description: 根据Timeseries批量删除 + * author: zhouhong + */ + public void deleteTimeserieList(List timeseriesList) throws StatementExecutionException, IoTDBConnectionException { + session.deleteTimeseries(timeseriesList); + } + + /** + * description: 根据分组批量删除 + * author: zhouhong + */ + public void deleteStorageGroupList(List storageGroupList) throws StatementExecutionException, IoTDBConnectionException { + session.deleteStorageGroups(storageGroupList); + } + + /** + * description: 根据路径和结束时间删除 结束时间之前的所有数据 + * author: zhouhong + */ + public void deleteDataByPathAndEndTime(String path, Long endTime) throws StatementExecutionException, IoTDBConnectionException { + session.deleteData(path, endTime); + } + + /** + * description: 根据路径集合和结束时间批量删除 结束时间之前的所有数据 + * author: zhouhong + */ + public void deleteDataByPathListAndEndTime(List pathList, Long endTime) throws StatementExecutionException, IoTDBConnectionException { + session.deleteData(pathList, endTime); + } + + /** + * description: 根据路径集合和时间段批量删除 + * author: zhouhong + */ + public void deleteDataByPathListAndTime(List pathList, Long startTime, Long endTime) throws StatementExecutionException, IoTDBConnectionException { + session.deleteData(pathList, startTime, endTime); + } + +} + diff --git a/src/main/java/com/muyu/iotDB/controller/IotDbController.java b/src/main/java/com/muyu/iotDB/controller/IotDbController.java new file mode 100644 index 0000000..446c4c0 --- /dev/null +++ b/src/main/java/com/muyu/iotDB/controller/IotDbController.java @@ -0,0 +1,61 @@ +package com.muyu.iotDB.controller; + + +import com.muyu.iotDB.config.IotDBSessionConfig; +import com.muyu.iotDB.data.IotDbParam; +import com.muyu.iotDB.data.ResponseData; +import com.muyu.iotDB.service.IotDbServer; +import lombok.extern.log4j.Log4j2; +import org.apache.iotdb.rpc.IoTDBConnectionException; +import org.apache.iotdb.rpc.StatementExecutionException; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.rmi.ServerException; + +/** + * description: iotdb 控制层 + * date: 2022/8/15 21:50 + * author: zhouhong + */ +@Log4j2 +@RestController +public class IotDbController { + + @Resource + private IotDbServer iotDbServer; + @Resource + private IotDBSessionConfig iotDBSessionConfig; + + + /** + * 插入数据 + * @param iotDbParam + */ + @PostMapping("/api/device/insert") + public ResponseData insert(@RequestBody IotDbParam iotDbParam) throws StatementExecutionException, ServerException, IoTDBConnectionException { + iotDbServer.insertData(iotDbParam); + return ResponseData.success(); + } + + /** + * 查询数据 + * @param iotDbParam + */ + @PostMapping("/api/device/queryData") + public ResponseData queryDataFromIotDb(@RequestBody IotDbParam iotDbParam) throws Exception { + return ResponseData.success(iotDbServer.queryDataFromIotDb(iotDbParam)); + } + + /** + * 删除分组 + * @return + */ + @PostMapping("/api/device/deleteGroup") + public ResponseData deleteGroup() throws StatementExecutionException, IoTDBConnectionException { + iotDBSessionConfig.deleteStorageGroup("root.a1eaKSRpRty"); + iotDBSessionConfig.deleteStorageGroup("root.smartretirement"); + return ResponseData.success(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/muyu/iotDB/data/ErrorResponseData.java b/src/main/java/com/muyu/iotDB/data/ErrorResponseData.java new file mode 100644 index 0000000..337002c --- /dev/null +++ b/src/main/java/com/muyu/iotDB/data/ErrorResponseData.java @@ -0,0 +1,71 @@ +package com.muyu.iotDB.data; + +public class ErrorResponseData extends ResponseData{ + private String exceptionClazz; + + ErrorResponseData(String message) { + super(false, DEFAULT_ERROR_CODE, message, message, (Object)null); + } + + public ErrorResponseData(Integer code, String message) { + super(false, code, message, message, (Object)null); + } + + ErrorResponseData(Integer code, String message, Object object) { + super(false, code, message, object); + } + + ErrorResponseData(Integer code, String message, String localizedMsg, Object object) { + super(false, code, message, localizedMsg, object); + } + + public boolean equals(final Object o) { + if (o == this) { + return true; + } else if (!(o instanceof ErrorResponseData)) { + return false; + } else { + ErrorResponseData other = (ErrorResponseData)o; + if (!other.canEqual(this)) { + return false; + } else if (!super.equals(o)) { + return false; + } else { + Object this$exceptionClazz = this.getExceptionClazz(); + Object other$exceptionClazz = other.getExceptionClazz(); + if (this$exceptionClazz == null) { + if (other$exceptionClazz != null) { + return false; + } + } else if (!this$exceptionClazz.equals(other$exceptionClazz)) { + return false; + } + + return true; + } + } + } + + protected boolean canEqual(final Object other) { + return other instanceof ErrorResponseData; + } + + public int hashCode() { + int result = super.hashCode(); + Object $exceptionClazz = this.getExceptionClazz(); + result = result * 59 + ($exceptionClazz == null ? 43 : $exceptionClazz.hashCode()); + return result; + } + + public String getExceptionClazz() { + return this.exceptionClazz; + } + + public void setExceptionClazz(final String exceptionClazz) { + this.exceptionClazz = exceptionClazz; + } + + public String toString() { + return "ErrorResponseData(exceptionClazz=" + this.getExceptionClazz() + ")"; + } +} diff --git a/src/main/java/com/muyu/iotDB/data/IotDbParam.java b/src/main/java/com/muyu/iotDB/data/IotDbParam.java new file mode 100644 index 0000000..98f06e6 --- /dev/null +++ b/src/main/java/com/muyu/iotDB/data/IotDbParam.java @@ -0,0 +1,40 @@ +package com.muyu.iotDB.data; + +import lombok.Data; +/** + * description: 入参 + * date: 2022/8/15 21:53 + * author: zhouhong + */ +@Data +public class IotDbParam { + /*** + * 产品PK + */ + private String pk; + /*** + * 设备号 + */ + private String sn; + /*** + * 时间 + */ + private Long time; + /*** + * 实时呼吸 + */ + private String breath; + /*** + * 实时心率 + */ + private String heart; + /*** + * 查询开始时间 + */ + private String startTime; + /*** + * 查询结束时间 + */ + private String endTime; + +} \ No newline at end of file diff --git a/src/main/java/com/muyu/iotDB/data/IotDbResult.java b/src/main/java/com/muyu/iotDB/data/IotDbResult.java new file mode 100644 index 0000000..66324b5 --- /dev/null +++ b/src/main/java/com/muyu/iotDB/data/IotDbResult.java @@ -0,0 +1,33 @@ +package com.muyu.iotDB.data; + +import lombok.Data; + +/** + * description: 返回结果 + * date: 2022/8/15 21:56 + * author: zhouhong + */ +@Data +public class IotDbResult { + /*** + * 时间 + */ + private String time; + /*** + * 产品PK + */ + private String pk; + /*** + * 设备号 + */ + private String sn; + /*** + * 实时呼吸 + */ + private String breath; + /*** + * 实时心率 + */ + private String heart; + +} \ No newline at end of file diff --git a/src/main/java/com/muyu/iotDB/data/ResponseData.java b/src/main/java/com/muyu/iotDB/data/ResponseData.java new file mode 100644 index 0000000..614e232 --- /dev/null +++ b/src/main/java/com/muyu/iotDB/data/ResponseData.java @@ -0,0 +1,212 @@ +package com.muyu.iotDB.data; + +import lombok.Data; + +@Data +public class ResponseData { + public static final String DEFAULT_SUCCESS_MESSAGE = "请求成功"; + public static final String DEFAULT_ERROR_MESSAGE = "网络异常"; + public static final Integer DEFAULT_SUCCESS_CODE = 200; + public static final Integer DEFAULT_ERROR_CODE = 500; + private Boolean success; + private Integer code; + private String message; + private String localizedMsg; + private Object data; + + public ResponseData() { + } + + public ResponseData(Boolean success, Integer code, String message, Object data) { + this.success = success; + this.code = code; + this.message = message; + this.data = data; + } + + public ResponseData(Boolean success, Integer code, String message, String localizedMsg, Object data) { + this.success = success; + this.code = code; + this.message = message; + this.localizedMsg = localizedMsg; + this.data = data; + } + + public ResponseData(Boolean success, Integer code, String message) { + this.success = success; + this.code = code; + this.message = message; + } + + public static SuccessResponseData success() { + return new SuccessResponseData(); + } + + public static SuccessResponseData success(Object object) { + return new SuccessResponseData(object); + } + + public static SuccessResponseData success(Integer code, String message, Object object) { + return new SuccessResponseData(code, message, object); + } + + public static SuccessResponseData success(Integer code, String message) { + return new SuccessResponseData(code, message); + } + + public static SuccessResponseData success(Integer code, String message, String localizedMsg, Object object) { + return new SuccessResponseData(code, message, localizedMsg, object); + } + + public static ErrorResponseData error(String message) { + return new ErrorResponseData(message); + } + + public static ErrorResponseData error(Integer code, String message) { + return new ErrorResponseData(code, message); + } + + public static ErrorResponseData error(Integer code, String message, Object object) { + return new ErrorResponseData(code, message, object); + } + + public static ErrorResponseData error(Integer code, String message, String localizedMsg, Object object) { + return new ErrorResponseData(code, message, localizedMsg, object); + } + + public Boolean getSuccess() { + return this.success; + } + + public Integer getCode() { + return this.code; + } + + public String getMessage() { + return this.message; + } + + public String getLocalizedMsg() { + return this.localizedMsg; + } + + public Object getData() { + return this.data; + } + + public void setSuccess(final Boolean success) { + this.success = success; + } + + public void setCode(final Integer code) { + this.code = code; + } + + public void setMessage(final String message) { + this.message = message; + } + + public void setLocalizedMsg(final String localizedMsg) { + this.localizedMsg = localizedMsg; + } + + public void setData(final Object data) { + this.data = data; + } + + public boolean equals(final Object o) { + if (o == this) { + return true; + } else if (!(o instanceof ResponseData)) { + return false; + } else { + ResponseData other = (ResponseData)o; + if (!other.canEqual(this)) { + return false; + } else { + label71: { + Object this$success = this.getSuccess(); + Object other$success = other.getSuccess(); + if (this$success == null) { + if (other$success == null) { + break label71; + } + } else if (this$success.equals(other$success)) { + break label71; + } + + return false; + } + + Object this$code = this.getCode(); + Object other$code = other.getCode(); + if (this$code == null) { + if (other$code != null) { + return false; + } + } else if (!this$code.equals(other$code)) { + return false; + } + + label57: { + Object this$message = this.getMessage(); + Object other$message = other.getMessage(); + if (this$message == null) { + if (other$message == null) { + break label57; + } + } else if (this$message.equals(other$message)) { + break label57; + } + + return false; + } + + Object this$localizedMsg = this.getLocalizedMsg(); + Object other$localizedMsg = other.getLocalizedMsg(); + if (this$localizedMsg == null) { + if (other$localizedMsg != null) { + return false; + } + } else if (!this$localizedMsg.equals(other$localizedMsg)) { + return false; + } + + Object this$data = this.getData(); + Object other$data = other.getData(); + if (this$data == null) { + if (other$data == null) { + return true; + } + } else if (this$data.equals(other$data)) { + return true; + } + + return false; + } + } + } + + protected boolean canEqual(final Object other) { + return other instanceof ResponseData; + } + + public int hashCode() { + int result1 = 1; + Object $success = this.getSuccess(); + int result = result1 * 59 + ($success == null ? 43 : $success.hashCode()); + Object $code = this.getCode(); + result = result * 59 + ($code == null ? 43 : $code.hashCode()); + Object $message = this.getMessage(); + result = result * 59 + ($message == null ? 43 : $message.hashCode()); + Object $localizedMsg = this.getLocalizedMsg(); + result = result * 59 + ($localizedMsg == null ? 43 : $localizedMsg.hashCode()); + Object $data = this.getData(); + result = result * 59 + ($data == null ? 43 : $data.hashCode()); + return result; + } + + public String toString() { + return "ResponseData(success=" + this.getSuccess() + ", code=" + this.getCode() + ", message=" + this.getMessage() + ", localizedMsg=" + this.getLocalizedMsg() + ", data=" + this.getData() + ")"; + } +} diff --git a/src/main/java/com/muyu/iotDB/data/SuccessResponseData.java b/src/main/java/com/muyu/iotDB/data/SuccessResponseData.java new file mode 100644 index 0000000..73eb739 --- /dev/null +++ b/src/main/java/com/muyu/iotDB/data/SuccessResponseData.java @@ -0,0 +1,23 @@ +package com.muyu.iotDB.data; + +public class SuccessResponseData extends ResponseData{ + public SuccessResponseData() { + super(true, DEFAULT_SUCCESS_CODE, "请求成功", "请求成功", (Object)null); + } + + public SuccessResponseData(Object object) { + super(true, DEFAULT_SUCCESS_CODE, "请求成功", "请求成功", object); + } + + public SuccessResponseData(Integer code, String message, Object object) { + super(true, code, message, message, object); + } + + public SuccessResponseData(Integer code, String message, String localizedMsg, Object object) { + super(true, code, message, localizedMsg, object); + } + + public SuccessResponseData(Integer code, String message) { + super(true, code, message); + } +} diff --git a/src/main/java/com/muyu/iotDB/service/IotDbServer.java b/src/main/java/com/muyu/iotDB/service/IotDbServer.java new file mode 100644 index 0000000..b121f02 --- /dev/null +++ b/src/main/java/com/muyu/iotDB/service/IotDbServer.java @@ -0,0 +1,20 @@ +package com.muyu.iotDB.service; + +import com.muyu.iotDB.data.IotDbParam; +import org.apache.iotdb.rpc.IoTDBConnectionException; +import org.apache.iotdb.rpc.StatementExecutionException; + +import java.rmi.ServerException; + +/** + * IotDbServer + * + * @author Yangle + * Date 2024/6/16 10:41 + */ +public interface IotDbServer { + void insertData(IotDbParam iotDbParam) throws ServerException, IoTDBConnectionException, StatementExecutionException; + + Object queryDataFromIotDb(IotDbParam iotDbParam) throws Exception; + +} diff --git a/src/main/java/com/muyu/iotDB/service/impl/IotDbServerImpl.java b/src/main/java/com/muyu/iotDB/service/impl/IotDbServerImpl.java new file mode 100644 index 0000000..d6dfca4 --- /dev/null +++ b/src/main/java/com/muyu/iotDB/service/impl/IotDbServerImpl.java @@ -0,0 +1,108 @@ +package com.muyu.iotDB.service.impl; + +import com.muyu.iotDB.config.IotDBSessionConfig; +import com.muyu.iotDB.data.IotDbParam; +import com.muyu.iotDB.data.IotDbResult; + +import com.muyu.iotDB.service.IotDbServer; +import lombok.extern.log4j.Log4j2; +import org.apache.iotdb.rpc.IoTDBConnectionException; +import org.apache.iotdb.rpc.StatementExecutionException; +import org.apache.iotdb.session.SessionDataSet; +import org.apache.iotdb.tsfile.read.common.Field; +import org.apache.iotdb.tsfile.read.common.RowRecord; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.rmi.ServerException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * description: iot服务实现类 + * date: 2022/8/15 9:43 + * author: zhouhong + */ + +@Log4j2 +@Service +public class IotDbServerImpl implements IotDbServer { + + @Resource + private IotDBSessionConfig iotDBSessionConfig; + + @Override + public void insertData(IotDbParam iotDbParam) throws ServerException, IoTDBConnectionException, StatementExecutionException { + // iotDbParam: 模拟设备上报消息 + // bizkey: 业务唯一key PK :产品唯一编码 SN:设备唯一编码 + String deviceId = "root.bizkey."+ iotDbParam.getPk() + "." + iotDbParam.getSn(); + // 将设备上报的数据存入数据库(时序数据库) + List measurementsList = new ArrayList<>(); + measurementsList.add("heart"); + measurementsList.add("breath"); + List valuesList = new ArrayList<>(); + valuesList.add(String.valueOf(iotDbParam.getHeart())); + valuesList.add(String.valueOf(iotDbParam.getBreath())); + iotDBSessionConfig.insertRecord(deviceId, iotDbParam.getTime(), measurementsList, valuesList); + } + + @Override + public List queryDataFromIotDb(IotDbParam iotDbParam) throws Exception { + List iotDbResultList = new ArrayList<>(); + + if (null != iotDbParam.getPk() && null != iotDbParam.getSn()) { + String sql = "select * from root.bizkey."+ iotDbParam.getPk() +"." + iotDbParam.getSn() + " where time >= " + + iotDbParam.getStartTime() + " and time < " + iotDbParam.getEndTime(); + SessionDataSet sessionDataSet = iotDBSessionConfig.query(sql); + List columnNames = sessionDataSet.getColumnNames(); + List titleList = new ArrayList<>(); + // 排除Time字段 -- 方便后面后面拼装数据 + for (int i = 1; i < columnNames.size(); i++) { + String[] temp = columnNames.get(i).split("\\."); + titleList.add(temp[temp.length - 1]); + } + // 封装处理数据 + packagingData(iotDbParam, iotDbResultList, sessionDataSet, titleList); + } else { + log.info("PK或者SN不能为空!!"); + } + return iotDbResultList; + } + /** + * 封装处理数据 + * @param iotDbParam + * @param iotDbResultList + * @param sessionDataSet + * @param titleList + * @throws StatementExecutionException + * @throws IoTDBConnectionException + */ + private void packagingData(IotDbParam iotDbParam, List iotDbResultList, SessionDataSet sessionDataSet, List titleList) + throws StatementExecutionException, IoTDBConnectionException { + int fetchSize = sessionDataSet.getFetchSize(); + if (fetchSize > 0) { + while (sessionDataSet.hasNext()) { + IotDbResult iotDbResult = new IotDbResult(); + RowRecord next = sessionDataSet.next(); + List fields = next.getFields(); + String timeString = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(next.getTimestamp()); + iotDbResult.setTime(timeString); + Map map = new HashMap<>(); + + for (int i = 0; i < fields.size(); i++) { + Field field = fields.get(i); + // 这里的需要按照类型获取 + map.put(titleList.get(i), field.getObjectValue(field.getDataType()).toString()); + } + iotDbResult.setTime(timeString); + iotDbResult.setPk(iotDbParam.getPk()); + iotDbResult.setSn(iotDbParam.getSn()); + iotDbResult.setHeart(map.get("heart")); + iotDbResult.setBreath(map.get("breath")); + iotDbResultList.add(iotDbResult); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/muyu/kafka/SimpleKafkaConsumer.java b/src/main/java/com/muyu/kafka/SimpleKafkaConsumer.java new file mode 100644 index 0000000..6d3527d --- /dev/null +++ b/src/main/java/com/muyu/kafka/SimpleKafkaConsumer.java @@ -0,0 +1,68 @@ +package com.muyu.kafka; + +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson2.JSON; +import com.muyu.iotDB.service.IotDbServer; +import com.muyu.mqtt.dao.MessageData; +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; + +/** + * 定时器 SimpleKafkaConsumer + * + * @author Yangle + * Date 2024/6/16 22:18 + */ +@Component +public class SimpleKafkaConsumer { + + @Resource + private IotDbServer iotDbServer; + + + @Scheduled(cron = "0 0/5 * * * ?") + public void consumer() { + List messageDataList = new ArrayList<>(); + // 配置Kafka消费者属性 + Properties props = new Properties(); + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); + props.put(ConsumerConfig.GROUP_ID_CONFIG, "test1"); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + + // 创建Kafka消费者实例 + KafkaConsumer consumer = new KafkaConsumer<>(props); + + // 订阅主题 + consumer.subscribe(Collections.singletonList("test1")); + + // 持续消费消息 + while (true) { + ConsumerRecords records = consumer.poll(Duration.ofMillis(100)); + for (ConsumerRecord record : records) { + System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value()); + String value = record.value(); + MessageData messageData = JSONObject.parseObject(value, MessageData.class); + messageDataList.add(messageData); + } + } + + } + +} + diff --git a/src/main/java/com/muyu/mqtt/MessageCallbackService.java b/src/main/java/com/muyu/mqtt/MessageCallbackService.java new file mode 100644 index 0000000..e430942 --- /dev/null +++ b/src/main/java/com/muyu/mqtt/MessageCallbackService.java @@ -0,0 +1,94 @@ +package com.muyu.mqtt; + + + +import com.muyu.mqtt.dao.MessageData; +import com.muyu.utils.ConversionUtil; +import lombok.extern.log4j.Log4j2; +import org.apache.kafka.clients.producer.ProducerRecord; +import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; +import org.eclipse.paho.client.mqttv3.MqttCallback; +import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.core.KafkaAdmin; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.stereotype.Service; + +/** + * 回执消息类 MessageCallbackService + * + * @author Yangle + * Date 2024/6/6 15:08 + */ +@Service +@Log4j2 +public class MessageCallbackService implements MqttCallback { + + @Autowired + private KafkaTemplate kafkaTemplate; + @Autowired + private KafkaAdmin kafkaAdmin; + + @Override + public void connectionLost(Throwable cause) { + System.out.println("connectionLost:"+cause.getMessage()); + } + + + @Override + public void messageArrived(String topic, MqttMessage mqttMessage) { + log.info("topic:{}",topic); + log.info("Qos:{}",mqttMessage.getQos()); + log.info("message content:{}",new String(mqttMessage.getPayload())); + String s = new String(mqttMessage.getPayload()); + MessageData main = ConversionUtil.main(s); +// try { +// List newTopicList = createTopic(topic,main); +// for (NewTopic newTopic : newTopicList) { +//// int partitionIndex = getPartitionIndexWithWeight(newTopic.getPartitions()); +// kafkaAdmin.createOrModifyTopics(newTopic); +// ProducerRecord stringObjectProducerRecord = new ProducerRecord<>(topic, main.getVin(), main.toString()); +// kafkaTemplate.send(stringObjectProducerRecord); +// } +// } catch (Exception e) { +// e.printStackTrace(); +// } + ProducerRecord stringObjectProducerRecord = new ProducerRecord<>(topic, main.getVin(), main.toString()); + kafkaTemplate.send(stringObjectProducerRecord); + } + private int currentPartitionIndex = 0; + + +// public List createTopic(String topic,MessageData messageData) { +// // 创建Kafka生产者实例 +// List newTopics = new ArrayList<>(); +// newTopics.add(new NewTopic(topic, 8, (short) 1)); +//// ProducerRecord stringObjectProducerRecord = new ProducerRecord<>(topic, messageData.getVin(), messageData.toString()); +//// kafkaTemplate.send(stringObjectProducerRecord); +// return newTopics; +// } + +// public static int getPartitionIndexWithWeight(List partitions) { +// int totalWeight = 0; +// for (PartitionInfo partition : partitions) { +// totalWeight += partition.getReplicas().size(); +// } +// +// int randomNum = new Random().nextInt(totalWeight); +// int currentWeight = 0; +// for (int i = 0; i < partitions.size(); i++) { +// currentWeight += partitions.get(i).getReplicas().size(); +// if (randomNum < currentWeight) { +// return i; +// } +// } +// +// return -1; // should never reach here +// } + + + @Override + public void deliveryComplete(IMqttDeliveryToken token) { + System.out.println("deliveryComplete---------" + token.isComplete()); + } +} diff --git a/src/main/java/com/muyu/mqtt/MqttFactory.java b/src/main/java/com/muyu/mqtt/MqttFactory.java new file mode 100644 index 0000000..9554ff5 --- /dev/null +++ b/src/main/java/com/muyu/mqtt/MqttFactory.java @@ -0,0 +1,46 @@ +package com.muyu.mqtt; + +import lombok.AllArgsConstructor; +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; +import org.springframework.stereotype.Service; + +/** + * mqtt配置 MqttFactory + * + * @author Yangle + * Date 2024/6/6 15:10 + */ +@Service +@AllArgsConstructor +public class MqttFactory { + + private final MessageCallbackService messageCallbackService; + + public MqttClient creatClient(MqttProperties mqttProperties) { + MqttClient client =null; + try { + client = new MqttClient(mqttProperties.getBroker(), mqttProperties.getClientid(), new MemoryPersistence()); + MqttConnectOptions options = new MqttConnectOptions(); + + // 连接参数 + if (mqttProperties.isLong()) + { + options.setUserName(mqttProperties.getUsername()); + options.setPassword(mqttProperties.getPassword().toCharArray()); + } + options.setConnectionTimeout(60); + options.setKeepAliveInterval(60); + client.connect(options); + client.setCallback(messageCallbackService); + client.subscribe(mqttProperties.getTopic(),0); + + } catch (MqttException e) { + throw new RuntimeException(e); + } + + return client; + } +} diff --git a/src/main/java/com/muyu/mqtt/MqttProperties.java b/src/main/java/com/muyu/mqtt/MqttProperties.java new file mode 100644 index 0000000..0fade3d --- /dev/null +++ b/src/main/java/com/muyu/mqtt/MqttProperties.java @@ -0,0 +1,40 @@ +package com.muyu.mqtt; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.apache.commons.lang3.StringUtils; + +/** + * 配置文件 MqttProperties + * + * @author Yangle + * Date 2024/5/29 20:06 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class MqttProperties { + + private String broker; + private String topic ; + private String username; + private String password; + private String clientid; + + public static MqttProperties configBuild(String ip,String topic){ + return MqttProperties.builder() + .broker("tcp://"+ip+":1883") + .topic(topic) + .clientid("protocol-parsing") + .build(); + } + + public boolean isLong(){ + return !StringUtils.isBlank(this.username) && !StringUtils.isBlank(this.password); + } + + +} diff --git a/src/main/java/com/muyu/mqtt/MsgHandler.java b/src/main/java/com/muyu/mqtt/MsgHandler.java new file mode 100644 index 0000000..aa95742 --- /dev/null +++ b/src/main/java/com/muyu/mqtt/MsgHandler.java @@ -0,0 +1,37 @@ +package com.muyu.mqtt; + +import lombok.extern.log4j.Log4j2; +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 消费处理器 MsgHandler + * + * @author Yangle + * Date 2024/6/6 15:15 + */ +@Log4j2 +@Component +public class MsgHandler { + @Autowired + private MqttFactory mqttFactory; + @RabbitListener(queues = "ip") + public void msg(String msg){ + log.info("接收到消息:{}",msg); + + String[] split = msg.split(","); + for (String s : split) { + MqttProperties mqttProperties = MqttProperties.configBuild( + s, + "test1" + ); + log.error("接收到消息初始化信息:{}",mqttProperties); + MqttClient mqttClient = mqttFactory.creatClient(mqttProperties); + log.error("client创建成功:{}",mqttClient.getClientId()); + } + + + } +} diff --git a/src/main/java/com/muyu/mqtt/config/RabbitConfig.java b/src/main/java/com/muyu/mqtt/config/RabbitConfig.java new file mode 100644 index 0000000..8e2782d --- /dev/null +++ b/src/main/java/com/muyu/mqtt/config/RabbitConfig.java @@ -0,0 +1,47 @@ +package com.muyu.mqtt.config; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.ConsumerRecords; +import org.apache.kafka.clients.consumer.KafkaConsumer; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.DirectExchange; +import org.springframework.amqp.core.Queue; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.time.Duration; +import java.util.Collections; +import java.util.Properties; + +/** + * RabbitConfig + * + * @author Yangle + * Date 2024/6/6 15:17 + */ +@Configuration +public class RabbitConfig { + + + @Bean + public Queue autoDeleteQueue1() { + return new Queue("create.topic", true); + } + + @Bean + public DirectExchange directExchange() { + return new DirectExchange("topic.direct"); + } + + @Bean + public Binding binding(DirectExchange directExchange, + Queue autoDeleteQueue1 ) { + return BindingBuilder.bind(autoDeleteQueue1) + .to(directExchange) + .with("protocol-parsing"); + } + +} diff --git a/src/main/java/com/muyu/mqtt/dao/MessageData.java b/src/main/java/com/muyu/mqtt/dao/MessageData.java new file mode 100644 index 0000000..f13a356 --- /dev/null +++ b/src/main/java/com/muyu/mqtt/dao/MessageData.java @@ -0,0 +1,215 @@ +package com.muyu.mqtt.dao; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +/** + * 报文对象 MessageData + * + * @author Yangle + * Date 2024/6/7 17:15 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@SuperBuilder +public class MessageData { + + + /** + *vin + */ + private String vin; + /** + *时间戳 + */ + private String timestamp; + /** + *经度 + */ + private String longitude; + /** + *维度 + */ + private String latitude; + /** + *车速 + */ + private String speed; + /** + *总里程 + */ + private String mileage; + /** + *总电压 + */ + private String dischargeVoltage; + /** + *总电流 + */ + private String dischargeCurrent; + /** + *绝缘电阻 + */ + private String insulationResistance; + /** + *档位 + */ + private String gear; + /** + *加速踏板行程值 + */ + private String accelerationPedal; + /** + *制动踏板行程值 + */ + private String brakePedal; + /** + *燃料消耗率 + */ + private String fuelConsumption; + /** + *电机控制器温度 + */ + private String motorControllerTemperature; + /** + *电机转速 + */ + private String motorSpeed; + /** + *电机转矩 + */ + private String motorTorque; + /** + *电机温度 + */ + private String motorTemperature; + /** + *电机电压 + */ + private String motorVoltage; + /** + *电机电流 + */ + private String motorCurrent; + /** + *动力电池剩余电量SOC + */ + private String powerBattery; + /** + *当前状态允许的最大反馈功率 + */ + private String maxFeedbackPower; + /** + *当前状态允许最大放电功率 + */ + private String maxDischargePower; + /** + *BMS自检计数器 + */ + private String bmsSelfCheck; + /** + *动力电池充放电电流 + */ + private String powerBatteryCurrent; + /** + *动力电池负载端总电压V3 + */ + private String powerBatteryV3; + /** + *单次最大电压 + */ + private String maxVoltage; + /** + *单体电池最低电压 + */ + private String minVoltage; + /** + *单体电池最高温度 + */ + private String maxTemperature; + /** + *单体电池最低温度 + */ + private String minTemperature; + /** + *动力电池可用容量 + */ + private String availableCapacity; + /** + *车辆状态 + */ + private String vehicleStatus; + /** + *充电状态 + */ + private String chargeStatus; + /** + *运行状态 + */ + private String runStatus; + /** + *SOC + */ + private String soc; + /** + *可充电储能装置工作状态 + */ + private String chargeWorkStatus; + /** + *驱动电机状态 + */ + private String driveMotorStatus; + /** + *定位是否有效 + */ + private String location; + /** + *EAS + */ + private String eas; + /** + *PTC + */ + private String ptc; + /** + *EPS + */ + private String eps; + /** + *ABS + */ + private String abs; + /** + *MCU + */ + private String mcu; + /** + *动力电池加热状态 + */ + private String powerBatteryHeating; + /** + *动力电池当前状态 + */ + private String powerBatteryCurrentStatus; + /** + *动力电池保温状态 + */ + private String powerBatteryHeat; + /** + *DCDC + */ + private String dcdc; + /** + *CHG + */ + private String chg; + + + + + + +} diff --git a/src/main/java/com/muyu/rabbitmq/SubscriptionHandler.java b/src/main/java/com/muyu/rabbitmq/SubscriptionHandler.java new file mode 100644 index 0000000..e14fb50 --- /dev/null +++ b/src/main/java/com/muyu/rabbitmq/SubscriptionHandler.java @@ -0,0 +1,35 @@ +package com.muyu.rabbitmq; + +import com.muyu.rabbitmq.confilg.RabbitmqConfig; +import com.rabbitmq.client.impl.AMQImpl; +import lombok.extern.log4j.Log4j2; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + + +/** + * 监听车辆上线的信息 SubscriptionHandler + * + * @author Yangle + * Date 2024/6/6 14:24 + */ +@Component +@Log4j2 +public class SubscriptionHandler { + + @RabbitListener(queues = {RabbitmqConfig.QUEUE_INFORM_EMAIL}) + public void receive_email(Object msg, Message message, AMQImpl.Channel channel){ + System.out.println("QUEUE_INFORM_EMAIL msg"+msg); + } + //监听sms队列 + @RabbitListener(queues = "subscription") + public void receiveSms(Message message) { + try { + log.info("消费者得到的消息: {}" , new String(message.getBody())); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/com/muyu/rabbitmq/confilg/RabbitmqConfig.java b/src/main/java/com/muyu/rabbitmq/confilg/RabbitmqConfig.java new file mode 100644 index 0000000..78c24b3 --- /dev/null +++ b/src/main/java/com/muyu/rabbitmq/confilg/RabbitmqConfig.java @@ -0,0 +1,53 @@ +package com.muyu.rabbitmq.confilg; + +import org.springframework.amqp.core.*; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +/** + * rabbitMQ配置 RabbitmqConfig + * + * @author Yangle + * Date 2024/5/28 21:42 + */ +@Configuration +public class RabbitmqConfig { + public static final String QUEUE_INFORM_EMAIL = "queue_inform_email"; + public static final String QUEUE_INFORM_SMS = "disconnect_connect"; + public static final String EXCHANGE_TOPICS_INFORM="exchange_topics_inform"; + public static final String ROUTINGKEY_EMAIL="inform.#.email.#"; + public static final String ROUTINGKEY_SMS="inform.#.sms.#"; + + + @Bean(EXCHANGE_TOPICS_INFORM) + public Exchange EXCHANGE_TOPICS_INFORM(){ + //durable(true) 持久化,mq重启之后交换机还在 + return ExchangeBuilder.topicExchange(EXCHANGE_TOPICS_INFORM).durable(true).build(); + } + + //声明QUEUE_INFORM_EMAIL队列 + @Bean(QUEUE_INFORM_EMAIL) + public Queue QUEUE_INFORM_EMAIL(){ + return new Queue(QUEUE_INFORM_EMAIL); + } + //声明QUEUE_INFORM_SMS队列 + @Bean(QUEUE_INFORM_SMS) + public Queue QUEUE_INFORM_SMS(){ + return new Queue(QUEUE_INFORM_SMS); + } + + //ROUTINGKEY_EMAIL队列绑定交换机,指定routingKey + @Bean + public Binding BINDING_QUEUE_INFORM_EMAIL(@Qualifier(QUEUE_INFORM_EMAIL) Queue queue, + @Qualifier(EXCHANGE_TOPICS_INFORM) Exchange exchange){ + return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY_EMAIL).noargs(); + } + //ROUTINGKEY_SMS队列绑定交换机,指定routingKey + @Bean + public Binding BINDING_ROUTINGKEY_SMS(@Qualifier(QUEUE_INFORM_SMS) Queue queue, + @Qualifier(EXCHANGE_TOPICS_INFORM) Exchange exchange){ + return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY_SMS).noargs(); + } +} diff --git a/src/main/java/com/muyu/utils/CalculateCheckDigit.java b/src/main/java/com/muyu/utils/CalculateCheckDigit.java new file mode 100644 index 0000000..e73a533 --- /dev/null +++ b/src/main/java/com/muyu/utils/CalculateCheckDigit.java @@ -0,0 +1,44 @@ +package com.muyu.utils; + +/** + * 校验位计算 + */ +public class CalculateCheckDigit { + + /** + * 不去空格 + * @param sHex + * @return + */ + public static String makeCheck(String sHex){ + return makeCheckSum(sHex.replace(" ", "")); + } + + /** + * 计算校验位 ,返回十六进制校验位 + * */ + private static String makeCheckSum(String data) { + int dSum = 0; + int length = data.length(); + int index = 0; + // 遍历十六进制,并计算总和 + while (index < length) { + // 截取2位字符 + String s = data.substring(index, index + 2); + // 十六进制转成十进制 , 并计算十进制的总和 + dSum += Integer.parseInt(s, 16); + index = index + 2; + } + + // 用256取余,十六进制最大是FF,FF的十进制是255 + int mod = dSum % 256; + // 余数转成十六进制 + String checkSumHex = Integer.toHexString(mod); + length = checkSumHex.length(); + if (length < 2) { + // 校验位不足两位的,在前面补0 + checkSumHex = "0" + checkSumHex; + } + return checkSumHex; + } +} diff --git a/src/main/java/com/muyu/utils/ConversionUtil.java b/src/main/java/com/muyu/utils/ConversionUtil.java new file mode 100644 index 0000000..e0c3b82 --- /dev/null +++ b/src/main/java/com/muyu/utils/ConversionUtil.java @@ -0,0 +1,354 @@ +package com.muyu.utils; + +import com.muyu.mqtt.dao.MessageData; +import lombok.extern.log4j.Log4j2; + +import java.nio.charset.StandardCharsets; + + +@Log4j2 +public class ConversionUtil { + /** + * 字符串转化成为16进制字符串 + * @param s + * @return + */ + public static String strToSixteen(String s) { + StringBuilder sb = new StringBuilder(); + int length = s.length(); + for (int i = 0; i < length; i++) { + int ch = s.charAt(i); + String s4 = Integer.toHexString(ch); + sb.append(s4 + " "); + } + return sb.toString(); + } + + public static MessageData main (String args) { +// String str = "\n" + +// "Sinus
80No Change0
"; +// String strToSixteen = strToSixteen(str); +// System.out.println(str); +// System.out.println(str.length()); +// System.out.println(strToSixteen); +// System.out.println(strToSixteen.replace(" ", "").length()); + +// String hexStr = "7E 48 58 49 54 48 58 55 51 52 32 54 55 43 30 58 33 55 31 37 31 37 35 38 39 32 35 37 35 35 31 31 31 36 2e 37 36 34 36 35 30 30 33 39 2e 35 37 34 38 38 30 30 32 37 30 2e 30 30 32 30 2e 33 35 30 30 30 30 30 30 32 37 36 30 30 30 38 30 30 30 30 32 32 30 38 30 30 30 30 30 44 31 30 30 30 39 2e 30 30 30 33 32 30 30 30 30 34 34 37 34 39 37 38 36 30 31 30 39 30 30 30 32 32 32 30 30 35 32 38 34 30 30 30 30 37 35 38 38 34 2e 33 32 30 30 30 30 31 33 30 30 30 30 31 31 34 30 30 30 30 36 39 39 30 30 30 34 30 30 30 33 30 30 30 35 30 30 30 30 30 35 30 30 30 30 30 32 33 30 30 30 30 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 11 7E"; + String hexStringToString = hexStringToString(args); + System.out.println(args); + System.out.println(args.length()); + System.out.println(hexStringToString); + System.out.println(hexStringToString.length()); + //截取第一位和最后两位 + String substring = hexStringToString.substring(1, hexStringToString.length() - 2); + log.error("substring:{}",substring.length()); + //vin + String vin = substring.substring(0,17); +// log.error("length:{}",vin.length()); +// log.error("vin:{}",vin); + //时间戳 + String timestamp = substring.substring(17,30); +// log.error("length:{}",timestamp.length()); +// log.error("timestamp:{}",timestamp); +// //经度 + String longitude = substring.substring(30, 41); +// log.error("length:{}",longitude.length()); +// log.error("longitude:{}",longitude); +// //维度 + String latitude = substring.substring(41, 51); +// log.error("length:{}",latitude.length()); +// log.error("latitude:{}",latitude); +// //车速 + String speed = substring.substring(51, 57); + int length = speed.length(); +// log.error("length:{}",length); +// log.info("speed:{}",speed); + //总里程 + String mileage = substring.substring(57, 68); +// log.error("length:{}",mileage.length()); +// log.error("mileage:{}",mileage); + + //总电压 + String dischargeVoltage = substring.substring(68, 74); +// log.error("length:{}",dischargeVoltage.length()); +// log.error("dischargeVoltage:{}",dischargeVoltage); + + //总电流 + String dischargeCurrent = substring.substring(74, 79); +// log.error("length:{}",dischargeCurrent.length()); +// log.error("dischargeCurrent:{}",dischargeCurrent); + //绝缘电阻 + String insulationResistance = substring.substring(79, 88); +// log.error("length:{}",insulationResistance.length()); +// log.error("insulationResistance:{}",insulationResistance); +// //档位 + String gear = substring.substring(88, 89); +// log.error("length:{}",gear.length()); +// log.error("gear:{}",gear); + + //加速踏板行程值 + String accelerationPedal = substring.substring(89, 91); +// log.error("length:{}",accelerationPedal.length()); +// log.error("accelerationPedal:{}",accelerationPedal); + + //制动踏板行程值 + String brakePedal = substring.substring(91, 93); +// log.error("length:{}",brakePedal.length()); +// log.error("brakePedal:{}",brakePedal); + + //燃料消耗率 + String fuelConsumption = substring.substring(93, 98); +// log.error("length:{}",fuelConsumption.length()); +// log.error("fuelConsumption:{}",fuelConsumption); +//////////////// + //电机控制器温度 + String motorControllerTemperature = substring.substring(98, 104); +// log.error("length:{}",motorControllerTemperature.length()); +// log.error("motorControllerTemperature:{}",motorControllerTemperature); + + //电机转速 + String motorSpeed = substring.substring(104, 109); +// log.error("length:{}",motorSpeed.length()); +// log.error("motorSpeed:{}",motorSpeed); + + //电机转矩 + String motorTorque = substring.substring(109, 113); + // log.error("length:{}",motorTorque.length()); + // log.error("motorTorque:{}",motorTorque); + + //电机温度 + String motorTemperature = substring.substring(113, 119); + // log.error("length:{}",motorTemperature.length()); + // log.error("motorTemperature:{}",motorTemperature); + + //电机电压 + String motorVoltage = substring.substring(119, 124); +// log.error("length:{}",motorVoltage.length()); +// log.error("motorVoltage:{}",motorVoltage); + + //电机电流 + String motorCurrent = substring.substring(124, 132); +// log.error("length:{}",motorCurrent.length()); +// log.error("motorCurrent:{}",motorCurrent); + + //动力电池剩余电量SOC + String powerBattery = substring.substring(132, 138); +// log.error("length:{}",powerBattery.length()); +// log.error("powerBattery:{}",powerBattery); + + //当前状态允许的最大反馈功率 + String maxFeedbackPower = substring.substring(138, 144); +// log.error("length:{}",maxFeedbackPower.length()); +// log.error("maxFeedbackPower:{}",maxFeedbackPower); + + //当前状态允许最大放电功率 + String maxDischargePower = substring.substring(144, 150); +// log.error("length:{}",maxDischargePower.length()); +// log.error("maxDischargePower:{}",maxDischargePower); + + //BMS自检计数器 + String bmsSelfCheck = substring.substring(150, 152); +// log.error("length:{}",bmsSelfCheck.length()); +// log.error("bmsSelfCheck:{}",bmsSelfCheck); + + //动力电池充放电电流 + String powerBatteryCurrent = substring.substring(152, 157); +// log.error("length:{}",powerBatteryCurrent.length()); +// log.error("powerBatteryCurrent:{}",powerBatteryCurrent); + + //动力电池负载端总电压V3 + String powerBatteryV3 = substring.substring(157, 163); +// log.error("length:{}",powerBatteryV3.length()); +// log.error("powerBatteryV3:{}",powerBatteryV3); + + //单次最大电压 + String maxVoltage = substring.substring(163, 167); +// log.error("length:{}",maxVoltage.length()); +// log.error("maxVoltage:{}",maxVoltage); + + //单体电池最低电压 + String minVoltage = substring.substring(167, 171); +// log.error("length:{}",minVoltage.length()); +// log.error("minVoltage:{}",minVoltage); + + //单体电池最高温度 + String maxTemperature = substring.substring(171, 177); +// log.error("length:{}",maxTemperature.length()); +// log.error("maxTemperature:{}",maxTemperature); + + //单体电池最低温度 + String minTemperature = substring.substring(177, 183); +// log.error("length:{}",minTemperature.length()); +// log.error("minTemperature:{}",minTemperature); + + //动力电池可用容量 + String availableCapacity = substring.substring(183, 189); +// log.error("length:{}",availableCapacity.length()); +// log.error("availableCapacity:{}",availableCapacity); + + //车辆状态 + String vehicleStatus = substring.substring(189, 190); +// log.error("length:{}",vehicleStatus.length()); +// log.error("vehicleStatus:{}",vehicleStatus); + + //充电状态 + String chargeStatus = substring.substring(190, 191); +// log.error("length:{}",chargeStatus.length()); +// log.error("chargeStatus:{}",chargeStatus); + + //运行状态 + String runStatus = substring.substring(191, 192); +// log.error("length:{}",runStatus.length()); +// log.error("runStatus:{}",runStatus); + + //SOC + String soc = substring.substring(192, 193); +// log.error("length:{}",soc.length()); +// log.error("soc:{}",soc); + + //可充电储能装置工作状态 + String chargeWorkStatus = substring.substring(193, 194); +// log.error("length:{}",chargeWorkStatus.length()); +// log.error("chargeWorkStatus:{}",chargeWorkStatus); + + //驱动电机状态 + String driveMotorStatus = substring.substring(194, 195); +// log.error("length:{}",driveMotorStatus.length()); +// log.error("driveMotorStatus:{}",driveMotorStatus); + + //定位是否有效 + String location = substring.substring(195, 196); +// log.error("length:{}",location.length()); +// log.error("location:{}",location); + + //EAS + String eas = substring.substring(196, 197); +// log.error("length:{}",eas.length()); +// log.error("eas:{}",eas); + + //PTC + String ptc = substring.substring(197, 198); +// log.error("length:{}",ptc.length()); +// log.error("ptc:{}",ptc); + + //EPS + String eps = substring.substring(198, 199); +// log.error("length:{}",eps.length()); +// log.error("eps:{}",eps); + + //ABS + String abs = substring.substring(199, 200); +// log.error("length:{}",abs.length()); +// log.error("abs:{}",abs); + + //MCU + String mcu = substring.substring(200, 201); +// log.error("length:{}",mcu.length()); +// log.error("mcu:{}",mcu); + + //动力电池加热状态 + String powerBatteryHeating = substring.substring(201, 202); +// log.error("length:{}",powerBatteryHeating.length()); +// log.error("powerBatteryHeating:{}",powerBatteryHeating); + + //动力电池当前状态 + String powerBatteryCurrentStatus = substring.substring(202, 203); +// log.error("length:{}",powerBatteryCurrentStatus.length()); +// log.error("powerBatteryCurrentStatus:{}",powerBatteryCurrentStatus); + + //动力电池保温状态 + String powerBatteryHeat = substring.substring(203, 204); +// log.error("length:{}",powerBatteryHeat.length()); +// log.error("powerBatteryHeat:{}",powerBatteryHeat); + + //DCDC + String dcdc = substring.substring(204, 205); +// log.error("length:{}",dcdc.length()); +// log.error("dcdc:{}",dcdc); + + //CHG + String chg = substring.substring(205, 206); +// log.error("length:{}",chg.length()); +// log.error("chg:{}",chg); + + MessageData build = MessageData.builder() + .vin(vin) + .timestamp(timestamp) + .longitude(longitude) + .latitude(latitude) + .speed(speed) + .mileage(mileage) + .dischargeVoltage(dischargeVoltage) + .dischargeCurrent(dischargeCurrent) + .insulationResistance(insulationResistance) + .gear(gear) + .accelerationPedal(accelerationPedal) + .brakePedal(brakePedal) + .fuelConsumption(fuelConsumption) + .motorControllerTemperature(motorControllerTemperature) + .motorSpeed(motorSpeed) + .motorTorque(motorTorque) + .motorTemperature(motorTemperature) + .motorVoltage(motorVoltage) + .motorCurrent(motorCurrent) + .powerBattery(powerBattery) + .maxFeedbackPower(maxFeedbackPower) + .maxDischargePower(maxDischargePower) + .bmsSelfCheck(bmsSelfCheck) + .powerBatteryCurrent(powerBatteryCurrent) + .powerBatteryV3(powerBatteryV3) + .maxVoltage(maxVoltage) + .minVoltage(minVoltage) + .maxTemperature(maxTemperature) + .minTemperature(minTemperature) + .availableCapacity(availableCapacity) + .vehicleStatus(vehicleStatus) + .chargeStatus(chargeStatus) + .runStatus(runStatus) + .soc(soc) + .chargeWorkStatus(chargeWorkStatus) + .driveMotorStatus(driveMotorStatus) + .location(location) + .eas(eas) + .ptc(ptc) + .eps(eps) + .abs(abs) + .mcu(mcu) + .powerBatteryHeating(powerBatteryHeating) + .powerBatteryCurrentStatus(powerBatteryCurrentStatus) + .powerBatteryHeat(powerBatteryHeat) + .dcdc(dcdc) + .chg(chg) + .build(); + log.error("报文解析:{}",build); + + System.out.println(hexStringToString.length()); + return build; + } + + /** + * 16进制转换成为string类型字符串 + * @param s + * @return + */ + public static String hexStringToString(String s) { + if (s == null || s.equals("")) { + return null; + } + s = s.replace(" ", ""); + byte[] baKeyword = new byte[s.length() / 2]; + for (int i = 0; i < baKeyword.length; i++) { + try { + baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16)); + } catch (Exception e) { + e.printStackTrace(); + } + } + try { + s = new String(baKeyword, StandardCharsets.UTF_8); + } catch (Exception e1) { + e1.printStackTrace(); + } + return s; + } +} diff --git a/src/main/java/com/muyu/utils/Convert.java b/src/main/java/com/muyu/utils/Convert.java new file mode 100644 index 0000000..ceea1de --- /dev/null +++ b/src/main/java/com/muyu/utils/Convert.java @@ -0,0 +1,893 @@ +package com.muyu.utils; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.text.NumberFormat; +import java.util.Set; + +/** + * 类型转换器 + * + * @author ruoyi + */ +public class Convert { + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * + * @return 结果 + */ + public static String toStr (Object value, String defaultValue) { + if (null == value) { + return defaultValue; + } + if (value instanceof String) { + return (String) value; + } + return value.toString(); + } + + /** + * 转换为字符串
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * + * @return 结果 + */ + public static String toStr (Object value) { + return toStr(value, null); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * + * @return 结果 + */ + public static Character toChar (Object value, Character defaultValue) { + if (null == value) { + return defaultValue; + } + if (value instanceof Character) { + return (Character) value; + } + + final String valueStr = toStr(value, null); + return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0); + } + + /** + * 转换为字符
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * + * @return 结果 + */ + public static Character toChar (Object value) { + return toChar(value, null); + } + + /** + * 转换为byte
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * + * @return 结果 + */ + public static Byte toByte (Object value, Byte defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Byte) { + return (Byte) value; + } + if (value instanceof Number) { + return ((Number) value).byteValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Byte.parseByte(valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为byte
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * + * @return 结果 + */ + public static Byte toByte (Object value) { + return toByte(value, null); + } + + /** + * 转换为Short
+ * 如果给定的值为null,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * + * @return 结果 + */ + public static Short toShort (Object value, Short defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Short) { + return (Short) value; + } + if (value instanceof Number) { + return ((Number) value).shortValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Short.parseShort(valueStr.trim()); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为Short
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * + * @return 结果 + */ + public static Short toShort (Object value) { + return toShort(value, null); + } + + /** + * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * + * @return 结果 + */ + public static Number toNumber (Object value, Number defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Number) { + return (Number) value; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return NumberFormat.getInstance().parse(valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为Number
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * + * @return 结果 + */ + public static Number toNumber (Object value) { + return toNumber(value, null); + } + + /** + * 转换为int
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * + * @return 结果 + */ + public static Integer toInt (Object value, Integer defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Integer) { + return (Integer) value; + } + if (value instanceof Number) { + return ((Number) value).intValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Integer.parseInt(valueStr.trim()); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为int
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * + * @return 结果 + */ + public static Integer toInt (Object value) { + return toInt(value, null); + } + + /** + * 转换为Integer数组
+ * + * @param str 被转换的值 + * + * @return 结果 + */ + public static Integer[] toIntArray (String str) { + return toIntArray(",", str); + } + + /** + * 转换为Long数组
+ * + * @param str 被转换的值 + * + * @return 结果 + */ + public static Long[] toLongArray (String str) { + return toLongArray(",", str); + } + + /** + * 转换为Integer数组
+ * + * @param split 分隔符 + * @param split 被转换的值 + * + * @return 结果 + */ + public static Integer[] toIntArray (String split, String str) { + if (StringUtils.isEmpty(str)) { + return new Integer[]{}; + } + String[] arr = str.split(split); + final Integer[] ints = new Integer[arr.length]; + for (int i = 0 ; i < arr.length ; i++) { + final Integer v = toInt(arr[i], 0); + ints[i] = v; + } + return ints; + } + + /** + * 转换为Long数组
+ * + * @param split 分隔符 + * @param str 被转换的值 + * + * @return 结果 + */ + public static Long[] toLongArray (String split, String str) { + if (StringUtils.isEmpty(str)) { + return new Long[]{}; + } + String[] arr = str.split(split); + final Long[] longs = new Long[arr.length]; + for (int i = 0 ; i < arr.length ; i++) { + final Long v = toLong(arr[i], null); + longs[i] = v; + } + return longs; + } + + /** + * 转换为String数组
+ * + * @param str 被转换的值 + * + * @return 结果 + */ + public static String[] toStrArray (String str) { + return toStrArray(",", str); + } + + /** + * 转换为String数组
+ * + * @param split 分隔符 + * @param split 被转换的值 + * + * @return 结果 + */ + public static String[] toStrArray (String split, String str) { + return str.split(split); + } + + /** + * 转换为long
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * + * @return 结果 + */ + public static Long toLong (Object value, Long defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Long) { + return (Long) value; + } + if (value instanceof Number) { + return ((Number) value).longValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).longValue(); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为long
+ * 如果给定的值为null,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * + * @return 结果 + */ + public static Long toLong (Object value) { + return toLong(value, null); + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * + * @return 结果 + */ + public static Double toDouble (Object value, Double defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Double) { + return (Double) value; + } + if (value instanceof Number) { + return ((Number) value).doubleValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + // 支持科学计数法 + return new BigDecimal(valueStr.trim()).doubleValue(); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为double
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * + * @return 结果 + */ + public static Double toDouble (Object value) { + return toDouble(value, null); + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * + * @return 结果 + */ + public static Float toFloat (Object value, Float defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Float) { + return (Float) value; + } + if (value instanceof Number) { + return ((Number) value).floatValue(); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Float.parseFloat(valueStr.trim()); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为Float
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * + * @return 结果 + */ + public static Float toFloat (Object value) { + return toFloat(value, null); + } + + /** + * 转换为boolean
+ * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * + * @return 结果 + */ + public static Boolean toBool (Object value, Boolean defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof Boolean) { + return (Boolean) value; + } + String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + valueStr = valueStr.trim().toLowerCase(); + switch (valueStr) { + case "true": + case "yes": + case "ok": + case "1": + return true; + case "false": + case "no": + case "0": + return false; + default: + return defaultValue; + } + } + + /** + * 转换为boolean
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * + * @return 结果 + */ + public static Boolean toBool (Object value) { + return toBool(value, null); + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * + * @param clazz Enum的Class + * @param value 值 + * @param defaultValue 默认值 + * + * @return Enum + */ + public static > E toEnum (Class clazz, Object value, E defaultValue) { + if (value == null) { + return defaultValue; + } + if (clazz.isAssignableFrom(value.getClass())) { + @SuppressWarnings("unchecked") + E myE = (E) value; + return myE; + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return Enum.valueOf(clazz, valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为Enum对象
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * + * @param clazz Enum的Class + * @param value 值 + * + * @return Enum + */ + public static > E toEnum (Class clazz, Object value) { + return toEnum(clazz, value, null); + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * + * @return 结果 + */ + public static BigInteger toBigInteger (Object value, BigInteger defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof BigInteger) { + return (BigInteger) value; + } + if (value instanceof Long) { + return BigInteger.valueOf((Long) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return new BigInteger(valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为BigInteger
+ * 如果给定的值为空,或者转换失败,返回默认值null
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * + * @return 结果 + */ + public static BigInteger toBigInteger (Object value) { + return toBigInteger(value, null); + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * @param defaultValue 转换错误时的默认值 + * + * @return 结果 + */ + public static BigDecimal toBigDecimal (Object value, BigDecimal defaultValue) { + if (value == null) { + return defaultValue; + } + if (value instanceof BigDecimal) { + return (BigDecimal) value; + } + if (value instanceof Long) { + return new BigDecimal((Long) value); + } + if (value instanceof Double) { + return BigDecimal.valueOf((Double) value); + } + if (value instanceof Integer) { + return new BigDecimal((Integer) value); + } + final String valueStr = toStr(value, null); + if (StringUtils.isEmpty(valueStr)) { + return defaultValue; + } + try { + return new BigDecimal(valueStr); + } catch (Exception e) { + return defaultValue; + } + } + + /** + * 转换为BigDecimal
+ * 如果给定的值为空,或者转换失败,返回默认值
+ * 转换失败不会报错 + * + * @param value 被转换的值 + * + * @return 结果 + */ + public static BigDecimal toBigDecimal (Object value) { + return toBigDecimal(value, null); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * + * @return 字符串 + */ + public static String utf8Str (Object obj) { + return str(obj, "utf-8"); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charsetName 字符集 + * + * @return 字符串 + */ + public static String str (Object obj, String charsetName) { + return str(obj, Charset.forName(charsetName)); + } + + /** + * 将对象转为字符串
+ * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 + * + * @param obj 对象 + * @param charset 字符集 + * + * @return 字符串 + */ + public static String str (Object obj, Charset charset) { + if (null == obj) { + return null; + } + + if (obj instanceof String) { + return (String) obj; + } else if (obj instanceof byte[]) { + return str((byte[]) obj, charset); + } else if (obj instanceof Byte[]) { + byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj); + return str(bytes, charset); + } else if (obj instanceof ByteBuffer) { + return str((ByteBuffer) obj, charset); + } + return obj.toString(); + } + + /** + * 将byte数组转为字符串 + * + * @param bytes byte数组 + * @param charset 字符集 + * + * @return 字符串 + */ + public static String str (byte[] bytes, String charset) { + return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset)); + } + + /** + * 解码字节码 + * + * @param data 字符串 + * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 + * + * @return 解码后的字符串 + */ + public static String str (byte[] data, Charset charset) { + if (data == null) { + return null; + } + + if (null == charset) { + return new String(data); + } + return new String(data, charset); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * + * @return 字符串 + */ + public static String str (ByteBuffer data, String charset) { + if (data == null) { + return null; + } + + return str(data, Charset.forName(charset)); + } + + /** + * 将编码的byteBuffer数据转换为字符串 + * + * @param data 数据 + * @param charset 字符集,如果为空使用当前系统字符集 + * + * @return 字符串 + */ + public static String str (ByteBuffer data, Charset charset) { + if (null == charset) { + charset = Charset.defaultCharset(); + } + return charset.decode(data).toString(); + } + + // ----------------------------------------------------------------------- 全角半角转换 + + /** + * 半角转全角 + * + * @param input String. + * + * @return 全角字符串. + */ + public static String toSBC (String input) { + return toSBC(input, null); + } + + /** + * 半角转全角 + * + * @param input String + * @param notConvertSet 不替换的字符集合 + * + * @return 全角字符串. + */ + public static String toSBC (String input, Set notConvertSet) { + char[] c = input.toCharArray(); + for (int i = 0 ; i < c.length ; i++) { + if (null != notConvertSet && notConvertSet.contains(c[i])) { + // 跳过不替换的字符 + continue; + } + + if (c[i] == ' ') { + c[i] = '\u3000'; + } else if (c[i] < '\177') { + c[i] = (char) (c[i] + 65248); + + } + } + return new String(c); + } + + /** + * 全角转半角 + * + * @param input String. + * + * @return 半角字符串 + */ + public static String toDBC (String input) { + return toDBC(input, null); + } + + /** + * 替换全角为半角 + * + * @param text 文本 + * @param notConvertSet 不替换的字符集合 + * + * @return 替换后的字符 + */ + public static String toDBC (String text, Set notConvertSet) { + char[] c = text.toCharArray(); + for (int i = 0 ; i < c.length ; i++) { + if (null != notConvertSet && notConvertSet.contains(c[i])) { + // 跳过不替换的字符 + continue; + } + + if (c[i] == '\u3000') { + c[i] = ' '; + } else if (c[i] > '\uFF00' && c[i] < '\uFF5F') { + c[i] = (char) (c[i] - 65248); + } + } + String returnString = new String(c); + + return returnString; + } + + /** + * 数字金额大写转换 先写个完整的然后将如零拾替换成零 + * + * @param n 数字 + * + * @return 中文大写数字 + */ + public static String digitUppercase (double n) { + String[] fraction = {"角", "分"}; + String[] digit = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"}; + String[][] unit = {{"元", "万", "亿"}, {"", "拾", "佰", "仟"}}; + + String head = n < 0 ? "负" : ""; + n = Math.abs(n); + + String s = ""; + for (int i = 0 ; i < fraction.length ; i++) { + s += (digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", ""); + } + if (s.length() < 1) { + s = "整"; + } + int integerPart = (int) Math.floor(n); + + for (int i = 0 ; i < unit[0].length && integerPart > 0 ; i++) { + String p = ""; + for (int j = 0 ; j < unit[1].length && n > 0 ; j++) { + p = digit[integerPart % 10] + unit[1][j] + p; + integerPart = integerPart / 10; + } + s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s; + } + return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整"); + } +} diff --git a/src/main/java/com/muyu/utils/MD5Util.java b/src/main/java/com/muyu/utils/MD5Util.java new file mode 100644 index 0000000..b1ae82d --- /dev/null +++ b/src/main/java/com/muyu/utils/MD5Util.java @@ -0,0 +1,71 @@ +package com.muyu.utils; + +import lombok.extern.log4j.Log4j2; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.SecureRandom; + +@Log4j2 +public class MD5Util { + + private static final Integer SALT_LENGTH = 12; + + /** + * 将指定byte数组转换成16进制字符串 + * @param b 字节数组 + * @return 返回结果字符串 + */ + public static String byteToHexString(byte[] b) { + StringBuilder hexString = new StringBuilder(); + for (byte value : b) { + String hex = Integer.toHexString(value & 0xFF); + if (hex.length() == 1) { + hex = '0' + hex; + } + hexString.append(hex.toUpperCase()); + } + return hexString.toString(); + } + + /** + * 获得加密后的口令 + * @param str 需要加密的字符串 + * @return 加密后的字符串 + */ + public static String encrypted (String str) { + try { + // 声明加密后的口令数组变量 + byte[] pwd = null; + // 随机数生成器 + SecureRandom random = new SecureRandom(); + // 声明盐数组变量 + byte[] salt = new byte[SALT_LENGTH]; + // 将随机数放入盐变量中 + random.nextBytes(salt); + + // 声明消息摘要对象 + MessageDigest md = null; + // 创建消息摘要 + md = MessageDigest.getInstance("MD5"); + // 将盐数据传入消息摘要对象 + md.update(salt); + // 将口令的数据传给消息摘要对象 + md.update(str.getBytes(StandardCharsets.UTF_8)); + // 获得消息摘要的字节数组 + byte[] digest = md.digest(); + + // 因为要在口令的字节数组中存放盐,所以加上盐的字节长度 + pwd = new byte[digest.length + SALT_LENGTH]; + // 将盐的字节拷贝到生成的加密口令字节数组的前12个字节,以便在验证口令时取出盐 + System.arraycopy(salt, 0, pwd, 0, SALT_LENGTH); + // 将消息摘要拷贝到加密口令字节数组从第13个字节开始的字节 + System.arraycopy(digest, 0, pwd, SALT_LENGTH, digest.length); + // 将字节数组格式加密后的口令转化为16进制字符串格式的口令 + return byteToHexString(pwd); + }catch (Exception exception){ + log.info("md5加密失败:[{}]", str, exception); + return str; + } + } +} diff --git a/src/main/java/com/muyu/utils/ReflectUtils.java b/src/main/java/com/muyu/utils/ReflectUtils.java new file mode 100644 index 0000000..3aa74ef --- /dev/null +++ b/src/main/java/com/muyu/utils/ReflectUtils.java @@ -0,0 +1,314 @@ +package com.muyu.utils; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.*; + +/** + * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数. + * + * @author ruoyi + */ +@SuppressWarnings("rawtypes") +public class ReflectUtils { + private static final String SETTER_PREFIX = "set"; + + private static final String GETTER_PREFIX = "get"; + + private static final String CGLIB_CLASS_SEPARATOR = "$$"; + + private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class); + + /** + * 调用Getter方法. + * 支持多级,如:对象名.对象名.方法 + */ + @SuppressWarnings("unchecked") + public static E invokeGetter (Object obj, String propertyName) { + Object object = obj; + for (String name : StringUtils.split(propertyName, ".")) { + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); + object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{}); + } + return (E) object; + } + + /** + * 调用Setter方法, 仅匹配方法名。 + * 支持多级,如:对象名.对象名.方法 + */ + public static void invokeSetter (Object obj, String propertyName, E value) { + Object object = obj; + String[] names = StringUtils.split(propertyName, "."); + for (int i = 0 ; i < names.length ; i++) { + if (i < names.length - 1) { + String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); + object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{}); + } else { + String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); + invokeMethodByName(object, setterMethodName, new Object[]{value}); + } + } + } + + /** + * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数. + */ + @SuppressWarnings("unchecked") + public static E getFieldValue (final Object obj, final String fieldName) { + Field field = getAccessibleField(obj, fieldName); + if (field == null) { + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + return null; + } + E result = null; + try { + result = (E) field.get(obj); + } catch (IllegalAccessException e) { + logger.error("不可能抛出的异常{}", e.getMessage()); + } + return result; + } + + /** + * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数. + */ + public static void setFieldValue (final Object obj, final String fieldName, final E value) { + Field field = getAccessibleField(obj, fieldName); + if (field == null) { + // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 "); + return; + } + try { + field.set(obj, value); + } catch (IllegalAccessException e) { + logger.error("不可能抛出的异常: {}", e.getMessage()); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符. + * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用. + * 同时匹配方法名+参数类型, + */ + @SuppressWarnings("unchecked") + public static E invokeMethod (final Object obj, final String methodName, final Class[] parameterTypes, + final Object[] args) { + if (obj == null || methodName == null) { + return null; + } + Method method = getAccessibleMethod(obj, methodName, parameterTypes); + if (method == null) { + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); + return null; + } + try { + return (E) method.invoke(obj, args); + } catch (Exception e) { + String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; + throw convertReflectionExceptionToUnchecked(msg, e); + } + } + + /** + * 直接调用对象方法, 无视private/protected修饰符, + * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用. + * 只匹配函数名,如果有多个同名函数调用第一个。 + */ + @SuppressWarnings("unchecked") + public static E invokeMethodByName (final Object obj, final String methodName, final Object[] args) { + Method method = getAccessibleMethodByName(obj, methodName, args.length); + if (method == null) { + // 如果为空不报错,直接返回空。 + logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 "); + return null; + } + try { + // 类型转换(将参数数据类型转换为目标方法参数类型) + Class[] cs = method.getParameterTypes(); + for (int i = 0 ; i < cs.length ; i++) { + if (args[i] != null && !args[i].getClass().equals(cs[i])) { + if (cs[i] == String.class) { + args[i] = Convert.toStr(args[i]); + if (StringUtils.endsWith((String) args[i], ".0")) { + args[i] = StringUtils.substringBefore((String) args[i], ".0"); + } + } else if (cs[i] == Integer.class) { + args[i] = Convert.toInt(args[i]); + } else if (cs[i] == Long.class) { + args[i] = Convert.toLong(args[i]); + } else if (cs[i] == Double.class) { + args[i] = Convert.toDouble(args[i]); + } else if (cs[i] == Float.class) { + args[i] = Convert.toFloat(args[i]); + } else if (cs[i] == boolean.class || cs[i] == Boolean.class) { + args[i] = Convert.toBool(args[i]); + } + } + } + return (E) method.invoke(obj, args); + } catch (Exception e) { + String msg = "method: " + method + ", obj: " + obj + ", args: " + args + ""; + throw convertReflectionExceptionToUnchecked(msg, e); + } + } + + /** + * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + */ + public static Field getAccessibleField (final Object obj, final String fieldName) { + // 为空不报错。直接返回 null + if (obj == null) { + return null; + } + Validate.notBlank(fieldName, "fieldName can't be blank"); + for (Class superClass = obj.getClass() ; superClass != Object.class ; superClass = superClass.getSuperclass()) { + try { + Field field = superClass.getDeclaredField(fieldName); + makeAccessible(field); + return field; + } catch (NoSuchFieldException e) { + continue; + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 匹配函数名+参数类型。 + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethod (final Object obj, final String methodName, + final Class... parameterTypes) { + // 为空不报错。直接返回 null + if (obj == null) { + return null; + } + Validate.notBlank(methodName, "methodName can't be blank"); + for (Class searchType = obj.getClass() ; searchType != Object.class ; searchType = searchType.getSuperclass()) { + try { + Method method = searchType.getDeclaredMethod(methodName, parameterTypes); + makeAccessible(method); + return method; + } catch (NoSuchMethodException e) { + continue; + } + } + return null; + } + + /** + * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. + * 如向上转型到Object仍无法找到, 返回null. + * 只匹配函数名。 + * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args) + */ + public static Method getAccessibleMethodByName (final Object obj, final String methodName, int argsNum) { + // 为空不报错。直接返回 null + if (obj == null) { + return null; + } + Validate.notBlank(methodName, "methodName can't be blank"); + for (Class searchType = obj.getClass() ; searchType != Object.class ; searchType = searchType.getSuperclass()) { + Method[] methods = searchType.getDeclaredMethods(); + for (Method method : methods) { + if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum) { + makeAccessible(method); + return method; + } + } + } + return null; + } + + /** + * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible (Method method) { + if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers())) + && !method.isAccessible()) { + method.setAccessible(true); + } + } + + /** + * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。 + */ + public static void makeAccessible (Field field) { + if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) + || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) { + field.setAccessible(true); + } + } + + /** + * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处 + * 如无法找到, 返回Object.class. + */ + @SuppressWarnings("unchecked") + public static Class getClassGenricType (final Class clazz) { + return getClassGenricType(clazz, 0); + } + + /** + * 通过反射, 获得Class定义中声明的父类的泛型参数的类型. + * 如无法找到, 返回Object.class. + */ + public static Class getClassGenricType (final Class clazz, final int index) { + Type genType = clazz.getGenericSuperclass(); + + if (!(genType instanceof ParameterizedType)) { + logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType"); + return Object.class; + } + + Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); + + if (index >= params.length || index < 0) { + logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: " + + params.length); + return Object.class; + } + if (!(params[index] instanceof Class)) { + logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter"); + return Object.class; + } + + return (Class) params[index]; + } + + public static Class getUserClass (Object instance) { + if (instance == null) { + throw new RuntimeException("Instance must not be null"); + } + Class clazz = instance.getClass(); + if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) { + Class superClass = clazz.getSuperclass(); + if (superClass != null && !Object.class.equals(superClass)) { + return superClass; + } + } + return clazz; + + } + + /** + * 将反射时的checked exception转换为unchecked exception. + */ + public static RuntimeException convertReflectionExceptionToUnchecked (String msg, Exception e) { + if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException + || e instanceof NoSuchMethodException) { + return new IllegalArgumentException(msg, e); + } else if (e instanceof InvocationTargetException) { + return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException()); + } + return new RuntimeException(msg, e); + } +} diff --git a/src/main/java/com/muyu/utils/VehicleUtils.java b/src/main/java/com/muyu/utils/VehicleUtils.java new file mode 100644 index 0000000..2651577 --- /dev/null +++ b/src/main/java/com/muyu/utils/VehicleUtils.java @@ -0,0 +1,93 @@ +package com.muyu.utils; + + +import com.muyu.demos.model.PositionModel; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Random; + +public class VehicleUtils { + + /** + * 生成VIN + * @return 返回结果对象 + */ + public static String genVin() { + String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + Random random = new Random(); + StringBuilder sb = new StringBuilder(17); + for (int i = 0; i < 17; i++) { + int index = (int) (random.nextFloat() * characters.length()); + sb.append(characters.charAt(index)); + } + return sb.toString(); + } + + private static Random random = new Random(); + + /** + * 生成电池额度 + * @return 电池额度 + */ + public static BigDecimal genBattery(){ + return BigDecimal.valueOf(random.nextInt(60, 80) * 1000L); + } + + + /** + * 两点之间的距离 + * @param startPositionModel 开始定位点 + * @param endPositionModel 结束定位点 + * @return + */ + public static BigDecimal distance(PositionModel startPositionModel, PositionModel endPositionModel){ + double lon1 = Double.parseDouble(startPositionModel.getLongitude()); + double lat1 = Double.parseDouble(startPositionModel.getLatitude()); + double lon2 = Double.parseDouble(endPositionModel.getLongitude()); + double lat2 = Double.parseDouble(endPositionModel.getLatitude()); + double lon1Rad = Math.toRadians(lon1); + double lat1Rad = Math.toRadians(lat1); + double lon2Rad = Math.toRadians(lon2); + double lat2Rad = Math.toRadians(lat2); + double earthRadius = 6371; // 地球半径(以公里为单位) + + double latDiff = lat2Rad - lat1Rad; + double lonDiff = lon2Rad - lon1Rad; + + double a = Math.sin(latDiff / 2) * Math.sin(latDiff / 2) + + Math.cos(lat1Rad) * Math.cos(lat2Rad) * + Math.sin(lonDiff / 2) * Math.sin(lonDiff / 2); + + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + + double distance = earthRadius * c; + return BigDecimal.valueOf(distance).setScale(2, RoundingMode.HALF_UP); + } + + /** + * 生成电池浮动 + * @return 电池浮动值 + */ + public static BigDecimal batteryFloat(){ + Random rand = new Random(); + // 生成0.00-0.31之间的随机数 + double num = rand.nextDouble() * 0.31; + // 加上0.90,得到0.90-1.21之间的随机数 + num += 0.90; + // 保留两位小数 + num = (double) Math.round(num * 100) / 100; + return BigDecimal.valueOf(num); + } + + /** + * 给予开始和结束的值生成数据 + * @param start 起始范围 + * @param end 截止范围 + * @return 返回结果 + */ + public static String genValue(int start, int end){ + Random rand = new Random(); + return String.valueOf(rand.nextInt(start, end)); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..af2ed01 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,88 @@ +server: + port: 8888 +spring: + mvc: + static-path-pattern: /static/** + redis: + host: 101.34.243.166 + port: 6379 + password: yl030509 + rabbitmq: + host: 101.34.243.166 + port: 5672 + datasource: + username: muyu + password: 123456 + # 如果需要数据本地化,则改成 file 方式 + # jdbc:h2:mem:testDB;DB_CLOSE_DELAY=-1 + url: jdbc:h2:file:./db/vehicleSimulationDataBaseFile;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1 + driver-class-name: org.h2.Driver + # secondary: + # driver-class-name: com.mysql.cj.jdbc.Driver + # url: jdbc:mysql://101.34.243.166:3306/zncar?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false + # username: root + # password: yl@123 + + +# mybatis-plus 配置 +mybatis-plus: + mapper-locations: classpath*:/com.muyu.mapper/**/*.xml + #实体扫描,多个package用逗号或者分号分隔 + typeAliasesPackage: com.dmo.entity + global-config: + #数据库相关配置 + db-config: + #主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID", ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID"; + id-type: AUTO + #字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断" + field-strategy: NOT_NULL + #驼峰下划线转换 + column-underline: true + logic-delete-value: -1 + logic-not-delete-value: 0 + #原生配置 + configuration: + # 打印sql + # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + map-underscore-to-camel-case: true + cache-enabled: false + call-setters-on-nulls: true + jdbc-type-for-null: 'null' + +# 日志输出配置 +logging: + level: + com.muyu: DEBUG + com.muyu.service: DEBUG + com.muyu.mapper: DEBUG + com.muyu.vehicle: DEBUG + root: INFO + org: + springframework: + security: WARN + web: ERROR + file: + path: ./logs + name: './logs/vehicle.log' + pattern: + file: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n' + console: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n' +# http调用框架 +forest: + max-connections: 1000 # 连接池最大连接数 + connect-timeout: 3000 # 连接超时时间,单位为毫秒 + read-timeout: 3000 # 数据读取超时时间,单位为毫秒 + variables: + adminHost: ${mqtt.admin.host} + adminTopicUri: ${mqtt.admin.topic-uri} + log-enabled: false +kafka: + bootstrap-servers: 127.0.0.1:9092 + producer: + acks: all + retries: 0 + batch-size: 16384 + key-serializer: org.apache.kafka.common.serialization.StringSerializer + value-serializer: org.apache.kafka.common.serialization.StringSerializer + + diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html new file mode 100644 index 0000000..e2d94a2 --- /dev/null +++ b/src/main/resources/static/index.html @@ -0,0 +1,6 @@ + + +

hello word!!!

+

this is a html page

+ + \ No newline at end of file diff --git a/src/test/java/com/muyu/IotDbApplicationTests.java b/src/test/java/com/muyu/IotDbApplicationTests.java new file mode 100644 index 0000000..157f0b5 --- /dev/null +++ b/src/test/java/com/muyu/IotDbApplicationTests.java @@ -0,0 +1,13 @@ +package com.muyu; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class IotDbApplicationTests { + + @Test + void contextLoads() { + } + +}