diff --git a/.gitignore b/.gitignore index 4e0f9461..6ef74f47 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,12 @@ *.iml **/target/* .vscode +**/node_modules/* +**/dist/* +zeus-starter/src/main/resources/public/ +.bdb/ +zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/Test.java +logs/ +**/assets/node/* +iot-server/server-starter/assets/* +iot-server/server-starter/pages/* diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..568e7a2d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "zeus-iot-ui"] + path = zeus-iot-ui + url = https://github.com/zmops/zeus-iot-ui.git +[submodule "camel-zabbix-agent"] + path = camel-zabbix-agent + url = https://github.com/zmops/camel-zabbix-agent.git diff --git a/.muse/config.toml b/.muse/config.toml new file mode 100644 index 00000000..344d17e4 --- /dev/null +++ b/.muse/config.toml @@ -0,0 +1,2 @@ +jdk8 = true +setup = ".muse/setup.sh" diff --git a/.muse/setup.sh b/.muse/setup.sh new file mode 100644 index 00000000..6bc9e756 --- /dev/null +++ b/.muse/setup.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +git submodule update --init --recursive diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..1acf21ee --- /dev/null +++ b/LICENSE @@ -0,0 +1,214 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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 + + http://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. + +======================================================================= +zeus-iot Subcomponents: + +The zeus-iot project contains subcomponents with separate copyright +notices and license terms. Your use of the source code for the these +subcomponents is subject to the terms and conditions of the following +licenses. + +proto files from iot-server: https://github.com/apache/skywalking Apache 2.0 +mvnw files from https://github.com/takari/maven-wrapper Apache 2.0 + +proto files from zeus-common,zeus-core https://github.com/stylefeng/Guns LGPL-3.0 \ No newline at end of file diff --git a/README.md b/README.md index 2cdb7ba9..2e85535d 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,96 @@ -## Zeus IOT 宙斯物联网分布式采集平台 +

+banner +

-[![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?style=for-the-badge&label=Stars&logo=github)](https://github.com/zmops/zeus-iot) -[![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?style=for-the-badge&label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) -[![GitHub forks](https://img.shields.io/github/forks/zmops/zeus-iot?style=for-the-badge&label=Forks&logo=github)](https://github.com/zmops/zeus-iot) +

+Zeus IoT is the world's first open source IoT distributed collection platform based on Zabbix +

-![Version](https://img.shields.io/badge/version-1.0.0--RELEASE-brightgreen) +---- + +[![GitHub stars](https://img.shields.io/github/stars/zmops/zeus-iot.svg?label=Stars&logo=github)](https://github.com/zmops/zeus-iot) +[![GitHub issues](https://img.shields.io/github/issues/zmops/zeus-iot?label=Issuess&logo=github)](https://github.com/zmops/zeus-iot) +[![GitHub forks](https://img.shields.io/github/forks/zmops/zeus-iot?label=Forks&logo=github)](https://github.com/zmops/zeus-iot) +![Version](https://img.shields.io/badge/version-1.0.0--BETA-brightgreen) [![QQ群736541577](https://img.shields.io/badge/QQ群-736541577-brightgreen)](https://qm.qq.com/cgi-bin/qm/qr?k=CcWBdkXjkgt99bBu5d_-1TeS36DhCkU4&jump_from=webapi) -### 简介 +## Abstract +[Zeus IoT](https://www.zmops.com/) is a **distributed IoT collection, analysis, and storage platform**,It is the world's first IoT open source platform based on zabbix secondary development, all this relies on a group of engineers with rich experience in zabbix development.It is hoped that through the community’s open source ecology, continuous improvement and continuous updates will make some contributions to the development of the Internet of Things industry. + +The following screenshots give a close insight into Zeus IoT. + + + + + + + + + + + + + + + + + +
Home ScreenDevice Resources
Realtime DataSystem Users
+ +## Technology stack +- Basic components: **[Zabbix 5.4+](https://www.zabbix.com)** +- Database: **PostgreSQL12+ , [TDEngine 2.2+](https://www.taosdata.com)** +- Webapp: **SpringBoot 2 , [Ebean](https://ebean.io/) , Vue Element , Socket.IO** +- IoT Server: **[Apache Camel 2.2](https://camel.apache.org/) , Modular design** +- Visualization: **[Grafana 8.0+](https://grafana.com/grafana/)** + +## Features +
+ 🏆Based on zabbix secondary development + Based on the powerful Zabbix for interface secondary development, with industrial-grade stability and powerful performance. +
+
+ 🥇Based on Apache Camel as the pre-routing rule + Very powerful rule-based routing engine, supports 300+ module access, including IoT protocols, born for low code; one line of code can start the protocol service interface. +
+
+ 🥉Use TDEngine for time series data storage by default + TDEngine is an ultra-high performance distributed database designed and optimized for time series data. +
+
+ ⚔️IoT Server is developed with a modular architecture + IoT Server adopts the Skywalking modular architecture design, which can dynamically configure and enable modules, which is very easy to expand; at the same time, combined with the multi-point collection of Zabbix Proxy, a modular cluster can be implemented well. +
+
+ 🏹Natural distributed collection architecture + Thanks to Zabbix's excellent architecture design, it has natural distributed collection capabilities, can be well horizontally expanded, and has the ability to cross-region and cross-network collection +
+ +## Architecture + +![Architecture](docs/images/arch.gif) + +--- + +## Installation +The Zeus IoT production environment can only be installed on a Linux system, either Centos7 or Ubuntu 18.04. In the development and test environment: The IoT Server service can be developed and debugged in the Windows environment. + +### Quick Start +- Centos7/Redhat7 -**Zeus-IOT**是 + ```shell + curl -sL https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash -s install + ``` -### 快速安装 +- Ubuntu 18.04 -Zeus-IOT 支持 Centos 7、Ubuntu 20.04、Debain 10 、Kylin、UOS 等基于x86_64平台的 Linux 操作系统。 + ```shell + curl -sL https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash -s install + ``` +After Zeus IoT is successfully installed, you can use http://IP:9090 to access the ZeusIoT Console with the default account and password (Admin/zabbix). -```shell -curl -L https://github.com/zmops/zeus-iot/blob/develop/docs/quick-install.sh | bash -``` +> For more detailed installation and deployment instructions, please visit our official website document center +## Demo Environment -访问 `http://` 登录 Zeus-IOT 系统。[快速开始](./docs/quick-start.rst) +Using the account `Admin / zabbix` to log in the [demo environment](https://zeusdemo.zmops.cn/). Please note the account is granted view access. diff --git a/dist-material/bin/IOTServerStart.sh b/dist-material/bin/IOTServerStart.sh deleted file mode 100644 index e69de29b..00000000 diff --git a/dist-material/bin/IoTServer.bat b/dist-material/bin/IoTServer.bat new file mode 100644 index 00000000..76473277 --- /dev/null +++ b/dist-material/bin/IoTServer.bat @@ -0,0 +1,37 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +@echo off + +setlocal +set IOT_PROCESS_TITLE=Zeus-IoT-Server +set IOT_SERVER_HOME=%~dp0%.. +set IOT_OPTS="-Xms1024M -Xmx1024M -Diot.logDir=%IOT_SERVER_HOME%\logs -Duser.timezone=GMT+08" + +set CLASSPATH=%IOT_SERVER_HOME%\config;.; +set CLASSPATH=%IOT_SERVER_HOME%\iot-server-libs\*;%CLASSPATH% + +if defined JAVA_HOME ( + set _EXECJAVA="%JAVA_HOME%\bin\java" +) + +if not defined JAVA_HOME ( + echo "JAVA_HOME not set." + set _EXECJAVA=java +) + +start "%IOT_PROCESS_TITLE%" %_EXECJAVA% "%IOT_OPTS%" -cp "%CLASSPATH%" com.zmops.zeus.iot.server.starter.IoTServerStartUp +endlocal diff --git a/dist-material/bin/IoTServer.sh b/dist-material/bin/IoTServer.sh new file mode 100644 index 00000000..4e9ecd48 --- /dev/null +++ b/dist-material/bin/IoTServer.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. + +PRG="$0" +PRGDIR=$(dirname "$PRG") +[ -z "$IOT_HOME" ] && IOT_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) + +IOT_LOG_DIR="${IOT_LOG_DIR:-${IOT_HOME}/logs}" +JAVA_OPTS="${JAVA_OPTS:- -Xms256M -Xmx512M}" + +if [ ! -d "${IOT_LOG_DIR}" ]; then + mkdir -p "${IOT_LOG_DIR}" +fi + +_RUNJAVA=${JAVA_HOME}/bin/java +[ -z "$JAVA_HOME" ] && _RUNJAVA=java + +CLASSPATH="$IOT_HOME/config:$CLASSPATH" +for i in "$IOT_HOME"/iot-server-libs/*.jar +do + CLASSPATH="$i:$CLASSPATH" +done + +IOT_OPTIONS=" -Diot.logDir=${IOT_LOG_DIR} -Duser.timezone=GMT+08" + +eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${IOT_OPTIONS} -classpath $CLASSPATH com.zmops.zeus.iot.server.starter.IoTServerStartUp \ + &> ${IOT_LOG_DIR}/zeus_iot.log &" + +if [ $? -eq 0 ]; then + sleep 1 + echo "Zeus IOT started successfully!" +else + echo "Zeus IoT Server started failure!" + exit 1 +fi diff --git a/dist-material/bin/IoTServerInit.bat b/dist-material/bin/IoTServerInit.bat new file mode 100644 index 00000000..36a68e61 --- /dev/null +++ b/dist-material/bin/IoTServerInit.bat @@ -0,0 +1,37 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +@echo off + +setlocal +set IOT_PROCESS_TITLE=IoT-Server-Collector +set IOT_SERVER_HOME=%~dp0%.. +set IOT_OPTS="-Xms256M -Xmx512M -Diot.logDir=%IOT_SERVER_HOME%\logs" + +set CLASSPATH=%IOT_SERVER_HOME%\config;.; +set CLASSPATH=%IOT_SERVER_HOME%\iot-server-libs\*;%CLASSPATH% + +if defined JAVA_HOME ( + set _EXECJAVA="%JAVA_HOME%\bin\java" +) + +if not defined JAVA_HOME ( + echo "JAVA_HOME not set." + set _EXECJAVA=java +) + +start "%IOT_PROCESS_TITLE%" %_EXECJAVA% "%IOT_OPTS%" -cp "%CLASSPATH%" -Dmode=init com.zmops.zeus.iot.server.starter.IoTServerStartUp +endlocal diff --git a/dist-material/bin/IoTServerInit.sh b/dist-material/bin/IoTServerInit.sh new file mode 100644 index 00000000..5a047c87 --- /dev/null +++ b/dist-material/bin/IoTServerInit.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env sh +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. + +PRG="$0" +PRGDIR=$(dirname "$PRG") +[ -z "$IOT_SERVER_HOME" ] && IOT_SERVER_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) + +IOT_LOG_DIR="${IOT_SERVER_HOME}/logs" +JAVA_OPTS="${JAVA_OPTS:- -Xms256M -Xmx512M}" + +if [ ! -d "${IOT_SERVER_HOME}/logs" ]; then + mkdir -p "${IOT_LOG_DIR}" +fi + +_RUNJAVA=${JAVA_HOME}/bin/java +[ -z "$JAVA_HOME" ] && _RUNJAVA=java + +CLASSPATH="$IOT_SERVER_HOME/config:$CLASSPATH" +for i in "$IOT_SERVER_HOME"/iot-server-libs/*.jar +do + CLASSPATH="$i:$CLASSPATH" +done + +IOT_OPTIONS=" -Diot.logDir=${IOT_LOG_DIR}" + +eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${IOT_OPTIONS} -classpath $CLASSPATH -Dmode=init com.zmops.zeus.iot.server.starter.IoTServerStartUp \ + 2>${IOT_LOG_DIR}/iot_server.log 1> /dev/null &" + +if [ $? -eq 0 ]; then + sleep 1 + echo "Zeus IoT Server started successfully!" +else + echo "Zeus IoT Server started failure!" + exit 1 +fi diff --git a/dist-material/bin/IoTServerNoInit.bat b/dist-material/bin/IoTServerNoInit.bat new file mode 100644 index 00000000..97e7322f --- /dev/null +++ b/dist-material/bin/IoTServerNoInit.bat @@ -0,0 +1,37 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +@echo off + +setlocal +set IOT_PROCESS_TITLE=IoT-Server-Collector +set IOT_SERVER_HOME=%~dp0%.. +set IOT_OPTS="-Xms256M -Xmx512M -Diot.logDir=%IOT_SERVER_HOME%\logs" + +set CLASSPATH=%IOT_SERVER_HOME%\config;.; +set CLASSPATH=%IOT_SERVER_HOME%\iot-server-libs\*;%CLASSPATH% + +if defined JAVA_HOME ( + set _EXECJAVA="%JAVA_HOME%\bin\java" +) + +if not defined JAVA_HOME ( + echo "JAVA_HOME not set." + set _EXECJAVA=java +) + +start "%IOT_PROCESS_TITLE%" %_EXECJAVA% "%IOT_OPTS%" -cp "%CLASSPATH%" -Dmode=no-init com.zmops.zeus.iot.server.starter.IoTServerStartUp +endlocal diff --git a/dist-material/bin/IoTServerNoInit.sh b/dist-material/bin/IoTServerNoInit.sh new file mode 100644 index 00000000..a7e17b73 --- /dev/null +++ b/dist-material/bin/IoTServerNoInit.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env sh +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. + +PRG="$0" +PRGDIR=$(dirname "$PRG") +[ -z "$IOT_SERVER_HOME" ] && IOT_SERVER_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) + +IOT_LOG_DIR=${IOT_LOG_DIR:-"${IOT_SERVER_HOME}/logs"} +JAVA_OPTS="${JAVA_OPTS:- -Xms512M -Xmx1024M}" + +if [ ! -d "${IOT_SERVER_HOME}/logs" ]; then + mkdir -p "${IOT_LOG_DIR}" +fi + +_RUNJAVA=${JAVA_HOME}/bin/java +[ -z "$JAVA_HOME" ] && _RUNJAVA=java + +CLASSPATH="$IOT_SERVER_HOME/config:$CLASSPATH" +for i in "$IOT_SERVER_HOME"/iot-server-libs/*.jar +do + CLASSPATH="$i:$CLASSPATH" +done + +IOT_OPTIONS=" -Diot.logDir=${IOT_LOG_DIR}" + +eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${IOT_OPTIONS} -classpath $CLASSPATH -Dmode=no-init com.zmops.zeus.iot.server.starter.IoTServerStartUp \ + 2>${IOT_LOG_DIR}/iot_server.log 1> /dev/null &" + +if [ $? -eq 0 ]; then + sleep 1 + echo "Zeus IoT Server started successfully!" +else + echo "Zeus IoT Server started failure!" + exit 1 +fi diff --git a/dist-material/bin/sql/zabbix_event.sql b/dist-material/bin/sql/zabbix_event.sql new file mode 100644 index 00000000..f7c3c539 --- /dev/null +++ b/dist-material/bin/sql/zabbix_event.sql @@ -0,0 +1,109 @@ +CREATE OR REPLACE FUNCTION "public"."event_notify"("channel" text, "routing_key" text, "message" text) + RETURNS "pg_catalog"."void" AS $BODY$ + select pg_notify(channel, routing_key || '$$' || message); +$BODY$ + LANGUAGE sql STABLE + COST 100; + + + + + + + CREATE OR REPLACE FUNCTION "public"."events_problem_trace"() + RETURNS "pg_catalog"."trigger" AS $BODY$ +DECLARE + v_eventid INT; + v_event_json TEXT; +BEGIN + CASE TG_OP + WHEN 'INSERT' THEN v_eventid := NEW.eventid; + select row_to_json(x) + into v_event_json + from (SELECT p."eventid", p."objectid", p."clock", p."r_clock", p."name", p."acknowledged", p."severity",tag.tag,tag."value" tagValue from problem p Inner JOIN (select eventid,tag,value from event_tag where tag ='__alarm__' ) tag on tag.eventid=p.eventid where p.source=0 and p.eventid = v_eventid) x; + WHEN 'UPDATE' THEN v_eventid := NEW.eventid; + select row_to_json(x) + into v_event_json + from (SELECT p."eventid", p."objectid", p."clock", p."r_clock", p."name", p."acknowledged", p."severity",tag.tag,tag."value" tagValue from problem p Inner JOIN (select eventid,tag,value from event_tag where tag ='__alarm__' ) tag on tag.eventid=p.eventid where p.source=0 and p.eventid = v_eventid) x; + ELSE RETURN NULL; + END CASE; + + perform event_notify('zabbix_pg_event', 'events', v_event_json); + + RETURN NULL; +END; +$BODY$ + LANGUAGE plpgsql VOLATILE STRICT + COST 100; + + + + + + + + + CREATE OR REPLACE FUNCTION "public"."events_tag_trace"() + RETURNS "pg_catalog"."trigger" AS $BODY$ +DECLARE + v_eventid INT; + v_event_json TEXT; +BEGIN + CASE TG_OP + WHEN 'INSERT' THEN v_eventid := NEW.eventid; + select row_to_json(x) + into v_event_json + from (select e.eventid,e.objectid,e.name,tag.tag,tag.value tagValue from events e LEFT JOIN (select eventid,tag,value from event_tag where tag = '__event__' ) tag on tag.eventid=e.eventid where e.source=0 and e.eventid = v_eventid) x; + ELSE RETURN NULL; + END CASE; + + perform event_notify('zabbix_pg_event', 'events', v_event_json); + + RETURN NULL; +END; +$BODY$ + LANGUAGE plpgsql VOLATILE STRICT + COST 100; + + + + + + + CREATE OR REPLACE FUNCTION "public"."events_trace"() + RETURNS "pg_catalog"."trigger" AS $BODY$ +DECLARE + v_eventid INT; + v_event_json TEXT; +BEGIN + CASE TG_OP + WHEN 'INSERT' THEN v_eventid := NEW.eventid; + select row_to_json(x) + into v_event_json + from (select e.eventid,e.objectid,e.name,tag.tag,tag.value tagValue from events e Inner JOIN (select triggerid,tag,value from trigger_tag where tag in ('__online__','__offline__','__execute__','__scene__') ) tag on tag.triggerid=e.objectid where e.source=0 and e.eventid = v_eventid) x; + ELSE RETURN NULL; + END CASE; + + perform event_notify('zabbix_pg_event', 'events', v_event_json); + + RETURN NULL; +END; +$BODY$ + LANGUAGE plpgsql VOLATILE STRICT + COST 100; + + + + CREATE TRIGGER "events_trigger" AFTER INSERT ON "public"."events" +FOR EACH ROW +EXECUTE PROCEDURE "public"."events_trace"(); + + +CREATE TRIGGER "events_problem_trigger" AFTER INSERT OR UPDATE OF "r_clock", "acknowledged" ON "public"."problem" +FOR EACH ROW +EXECUTE PROCEDURE "public"."events_problem_trace"(); + + +CREATE TRIGGER "tag_trigger" AFTER INSERT ON "public"."event_tag" +FOR EACH ROW +EXECUTE PROCEDURE "public"."events_tag_trace"(); \ No newline at end of file diff --git a/dist-material/bin/sql/zeus-iot.sql b/dist-material/bin/sql/zeus-iot.sql new file mode 100644 index 00000000..7c6f4837 --- /dev/null +++ b/dist-material/bin/sql/zeus-iot.sql @@ -0,0 +1,2557 @@ +/* + Navicat Premium Data Transfer + + Source Server : 172.16.60.130-专业演示LOT + Source Server Type : PostgreSQL + Source Server Version : 130004 + Source Host : 172.16.60.130:5432 + Source Catalog : zeus-iot-开源空库不要删 + Source Schema : public + + Target Server Type : PostgreSQL + Target Server Version : 130004 + File Encoding : 65001 + + Date: 21/01/2022 13:56:30 +*/ + + +-- ---------------------------- +-- Sequence structure for device_online_report_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."device_online_report_id_seq"; +CREATE SEQUENCE "public"."device_online_report_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for devices_groups_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."devices_groups_id_seq"; +CREATE SEQUENCE "public"."devices_groups_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for event_trigger_record_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."event_trigger_record_id_seq"; +CREATE SEQUENCE "public"."event_trigger_record_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for mail_setting_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."mail_setting_id_seq"; +CREATE SEQUENCE "public"."mail_setting_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for media_type_setting_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."media_type_setting_id_seq"; +CREATE SEQUENCE "public"."media_type_setting_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for messages_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."messages_id_seq"; +CREATE SEQUENCE "public"."messages_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for notice_record_record_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."notice_record_record_id_seq"; +CREATE SEQUENCE "public"."notice_record_record_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for product_event_relation_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."product_event_relation_id_seq"; +CREATE SEQUENCE "public"."product_event_relation_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for product_event_tags_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."product_event_tags_id_seq"; +CREATE SEQUENCE "public"."product_event_tags_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for product_event_time_interval_event_time_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."product_event_time_interval_event_time_id_seq"; +CREATE SEQUENCE "public"."product_event_time_interval_event_time_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for product_service_relation_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."product_service_relation_id_seq"; +CREATE SEQUENCE "public"."product_service_relation_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for product_status_function_relation_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."product_status_function_relation_id_seq"; +CREATE SEQUENCE "public"."product_status_function_relation_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for product_type_product_type_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."product_type_product_type_id_seq"; +CREATE SEQUENCE "public"."product_type_product_type_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for protocol_component_protocol_component_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."protocol_component_protocol_component_id_seq"; +CREATE SEQUENCE "public"."protocol_component_protocol_component_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for protocol_gateway_protocol_gateway_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."protocol_gateway_protocol_gateway_id_seq"; +CREATE SEQUENCE "public"."protocol_gateway_protocol_gateway_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for protocol_service_protocol_service_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."protocol_service_protocol_service_id_seq"; +CREATE SEQUENCE "public"."protocol_service_protocol_service_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for scenes_trigger_record_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."scenes_trigger_record_id_seq"; +CREATE SEQUENCE "public"."scenes_trigger_record_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for service_execute_record_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."service_execute_record_id_seq"; +CREATE SEQUENCE "public"."service_execute_record_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for service_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."service_id_seq"; +CREATE SEQUENCE "public"."service_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for service_param_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."service_param_id_seq"; +CREATE SEQUENCE "public"."service_param_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for session_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."session_id_seq"; +CREATE SEQUENCE "public"."session_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_user_group_user_group_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_user_group_user_group_id_seq"; +CREATE SEQUENCE "public"."sys_user_group_user_group_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for sys_user_user_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."sys_user_user_id_seq"; +CREATE SEQUENCE "public"."sys_user_user_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 9223372036854775807 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for tag_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."tag_id_seq"; +CREATE SEQUENCE "public"."tag_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for task_info_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."task_info_id_seq"; +CREATE SEQUENCE "public"."task_info_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Sequence structure for token_token_id_seq +-- ---------------------------- +DROP SEQUENCE IF EXISTS "public"."token_token_id_seq"; +CREATE SEQUENCE "public"."token_token_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 2147483647 +START 1 +CACHE 1; + +-- ---------------------------- +-- Table structure for device +-- ---------------------------- +DROP TABLE IF EXISTS "public"."device"; +CREATE TABLE "public"."device" ( + "device_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default", + "product_id" int8, + "status" varchar(16) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8, + "type" varchar(16) COLLATE "pg_catalog"."default", + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "addr" varchar(255) COLLATE "pg_catalog"."default", + "position" varchar(64) COLLATE "pg_catalog"."default", + "online" int2 DEFAULT 1, + "latest_online" timestamp(6), + "proxy_id" int8, + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."device"."device_id" IS '设备ID'; +COMMENT ON COLUMN "public"."device"."name" IS '设备名称'; +COMMENT ON COLUMN "public"."device"."product_id" IS '关联产品'; +COMMENT ON COLUMN "public"."device"."status" IS '状态'; +COMMENT ON COLUMN "public"."device"."remark" IS '备注'; +COMMENT ON COLUMN "public"."device"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."device"."create_user" IS '创建者'; +COMMENT ON COLUMN "public"."device"."update_time" IS '系统时间'; +COMMENT ON COLUMN "public"."device"."update_user" IS '修改者'; +COMMENT ON COLUMN "public"."device"."type" IS '设备类型'; +COMMENT ON COLUMN "public"."device"."zbx_id" IS 'zbx主机ID'; +COMMENT ON COLUMN "public"."device"."addr" IS '设备地址'; +COMMENT ON COLUMN "public"."device"."position" IS '地址坐标'; +COMMENT ON COLUMN "public"."device"."online" IS '是否在线 1是 0否'; +COMMENT ON COLUMN "public"."device"."latest_online" IS '最近在线时间'; +COMMENT ON COLUMN "public"."device"."proxy_id" IS '代理ID'; +COMMENT ON COLUMN "public"."device"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of device +-- ---------------------------- + +-- ---------------------------- +-- Table structure for device_group +-- ---------------------------- +DROP TABLE IF EXISTS "public"."device_group"; +CREATE TABLE "public"."device_group" ( + "device_group_id" int8 NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "remark" varchar(255) COLLATE "pg_catalog"."default", + "zbx_id" varchar(32) COLLATE "pg_catalog"."default" NOT NULL, + "create_user" int8, + "create_time" timestamp(6), + "update_user" int8, + "update_time" timestamp(6), + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."device_group"."device_group_id" IS '主机组ID'; +COMMENT ON COLUMN "public"."device_group"."name" IS '主机组名称'; +COMMENT ON COLUMN "public"."device_group"."remark" IS '备注'; +COMMENT ON COLUMN "public"."device_group"."zbx_id" IS 'zabbix 主机组ID'; +COMMENT ON COLUMN "public"."device_group"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."device_group"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."device_group"."update_user" IS '更新人'; +COMMENT ON COLUMN "public"."device_group"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."device_group"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of device_group +-- ---------------------------- + +-- ---------------------------- +-- Table structure for device_online_report +-- ---------------------------- +DROP TABLE IF EXISTS "public"."device_online_report"; +CREATE TABLE "public"."device_online_report" ( + "id" int8 NOT NULL DEFAULT nextval('device_online_report_id_seq'::regclass), + "create_time" varchar(10) COLLATE "pg_catalog"."default", + "online" int4, + "offline" int4, + "type" int2, + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."device_online_report"."online" IS '在线数'; +COMMENT ON COLUMN "public"."device_online_report"."offline" IS '离线数'; +COMMENT ON COLUMN "public"."device_online_report"."type" IS '设备类型'; +COMMENT ON COLUMN "public"."device_online_report"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of device_online_report +-- ---------------------------- + +-- ---------------------------- +-- Table structure for devices_groups +-- ---------------------------- +DROP TABLE IF EXISTS "public"."devices_groups"; +CREATE TABLE "public"."devices_groups" ( + "id" int8 NOT NULL DEFAULT nextval('devices_groups_id_seq'::regclass), + "device_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "device_group_id" int8 NOT NULL +) +; +COMMENT ON COLUMN "public"."devices_groups"."id" IS 'ID'; +COMMENT ON COLUMN "public"."devices_groups"."device_id" IS '设备ID'; +COMMENT ON COLUMN "public"."devices_groups"."device_group_id" IS '设备组ID'; + +-- ---------------------------- +-- Records of devices_groups +-- ---------------------------- + +-- ---------------------------- +-- Table structure for event_trigger_record +-- ---------------------------- +DROP TABLE IF EXISTS "public"."event_trigger_record"; +CREATE TABLE "public"."event_trigger_record" ( + "id" int4 NOT NULL DEFAULT nextval('event_trigger_record_id_seq'::regclass), + "event_name" varchar(128) COLLATE "pg_catalog"."default", + "event_value" varchar(255) COLLATE "pg_catalog"."default", + "device_id" varchar(64) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "key" varchar(64) COLLATE "pg_catalog"."default", + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."event_trigger_record"."event_name" IS '事件名称'; +COMMENT ON COLUMN "public"."event_trigger_record"."event_value" IS '事件发生时的值'; +COMMENT ON COLUMN "public"."event_trigger_record"."device_id" IS '设备ID'; +COMMENT ON COLUMN "public"."event_trigger_record"."create_time" IS '发生时间'; +COMMENT ON COLUMN "public"."event_trigger_record"."key" IS '事件标识'; +COMMENT ON COLUMN "public"."event_trigger_record"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of event_trigger_record +-- ---------------------------- + +-- ---------------------------- +-- Table structure for mail_setting +-- ---------------------------- +DROP TABLE IF EXISTS "public"."mail_setting"; +CREATE TABLE "public"."mail_setting" ( + "host" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "port" int4 NOT NULL, + "account" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "password" varchar(100) COLLATE "pg_catalog"."default" NOT NULL, + "sender" varchar(100) COLLATE "pg_catalog"."default", + "ssl" int4 NOT NULL DEFAULT 0, + "tls" int4 NOT NULL DEFAULT 0, + "severity" varchar(255) COLLATE "pg_catalog"."default" DEFAULT ''::character varying, + "silent" int2 NOT NULL DEFAULT 3, + "id" int4 NOT NULL DEFAULT nextval('mail_setting_id_seq'::regclass), + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."mail_setting"."host" IS 'smtp服务器地址'; +COMMENT ON COLUMN "public"."mail_setting"."port" IS 'smtp服务器端口'; +COMMENT ON COLUMN "public"."mail_setting"."account" IS 'smtp登陆账号'; +COMMENT ON COLUMN "public"."mail_setting"."password" IS 'smtp密码'; +COMMENT ON COLUMN "public"."mail_setting"."sender" IS '发送邮箱'; +COMMENT ON COLUMN "public"."mail_setting"."ssl" IS '1-是 0-否'; +COMMENT ON COLUMN "public"."mail_setting"."tls" IS '1-是 0-否'; +COMMENT ON COLUMN "public"."mail_setting"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of mail_setting +-- ---------------------------- +INSERT INTO "public"."mail_setting" VALUES ('172.16.2.221', 587, 'sanshi@zmops.cn', 'Zmops@0610', 'sanshi@zmops.cn', 0, 1, '54', 3, 1, NULL); + +-- ---------------------------- +-- Table structure for media_type_setting +-- ---------------------------- +DROP TABLE IF EXISTS "public"."media_type_setting"; +CREATE TABLE "public"."media_type_setting" ( + "id" int4 NOT NULL DEFAULT nextval('media_type_setting_id_seq'::regclass), + "type" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "template" text COLLATE "pg_catalog"."default", + "webhooks" text COLLATE "pg_catalog"."default", + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."media_type_setting"."type" IS '类型'; +COMMENT ON COLUMN "public"."media_type_setting"."template" IS '消息模板'; +COMMENT ON COLUMN "public"."media_type_setting"."webhooks" IS '推送配置'; +COMMENT ON COLUMN "public"."media_type_setting"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of media_type_setting +-- ---------------------------- +INSERT INTO "public"."media_type_setting" VALUES (1, 'wechat', ' +{ + "content": "广州今日天气:29度,大部分多云,降雨概率:80%", + "mentioned_list":["wangqing","@all"], + "mentioned_mobile_list":["13800001111","@all"] + } +', '{"url":"https://oapi.dingtalk.com/robot/send?access_token=dd0f8a3340c15ec0f1d54b91980584c1127abe6dd143a964d44385647bc15124"}', NULL); +INSERT INTO "public"."media_type_setting" VALUES (2, 'dingtalk', '{ + "msgtype":"text", + "text": { + "content":"%s" + } +}', '{"url":"https://oapi.dingtalk.com/robot/send?access_token=dd","secret":"5c60"}', NULL); +INSERT INTO "public"."media_type_setting" VALUES (3, 'feishu', '{ + "msg_type":"text", + "content": { + "text":"%s" + } +}', '{"url":"https://open.feishu.cn/open-apis/bot/v2/hook/c43e56f","secret":"xoaP"}', NULL); + +-- ---------------------------- +-- Table structure for messages +-- ---------------------------- +DROP TABLE IF EXISTS "public"."messages"; +CREATE TABLE "public"."messages" ( + "classify" int4 NOT NULL, + "title" varchar(200) COLLATE "pg_catalog"."default" NOT NULL, + "content" text COLLATE "pg_catalog"."default", + "clock" int4 NOT NULL, + "module" varchar(100) COLLATE "pg_catalog"."default" DEFAULT NULL::character varying, + "readed" int2 DEFAULT 0, + "user_id" int8, + "id" int8 NOT NULL DEFAULT nextval('messages_id_seq'::regclass) +) +; +COMMENT ON COLUMN "public"."messages"."classify" IS '消息的类型'; +COMMENT ON COLUMN "public"."messages"."module" IS '消息跳转的模块'; +COMMENT ON COLUMN "public"."messages"."readed" IS '是否已读 1-是 0-否'; + +-- ---------------------------- +-- Records of messages +-- ---------------------------- + +-- ---------------------------- +-- Table structure for notice_record +-- ---------------------------- +DROP TABLE IF EXISTS "public"."notice_record"; +CREATE TABLE "public"."notice_record" ( + "record_id" int4 NOT NULL DEFAULT nextval('notice_record_record_id_seq'::regclass), + "user_id" int4, + "problem_id" varchar(32) COLLATE "pg_catalog"."default", + "notice_type" int4, + "notice_status" varchar(255) COLLATE "pg_catalog"."default", + "notice_msg" varchar(2550) COLLATE "pg_catalog"."default", + "alarm_info" varchar(255) COLLATE "pg_catalog"."default" DEFAULT NULL::character varying, + "receive_account" varchar(255) COLLATE "pg_catalog"."default" DEFAULT NULL::character varying, + "creat_time" timestamp(6) NOT NULL +) +; +COMMENT ON COLUMN "public"."notice_record"."record_id" IS '通知记录表主键id'; +COMMENT ON COLUMN "public"."notice_record"."user_id" IS '用户id'; +COMMENT ON COLUMN "public"."notice_record"."problem_id" IS '告警id'; +COMMENT ON COLUMN "public"."notice_record"."notice_type" IS '通知类型(1:sms 2:email 3:wechat 4:dingtalk)'; +COMMENT ON COLUMN "public"."notice_record"."notice_status" IS '通知状态'; +COMMENT ON COLUMN "public"."notice_record"."notice_msg" IS '通知消息'; +COMMENT ON COLUMN "public"."notice_record"."alarm_info" IS '告警信息'; +COMMENT ON COLUMN "public"."notice_record"."receive_account" IS '接收账号'; +COMMENT ON COLUMN "public"."notice_record"."creat_time" IS '创建时间'; + +-- ---------------------------- +-- Records of notice_record +-- ---------------------------- + +-- ---------------------------- +-- Table structure for problem +-- ---------------------------- +DROP TABLE IF EXISTS "public"."problem"; +CREATE TABLE "public"."problem" ( + "event_id" int8 NOT NULL, + "object_id" int8 NOT NULL DEFAULT '0'::bigint, + "name" varchar(2048) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying, + "acknowledged" int4 NOT NULL DEFAULT 0, + "severity" int4 NOT NULL DEFAULT 0, + "clock" timestamp(6), + "r_clock" timestamp(6), + "device_id" varchar(64) COLLATE "pg_catalog"."default" +) +; + +-- ---------------------------- +-- Records of problem +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product"; +CREATE TABLE "public"."product" ( + "product_id" int8 NOT NULL, + "group_id" int8, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "type" varchar(64) COLLATE "pg_catalog"."default", + "manufacturer" varchar(255) COLLATE "pg_catalog"."default", + "model" varchar(255) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8, + "product_code" varchar(255) COLLATE "pg_catalog"."default", + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "icon" text COLLATE "pg_catalog"."default", + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."product"."product_id" IS '产品ID'; +COMMENT ON COLUMN "public"."product"."group_id" IS '产品组ID'; +COMMENT ON COLUMN "public"."product"."name" IS '产品名称'; +COMMENT ON COLUMN "public"."product"."type" IS '设备类型'; +COMMENT ON COLUMN "public"."product"."manufacturer" IS '厂商'; +COMMENT ON COLUMN "public"."product"."model" IS '型号'; +COMMENT ON COLUMN "public"."product"."remark" IS '备注描述'; +COMMENT ON COLUMN "public"."product"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."product"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."product"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."product"."update_user" IS '更新人'; +COMMENT ON COLUMN "public"."product"."product_code" IS '产品编号'; +COMMENT ON COLUMN "public"."product"."zbx_id" IS 'Zabbix对应模板ID'; +COMMENT ON COLUMN "public"."product"."icon" IS '图片'; +COMMENT ON COLUMN "public"."product"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of product +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_attribute +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_attribute"; +CREATE TABLE "public"."product_attribute" ( + "attr_id" int8 NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "key" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "units" varchar(16) COLLATE "pg_catalog"."default", + "source" varchar(16) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "product_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "create_user" int8, + "create_time" timestamp(6), + "update_user" int8, + "update_time" timestamp(6), + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "value_type" varchar(16) COLLATE "pg_catalog"."default", + "dep_attr_id" int8, + "template_id" int8, + "delay" int2, + "unit" varchar(4) COLLATE "pg_catalog"."default", + "valuemapid" varchar(8) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_attribute"."attr_id" IS '属性ID'; +COMMENT ON COLUMN "public"."product_attribute"."name" IS '属性名称'; +COMMENT ON COLUMN "public"."product_attribute"."key" IS '属性标识Key'; +COMMENT ON COLUMN "public"."product_attribute"."units" IS '数字类型单位'; +COMMENT ON COLUMN "public"."product_attribute"."source" IS '数据来源'; +COMMENT ON COLUMN "public"."product_attribute"."remark" IS '备注描述'; +COMMENT ON COLUMN "public"."product_attribute"."product_id" IS '产品ID'; +COMMENT ON COLUMN "public"."product_attribute"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."product_attribute"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."product_attribute"."update_user" IS '更新人'; +COMMENT ON COLUMN "public"."product_attribute"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."product_attribute"."zbx_id" IS 'itemid'; +COMMENT ON COLUMN "public"."product_attribute"."value_type" IS '值类型'; +COMMENT ON COLUMN "public"."product_attribute"."dep_attr_id" IS '依赖属性ID'; +COMMENT ON COLUMN "public"."product_attribute"."template_id" IS '继承的属性ID'; +COMMENT ON COLUMN "public"."product_attribute"."delay" IS '取数间隔'; +COMMENT ON COLUMN "public"."product_attribute"."unit" IS '取数间隔单位 s m h '; +COMMENT ON COLUMN "public"."product_attribute"."valuemapid" IS '值映射ID'; + +-- ---------------------------- +-- Records of product_attribute +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_attribute_event +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_attribute_event"; +CREATE TABLE "public"."product_attribute_event" ( + "attr_id" int8 NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "key" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "units" varchar(16) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "product_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "create_user" int8, + "create_time" timestamp(6), + "update_user" int8, + "update_time" timestamp(6), + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "value_type" varchar(16) COLLATE "pg_catalog"."default", + "template_id" int8, + "event_level" char(1) COLLATE "pg_catalog"."default", + "source" varchar(16) COLLATE "pg_catalog"."default", + "delay" int2, + "unit" varchar(4) COLLATE "pg_catalog"."default", + "valuemapid" varchar(8) COLLATE "pg_catalog"."default", + "dep_attr_id" int8 +) +; +COMMENT ON COLUMN "public"."product_attribute_event"."attr_id" IS '属性ID'; +COMMENT ON COLUMN "public"."product_attribute_event"."name" IS '属性名称'; +COMMENT ON COLUMN "public"."product_attribute_event"."key" IS '属性标识Key'; +COMMENT ON COLUMN "public"."product_attribute_event"."units" IS '数字类型单位'; +COMMENT ON COLUMN "public"."product_attribute_event"."remark" IS '备注描述'; +COMMENT ON COLUMN "public"."product_attribute_event"."product_id" IS '产品ID'; +COMMENT ON COLUMN "public"."product_attribute_event"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."product_attribute_event"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."product_attribute_event"."update_user" IS '更新人'; +COMMENT ON COLUMN "public"."product_attribute_event"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."product_attribute_event"."zbx_id" IS 'itemid'; +COMMENT ON COLUMN "public"."product_attribute_event"."value_type" IS '值类型'; +COMMENT ON COLUMN "public"."product_attribute_event"."template_id" IS '继承的属性ID'; +COMMENT ON COLUMN "public"."product_attribute_event"."event_level" IS '事件级别'; +COMMENT ON COLUMN "public"."product_attribute_event"."source" IS '数据来源'; +COMMENT ON COLUMN "public"."product_attribute_event"."delay" IS '取数间隔'; +COMMENT ON COLUMN "public"."product_attribute_event"."unit" IS '取数间隔单位 s m h '; +COMMENT ON COLUMN "public"."product_attribute_event"."valuemapid" IS '值映射ID'; +COMMENT ON COLUMN "public"."product_attribute_event"."dep_attr_id" IS '依赖属性ID'; + +-- ---------------------------- +-- Records of product_attribute_event +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_event +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_event"; +CREATE TABLE "public"."product_event" ( + "event_rule_id" int8 NOT NULL, + "event_rule_name" varchar(255) COLLATE "pg_catalog"."default", + "event_level" varchar(1) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8, + "exp_logic" varchar(10) COLLATE "pg_catalog"."default", + "event_notify" varchar(1) COLLATE "pg_catalog"."default", + "status" varchar(8) COLLATE "pg_catalog"."default", + "classify" varchar(2) COLLATE "pg_catalog"."default", + "task_id" int4, + "trigger_type" int2, + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."product_event"."event_rule_id" IS '告警规则ID'; +COMMENT ON COLUMN "public"."product_event"."event_rule_name" IS '告警规则名称'; +COMMENT ON COLUMN "public"."product_event"."event_level" IS '告警等级'; +COMMENT ON COLUMN "public"."product_event"."remark" IS '备注'; +COMMENT ON COLUMN "public"."product_event"."exp_logic" IS 'and 或者 or'; +COMMENT ON COLUMN "public"."product_event"."event_notify" IS '0 否 1 是'; +COMMENT ON COLUMN "public"."product_event"."classify" IS '0 告警 1场景联动'; +COMMENT ON COLUMN "public"."product_event"."task_id" IS '任务ID'; +COMMENT ON COLUMN "public"."product_event"."trigger_type" IS '触发类型 0-条件触发 1-定时触发'; +COMMENT ON COLUMN "public"."product_event"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of product_event +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_event_expression +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_event_expression"; +CREATE TABLE "public"."product_event_expression" ( + "event_exp_id" int8 NOT NULL, + "event_rule_id" int8, + "function" varchar(16) COLLATE "pg_catalog"."default", + "scope" varchar(10) COLLATE "pg_catalog"."default", + "condition" varchar(10) COLLATE "pg_catalog"."default", + "value" varchar(255) COLLATE "pg_catalog"."default", + "product_attr_key" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "device_id" varchar(255) COLLATE "pg_catalog"."default", + "unit" varchar(16) COLLATE "pg_catalog"."default", + "product_attr_id" int8, + "product_attr_type" varchar(4) COLLATE "pg_catalog"."default", + "period" varchar(8) COLLATE "pg_catalog"."default", + "attr_value_type" varchar(8) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_event_expression"."event_exp_id" IS '告警函数ID'; +COMMENT ON COLUMN "public"."product_event_expression"."event_rule_id" IS '告警规则ID'; +COMMENT ON COLUMN "public"."product_event_expression"."product_attr_key" IS 'item key'; +COMMENT ON COLUMN "public"."product_event_expression"."device_id" IS '设备ID'; +COMMENT ON COLUMN "public"."product_event_expression"."product_attr_id" IS '属性ID'; +COMMENT ON COLUMN "public"."product_event_expression"."product_attr_type" IS '属性类型 属性 事件'; +COMMENT ON COLUMN "public"."product_event_expression"."period" IS '取值周期 时间 周期'; +COMMENT ON COLUMN "public"."product_event_expression"."attr_value_type" IS '属性值类型'; + +-- ---------------------------- +-- Records of product_event_expression +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_event_relation +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_event_relation"; +CREATE TABLE "public"."product_event_relation" ( + "id" int8 NOT NULL DEFAULT nextval('product_event_relation_id_seq'::regclass), + "event_rule_id" int8 NOT NULL, + "relation_id" varchar(64) COLLATE "pg_catalog"."default", + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "inherit" varchar(4) COLLATE "pg_catalog"."default" DEFAULT '0'::character varying, + "status" varchar(8) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_event_relation"."event_rule_id" IS '规则ID'; +COMMENT ON COLUMN "public"."product_event_relation"."relation_id" IS '关联产品或设备ID'; +COMMENT ON COLUMN "public"."product_event_relation"."zbx_id" IS 'trigger id'; +COMMENT ON COLUMN "public"."product_event_relation"."inherit" IS '是否来自产品'; +COMMENT ON COLUMN "public"."product_event_relation"."status" IS '状态'; +COMMENT ON COLUMN "public"."product_event_relation"."remark" IS '备注'; + +-- ---------------------------- +-- Records of product_event_relation +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_event_service +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_event_service"; +CREATE TABLE "public"."product_event_service" ( + "event_rule_id" int8, + "service_id" int8, + "device_id" varchar(64) COLLATE "pg_catalog"."default", + "execute_device_id" varchar(64) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_event_service"."event_rule_id" IS '告警规则ID'; +COMMENT ON COLUMN "public"."product_event_service"."service_id" IS '产品服务ID'; +COMMENT ON COLUMN "public"."product_event_service"."device_id" IS '关联产品或设备ID'; +COMMENT ON COLUMN "public"."product_event_service"."execute_device_id" IS '执行目标设备ID'; + +-- ---------------------------- +-- Records of product_event_service +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_event_tags +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_event_tags"; +CREATE TABLE "public"."product_event_tags" ( + "id" int4 NOT NULL DEFAULT nextval('product_event_tags_id_seq'::regclass), + "event_rule_id" int8 NOT NULL, + "tag_zbx_id" int4 NOT NULL +) +; +COMMENT ON COLUMN "public"."product_event_tags"."id" IS '自增ID'; +COMMENT ON COLUMN "public"."product_event_tags"."event_rule_id" IS '告警规则ID'; +COMMENT ON COLUMN "public"."product_event_tags"."tag_zbx_id" IS 'zabbix tag id'; + +-- ---------------------------- +-- Records of product_event_tags +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_event_time_interval +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_event_time_interval"; +CREATE TABLE "public"."product_event_time_interval" ( + "event_time_id" int4 NOT NULL DEFAULT nextval('product_event_time_interval_event_time_id_seq'::regclass), + "event_rule_id" int8 NOT NULL, + "start_time" int4, + "end_time" int4, + "day_of_weeks" varchar(16) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_event_time_interval"."event_time_id" IS '告警函数ID'; +COMMENT ON COLUMN "public"."product_event_time_interval"."event_rule_id" IS '告警规则ID'; +COMMENT ON COLUMN "public"."product_event_time_interval"."start_time" IS '开始时间'; +COMMENT ON COLUMN "public"."product_event_time_interval"."end_time" IS '结束时间'; +COMMENT ON COLUMN "public"."product_event_time_interval"."day_of_weeks" IS '周几'; + +-- ---------------------------- +-- Records of product_event_time_interval +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_service +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_service"; +CREATE TABLE "public"."product_service" ( + "id" int8 NOT NULL DEFAULT nextval('service_id_seq'::regclass), + "name" varchar(64) COLLATE "pg_catalog"."default", + "mark" varchar(64) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "async" varchar(16) COLLATE "pg_catalog"."default" DEFAULT 1 +) +; +COMMENT ON COLUMN "public"."product_service"."name" IS '服务名称'; +COMMENT ON COLUMN "public"."product_service"."mark" IS '服务标识'; +COMMENT ON COLUMN "public"."product_service"."remark" IS '备注'; +COMMENT ON COLUMN "public"."product_service"."async" IS '执行方式 0-同步 1-异步'; + +-- ---------------------------- +-- Records of product_service +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_service_param +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_service_param"; +CREATE TABLE "public"."product_service_param" ( + "id" int8 NOT NULL DEFAULT nextval('service_param_id_seq'::regclass), + "service_id" int8, + "key" varchar(32) COLLATE "pg_catalog"."default", + "name" varchar(32) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "value" varchar(255) COLLATE "pg_catalog"."default", + "device_id" varchar(64) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_service_param"."service_id" IS '服务ID'; +COMMENT ON COLUMN "public"."product_service_param"."key" IS '参数标识'; +COMMENT ON COLUMN "public"."product_service_param"."name" IS '参数名称'; +COMMENT ON COLUMN "public"."product_service_param"."remark" IS '备注'; +COMMENT ON COLUMN "public"."product_service_param"."value" IS '参数值'; +COMMENT ON COLUMN "public"."product_service_param"."device_id" IS '关联设备ID'; + +-- ---------------------------- +-- Records of product_service_param +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_service_relation +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_service_relation"; +CREATE TABLE "public"."product_service_relation" ( + "service_id" int8 NOT NULL, + "relation_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "id" int8 NOT NULL DEFAULT nextval('product_service_relation_id_seq'::regclass), + "inherit" varchar(4) COLLATE "pg_catalog"."default" DEFAULT 0 +) +; +COMMENT ON COLUMN "public"."product_service_relation"."inherit" IS '是否继承'; + +-- ---------------------------- +-- Records of product_service_relation +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_status_function +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_status_function"; +CREATE TABLE "public"."product_status_function" ( + "rule_function" varchar(10) COLLATE "pg_catalog"."default", + "rule_status" int2 DEFAULT 1, + "create_user" int8, + "update_user" int8, + "create_time" timestamp(6), + "update_time" timestamp(6), + "rule_id" int8 NOT NULL, + "rule_condition" varchar(255) COLLATE "pg_catalog"."default", + "rule_function_recovery" varchar(10) COLLATE "pg_catalog"."default", + "rule_condition_recovery" varchar(255) COLLATE "pg_catalog"."default", + "attr_id" int8, + "attr_id_recovery" int8, + "unit" varchar(8) COLLATE "pg_catalog"."default", + "unit_recovery" varchar(8) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_status_function"."rule_function" IS '''nodata'' or ''last'''; +COMMENT ON COLUMN "public"."product_status_function"."rule_status" IS '0 or 1'; +COMMENT ON COLUMN "public"."product_status_function"."rule_id" IS '触发器ID,离线 上线'; +COMMENT ON COLUMN "public"."product_status_function"."rule_condition" IS '''5m'' or ''4'''; +COMMENT ON COLUMN "public"."product_status_function"."rule_function_recovery" IS '''nodata'' or ''last'''; +COMMENT ON COLUMN "public"."product_status_function"."rule_condition_recovery" IS '''5m'' or ''4'''; +COMMENT ON COLUMN "public"."product_status_function"."attr_id" IS 'trigger attrId'; +COMMENT ON COLUMN "public"."product_status_function"."attr_id_recovery" IS 'recovery attrId'; + +-- ---------------------------- +-- Records of product_status_function +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_status_function_relation +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_status_function_relation"; +CREATE TABLE "public"."product_status_function_relation" ( + "rule_id" int8 NOT NULL, + "relation_id" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "id" int8 NOT NULL DEFAULT nextval('product_status_function_relation_id_seq'::regclass), + "inherit" varchar(4) COLLATE "pg_catalog"."default" DEFAULT 0, + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "zbx_id_recovery" varchar(32) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."product_status_function_relation"."inherit" IS '是否继承自产品 1是0否'; +COMMENT ON COLUMN "public"."product_status_function_relation"."zbx_id" IS 'zabbix trigger id'; +COMMENT ON COLUMN "public"."product_status_function_relation"."zbx_id_recovery" IS 'zbx recovery trigger id'; + +-- ---------------------------- +-- Records of product_status_function_relation +-- ---------------------------- + +-- ---------------------------- +-- Table structure for product_type +-- ---------------------------- +DROP TABLE IF EXISTS "public"."product_type"; +CREATE TABLE "public"."product_type" ( + "id" int4 NOT NULL DEFAULT nextval('product_type_product_type_id_seq'::regclass), + "pid" int4, + "name" varchar(32) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "pids" varchar(255) COLLATE "pg_catalog"."default", + "create_user" int8, + "create_time" timestamp(6), + "update_user" int8, + "update_time" timestamp(6), + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."product_type"."name" IS '分类名称'; +COMMENT ON COLUMN "public"."product_type"."remark" IS '备注'; +COMMENT ON COLUMN "public"."product_type"."pids" IS '所有父ID'; +COMMENT ON COLUMN "public"."product_type"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."product_type"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."product_type"."update_user" IS '更新人'; +COMMENT ON COLUMN "public"."product_type"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."product_type"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of product_type +-- ---------------------------- +INSERT INTO "public"."product_type" VALUES (1, 0, '默认产品分组', NULL, '[0],', NULL, NULL, NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for protocol_component +-- ---------------------------- +DROP TABLE IF EXISTS "public"."protocol_component"; +CREATE TABLE "public"."protocol_component" ( + "protocol_component_id" int8 NOT NULL DEFAULT nextval('protocol_component_protocol_component_id_seq'::regclass), + "name" varchar(64) COLLATE "pg_catalog"."default", + "effect_proxy" varchar(255) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "status" varchar(4) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8, + "tenant_id" int8, + "protocol_type" varchar(8) COLLATE "pg_catalog"."default", + "file_name" varchar(255) COLLATE "pg_catalog"."default", + "unique_id" varchar(16) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."protocol_component"."name" IS '组件名称'; +COMMENT ON COLUMN "public"."protocol_component"."effect_proxy" IS '影响的代理'; +COMMENT ON COLUMN "public"."protocol_component"."remark" IS '备注'; +COMMENT ON COLUMN "public"."protocol_component"."status" IS '状态 0-待上传 1-未发布 2-已发布'; +COMMENT ON COLUMN "public"."protocol_component"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."protocol_component"."create_user" IS '创建者'; +COMMENT ON COLUMN "public"."protocol_component"."update_time" IS '系统时间'; +COMMENT ON COLUMN "public"."protocol_component"."update_user" IS '修改者'; +COMMENT ON COLUMN "public"."protocol_component"."tenant_id" IS '租户ID'; +COMMENT ON COLUMN "public"."protocol_component"."protocol_type" IS '协议类型'; +COMMENT ON COLUMN "public"."protocol_component"."file_name" IS '协议JAR包名称'; +COMMENT ON COLUMN "public"."protocol_component"."unique_id" IS '唯一ID'; + +-- ---------------------------- +-- Records of protocol_component +-- ---------------------------- + +-- ---------------------------- +-- Table structure for protocol_gateway +-- ---------------------------- +DROP TABLE IF EXISTS "public"."protocol_gateway"; +CREATE TABLE "public"."protocol_gateway" ( + "protocol_gateway_id" int8 NOT NULL DEFAULT nextval('protocol_gateway_protocol_gateway_id_seq'::regclass), + "name" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "protocol_type" varchar(4) COLLATE "pg_catalog"."default", + "protocol_component_id" int8, + "protocol_service_id" int8, + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8, + "tenant_id" int8, + "remark" varchar(255) COLLATE "pg_catalog"."default", + "status" varchar(4) COLLATE "pg_catalog"."default", + "qos" int2 +) +; +COMMENT ON COLUMN "public"."protocol_gateway"."name" IS '名称'; +COMMENT ON COLUMN "public"."protocol_gateway"."protocol_type" IS '类型'; +COMMENT ON COLUMN "public"."protocol_gateway"."protocol_component_id" IS '协议组件ID'; +COMMENT ON COLUMN "public"."protocol_gateway"."protocol_service_id" IS '协议服务ID'; +COMMENT ON COLUMN "public"."protocol_gateway"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."protocol_gateway"."create_user" IS '创建者'; +COMMENT ON COLUMN "public"."protocol_gateway"."update_time" IS '系统时间'; +COMMENT ON COLUMN "public"."protocol_gateway"."update_user" IS '修改者'; +COMMENT ON COLUMN "public"."protocol_gateway"."tenant_id" IS '租户ID'; +COMMENT ON COLUMN "public"."protocol_gateway"."remark" IS '备注'; +COMMENT ON COLUMN "public"."protocol_gateway"."status" IS '网关状态'; +COMMENT ON COLUMN "public"."protocol_gateway"."qos" IS 'Qos'; + +-- ---------------------------- +-- Records of protocol_gateway +-- ---------------------------- + +-- ---------------------------- +-- Table structure for protocol_gateway_mqtt +-- ---------------------------- +DROP TABLE IF EXISTS "public"."protocol_gateway_mqtt"; +CREATE TABLE "public"."protocol_gateway_mqtt" ( + "protocol_gateway_id" int8 NOT NULL, + "topic" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "protocol_component_id" int8 NOT NULL +) +; +COMMENT ON COLUMN "public"."protocol_gateway_mqtt"."protocol_gateway_id" IS '设备协议ID'; +COMMENT ON COLUMN "public"."protocol_gateway_mqtt"."topic" IS 'mqtt client 协议 TOPIC'; +COMMENT ON COLUMN "public"."protocol_gateway_mqtt"."protocol_component_id" IS '协议组件ID'; + +-- ---------------------------- +-- Records of protocol_gateway_mqtt +-- ---------------------------- + +-- ---------------------------- +-- Table structure for protocol_service +-- ---------------------------- +DROP TABLE IF EXISTS "public"."protocol_service"; +CREATE TABLE "public"."protocol_service" ( + "protocol_service_id" int8 NOT NULL DEFAULT nextval('protocol_service_protocol_service_id_seq'::regclass), + "name" varchar(64) COLLATE "pg_catalog"."default", + "protocol_type" varchar(4) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "effect_proxy" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8, + "tenant_id" int8, + "url" varchar(128) COLLATE "pg_catalog"."default", + "ip" varchar(16) COLLATE "pg_catalog"."default", + "port" int2, + "msg_length" int2, + "client_id" varchar(32) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."protocol_service"."name" IS '名称'; +COMMENT ON COLUMN "public"."protocol_service"."protocol_type" IS '协议类型'; +COMMENT ON COLUMN "public"."protocol_service"."remark" IS '备注'; +COMMENT ON COLUMN "public"."protocol_service"."effect_proxy" IS '影响的代理'; +COMMENT ON COLUMN "public"."protocol_service"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."protocol_service"."create_user" IS '创建者'; +COMMENT ON COLUMN "public"."protocol_service"."update_time" IS '系统时间'; +COMMENT ON COLUMN "public"."protocol_service"."update_user" IS '修改者'; +COMMENT ON COLUMN "public"."protocol_service"."tenant_id" IS '租户ID'; +COMMENT ON COLUMN "public"."protocol_service"."url" IS 'URL'; +COMMENT ON COLUMN "public"."protocol_service"."ip" IS 'ip地址'; +COMMENT ON COLUMN "public"."protocol_service"."port" IS '端口'; +COMMENT ON COLUMN "public"."protocol_service"."msg_length" IS '消息长度'; + +-- ---------------------------- +-- Records of protocol_service +-- ---------------------------- + +-- ---------------------------- +-- Table structure for proxy +-- ---------------------------- +DROP TABLE IF EXISTS "public"."proxy"; +CREATE TABLE "public"."proxy" ( + "id" int8 NOT NULL, + "name" varchar(64) COLLATE "pg_catalog"."default", + "mode" varchar(16) COLLATE "pg_catalog"."default" DEFAULT '0'::character varying, + "address" varchar(32) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "tls_accept" int4 DEFAULT 1, + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8, + "zbx_id" varchar(16) COLLATE "pg_catalog"."default", + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."proxy"."name" IS '代理名称'; +COMMENT ON COLUMN "public"."proxy"."mode" IS '代理模式'; +COMMENT ON COLUMN "public"."proxy"."address" IS '代理服务器地址'; +COMMENT ON COLUMN "public"."proxy"."remark" IS '描述'; +COMMENT ON COLUMN "public"."proxy"."tls_accept" IS '加密方式'; +COMMENT ON COLUMN "public"."proxy"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."proxy"."create_user" IS '创建者'; +COMMENT ON COLUMN "public"."proxy"."update_time" IS '系统时间'; +COMMENT ON COLUMN "public"."proxy"."update_user" IS '修改者'; +COMMENT ON COLUMN "public"."proxy"."zbx_id" IS 'zbx ID'; +COMMENT ON COLUMN "public"."proxy"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of proxy +-- ---------------------------- + +-- ---------------------------- +-- Table structure for scenes_trigger_record +-- ---------------------------- +DROP TABLE IF EXISTS "public"."scenes_trigger_record"; +CREATE TABLE "public"."scenes_trigger_record" ( + "id" int8 NOT NULL DEFAULT nextval('scenes_trigger_record_id_seq'::regclass), + "create_time" timestamp(6), + "rule_name" varchar(64) COLLATE "pg_catalog"."default", + "rule_id" int8, + "trigger_type" varchar(16) COLLATE "pg_catalog"."default", + "trigger_user" int8, + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."scenes_trigger_record"."create_time" IS '触发时间'; +COMMENT ON COLUMN "public"."scenes_trigger_record"."rule_name" IS '场景联动名称'; +COMMENT ON COLUMN "public"."scenes_trigger_record"."rule_id" IS '场景联动ID'; +COMMENT ON COLUMN "public"."scenes_trigger_record"."trigger_type" IS '触发类型 手动 自动'; +COMMENT ON COLUMN "public"."scenes_trigger_record"."trigger_user" IS '触发人'; +COMMENT ON COLUMN "public"."scenes_trigger_record"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of scenes_trigger_record +-- ---------------------------- + +-- ---------------------------- +-- Table structure for service_execute_record +-- ---------------------------- +DROP TABLE IF EXISTS "public"."service_execute_record"; +CREATE TABLE "public"."service_execute_record" ( + "id" int8 NOT NULL DEFAULT nextval('service_execute_record_id_seq'::regclass), + "create_time" timestamp(6), + "service_name" varchar(64) COLLATE "pg_catalog"."default", + "param" varchar(255) COLLATE "pg_catalog"."default", + "device_id" varchar(64) COLLATE "pg_catalog"."default", + "execute_type" varchar(16) COLLATE "pg_catalog"."default", + "execute_user" int8, + "execute_rule_id" int8, + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."service_execute_record"."service_name" IS '服务名称'; +COMMENT ON COLUMN "public"."service_execute_record"."param" IS '执行参数'; +COMMENT ON COLUMN "public"."service_execute_record"."device_id" IS '设备ID'; +COMMENT ON COLUMN "public"."service_execute_record"."execute_type" IS '执行方式 手动触发 场景触发'; +COMMENT ON COLUMN "public"."service_execute_record"."execute_user" IS '执行人 执行方式未手动触发时有值'; +COMMENT ON COLUMN "public"."service_execute_record"."execute_rule_id" IS '执行场景ID'; +COMMENT ON COLUMN "public"."service_execute_record"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of service_execute_record +-- ---------------------------- + +-- ---------------------------- +-- Table structure for session +-- ---------------------------- +DROP TABLE IF EXISTS "public"."session"; +CREATE TABLE "public"."session" ( + "id" int4 NOT NULL DEFAULT nextval('session_id_seq'::regclass), + "key" varchar(255) COLLATE "pg_catalog"."default", + "value" varchar COLLATE "pg_catalog"."default" +) +; + +-- ---------------------------- +-- Records of session +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_config +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_config"; +CREATE TABLE "public"."sys_config" ( + "id" int8 NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "code" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "dict_flag" char(1) COLLATE "pg_catalog"."default" NOT NULL, + "dict_type_id" int8, + "value" varchar(255) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "create_user" int8, + "update_user" int8, + "create_time" timestamp(6), + "update_time" timestamp(6), + "status" varchar(8) COLLATE "pg_catalog"."default" DEFAULT 'ENABLE'::character varying +) +; +COMMENT ON COLUMN "public"."sys_config"."id" IS '主键ID'; +COMMENT ON COLUMN "public"."sys_config"."name" IS '名称'; +COMMENT ON COLUMN "public"."sys_config"."code" IS '属性编码标识'; +COMMENT ON COLUMN "public"."sys_config"."dict_flag" IS '是否是字典中的值'; +COMMENT ON COLUMN "public"."sys_config"."dict_type_id" IS '字典类型的编码'; +COMMENT ON COLUMN "public"."sys_config"."value" IS '属性值,如果是字典中的类型,则为dict的code'; +COMMENT ON COLUMN "public"."sys_config"."remark" IS '备注'; +COMMENT ON COLUMN "public"."sys_config"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."sys_config"."update_user" IS '更新人'; +COMMENT ON COLUMN "public"."sys_config"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."sys_config"."update_time" IS '修改时间'; +COMMENT ON COLUMN "public"."sys_config"."status" IS '是否可修改 ENABLE可以 DISABLE不可'; + +-- ---------------------------- +-- Records of sys_config +-- ---------------------------- +INSERT INTO "public"."sys_config" VALUES (1143324237579165697, '验证码开关', 'ZEUS_KAPTCHA_OPEN', 'Y', 1106120265689055233, 'DISABLE', '是否开启验证码', 1, 1, '2019-06-24 12:46:43', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468689664876546, '管理系统名称', 'ZEUS_SYSTEM_NAME', 'N', NULL, 'ZEUS-IOT', '管理系统名称', 1, 1, '2019-06-25 18:39:15', '2021-08-09 17:17:30.189', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607297, '默认系统密码', 'ZEUS_DEFAULT_PASSWORD', 'N', NULL, '111111', '默认系统密码', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607298, '用户角色ID', 'ZEUS_ADMIN_ROLE_ID', 'N', NULL, '3', '用户角色ID', 1, 1, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1143469008025133058, 'OAuth2登录用户的账号标识', 'ZEUS_OAUTH2_PREFIX', 'N', NULL, 'oauth2', 'OAuth2登录用户的账号标识', 1, 1, '2019-06-25 18:40:31', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370496, '全局主机组Id', 'ZEUS_HOST_GROUP_ID', 'Y', NULL, '19', '全局主机和模板组ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370498, 'Zeus发布的编号', 'ZEUS_SYSTEM_RELEASE_VERSION', 'N', NULL, '10', '用于防止浏览器缓存相关的js和css', 1, 1, '2019-07-02 12:42:30', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370499, '文件上传路径', 'ZEUS_FILE_UPLOAD_PATH', 'N', NULL, '/tmp', '文件上传默认目录', 1, 1, '2019-08-30 09:10:40', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370502, '获取token的header标识', 'ZEUS_TOKEN_HEADER_NAME', 'N', NULL, 'Authorization', '获取token的header标识', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370602, '获取系统地密钥加密字符', 'ZEUS_JWT_SECRET', 'N', NULL, 'xoav75nyxl4dsm0av1md1zi3wszntan4', '获取系统地密钥加密字符', 1, 1, '2019-10-16 23:02:39', '2021-11-15 11:16:23.993', 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607207, '默认租户角色ID', 'ZEUS_TENANT_ROLE_ID', 'N', NULL, '2', '默认租户角色ID', 1, 122, '2019-06-25 18:39:57', '2021-09-28 09:46:39.421', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1143468867767607208, '单点登录开关', 'ZEUS_SIGN_IN', 'N', NULL, 'ENABLE', '是否启用单点登录', 1, 1, '2019-06-25 18:39:57', '2021-08-03 16:38:12.432', 'ENABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370497, '离线回调ActionId', 'ZEUS_OFFLINE_ACTION_ID', 'Y', NULL, '15', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370501, '获取系统地密钥过期时间', 'ZEUS_JWT_SECRET_EXPIRE', 'N', NULL, '864000000', '获取系统地密钥过期时间(单位:秒),默认1天', 1, 1, '2019-10-16 23:02:39', '2021-08-03 16:38:12.432', 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370503, '告警回调ActionId', 'ZEUS_ALARM_ACTION_ID', 'Y', NULL, '16', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370504, '动作回调ActionId', 'ZEUS_EXEC_ACTION_ID', 'Y', NULL, '17', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); +INSERT INTO "public"."sys_config" VALUES (1145915627211370505, '事件回调ActionId', 'ZEUS_EVENT_ACTION_ID', 'Y', NULL, '18', '回调动作ID', NULL, NULL, NULL, NULL, 'DISABLE'); + +-- ---------------------------- +-- Table structure for sys_dict +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_dict"; +CREATE TABLE "public"."sys_dict" ( + "dict_id" int8 NOT NULL, + "dict_type_id" int8 NOT NULL, + "code" varchar(50) COLLATE "pg_catalog"."default" NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "status" varchar(10) COLLATE "pg_catalog"."default" NOT NULL, + "sort" int4, + "remark" varchar(1000) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "update_time" timestamp(6), + "create_user" int8, + "update_user" int8, + "groups" varchar(64) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."sys_dict"."dict_id" IS '字典id'; +COMMENT ON COLUMN "public"."sys_dict"."dict_type_id" IS '所属字典类型的id'; +COMMENT ON COLUMN "public"."sys_dict"."code" IS '字典编码'; +COMMENT ON COLUMN "public"."sys_dict"."name" IS '字典名称'; +COMMENT ON COLUMN "public"."sys_dict"."status" IS '状态(字典)'; +COMMENT ON COLUMN "public"."sys_dict"."sort" IS '排序'; +COMMENT ON COLUMN "public"."sys_dict"."remark" IS '字典的描述'; +COMMENT ON COLUMN "public"."sys_dict"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."sys_dict"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."sys_dict"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."sys_dict"."update_user" IS '修改人'; +COMMENT ON COLUMN "public"."sys_dict"."groups" IS '分组'; +COMMENT ON TABLE "public"."sys_dict" IS '基础字典'; + +-- ---------------------------- +-- Records of sys_dict +-- ---------------------------- +INSERT INTO "public"."sys_dict" VALUES (1106120532442595330, 1106120208097067009, 'M', '男', 'ENABLE', NULL, '', '2019-03-14 17:11:00', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120574163337218, 1106120208097067009, 'F', '女', 'ENABLE', NULL, '', '2019-03-14 17:11:10', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120645697191938, 1106120265689055233, 'ENABLE', '启用', 'ENABLE', NULL, '', '2019-03-14 17:11:27', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120699468169217, 1106120265689055233, 'DISABLE', '禁用', 'ENABLE', NULL, '', '2019-03-14 17:11:40', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120784318939137, 1106120322450571266, 'ENABLE', '启用', 'ENABLE', NULL, '', '2019-03-14 17:12:00', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120825993543682, 1106120322450571266, 'FREEZE', '冻结', 'ENABLE', 1, '', '2019-03-14 17:12:10', '2019-03-16 10:56:36', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120875872206849, 1106120322450571266, 'DELETED', '已删除', 'ENABLE', -1221, '', '2019-03-14 17:12:22', '2019-03-16 10:56:53', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120935070613505, 1106120388036902914, 'Y', '删除', 'ENABLE', 23333, '', '2019-03-14 17:12:36', '2019-03-16 10:58:53', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1106120968910258177, 1106120388036902914, 'N', '未删除', 'ENABLE', 1212211221, '', '2019-03-14 17:12:44', '2019-03-16 10:59:03', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1149218674746355713, 1149217131989069826, 'BASE_SYSTEM', '基础功能', 'ENABLE', 1, '系统管理平台', '2019-07-11 15:27:38', '2020-01-01 17:14:45', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533174626959361, 1160532704105742337, '00101', '办公审批', 'ENABLE', 10, '', '2019-08-11 20:47:25', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533264645111810, 1160532704105742337, '00102', '行政审批', 'ENABLE', 20, '', '2019-08-11 20:47:47', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533377727741954, 1160532775455047681, 'KEY_LEAVE', '请假流程标识', 'ENABLE', 10, '', '2019-08-11 20:48:14', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533455343337474, 1160532775455047681, 'KEY_FINANCE', '财务流程标识', 'ENABLE', 20, '', '2019-08-11 20:48:32', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533574843252737, 1160532886713155585, '00401', '事假', 'ENABLE', 10, '', '2019-08-11 20:49:01', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533625615302658, 1160532886713155585, '00402', '婚假', 'ENABLE', 20, '', '2019-08-11 20:49:13', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533707215486977, 1160532886713155585, '00403', '产假', 'ENABLE', 30, '', '2019-08-11 20:49:32', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533765403066370, 1160532886713155585, '00404', '病假', 'ENABLE', 40, '', '2019-08-11 20:49:46', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533863834992641, 1160532886713155585, '00405', '公假', 'ENABLE', 50, '', '2019-08-11 20:50:09', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160533945309347841, 1160532886713155585, '00406', '年假', 'ENABLE', 60, '', '2019-08-11 20:50:29', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1160534007389241346, 1160532886713155585, '00407', '其他', 'ENABLE', 70, '', '2019-08-11 20:50:44', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1212300736972668929, 1149217131989069826, 'ENT_FUNC', '企业功能', 'ENABLE', 20, '企业功能', '2020-01-01 17:13:14', NULL, 1, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423166477712343040, 1423160140530053120, 'DICTTYPE', '字典类型', 'ENABLE', 1, '测试', '2021-08-05 14:18:24.098', '2021-08-05 14:18:24.098', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423234510216499200, 1423160140530053120, 'DICTTYPE4', '字典类型4', 'ENABLE', 1, '测试', '2021-08-05 18:48:44.31', '2021-08-05 18:48:44.31', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423234906741895168, 1423160140530053120, 'DICTTYPE5', '字典类型5', 'ENABLE', 1, '测试', '2021-08-05 18:50:18.848', '2021-08-05 18:50:18.848', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423235174556626944, 1423160140530053120, 'DICTTYPE6', '字典类型6', 'ENABLE', 1, '测试', '2021-08-05 18:51:22.701', '2021-08-05 18:51:22.701', 1, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423464964597334017, 1160532886713155586, '1', '直连设备', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423464964597334018, 1160532886713155586, '2', '网关子设备', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423464964597334019, 1160532886713155586, '3', '网关设备', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199425, 1160532886713155587, 'wechat', '企业微信', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199426, 1160532886713155587, 'dingtalk', '钉钉', 'ENABLE', 2, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199427, 1160532886713155587, 'feishu', '飞书', 'ENABLE', 3, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199428, 1160532886713155588, '2', '主动上报', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199430, 1160532886713155588, '18', '根据单个属性预处理', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199431, 1160532886713155590, '3', '整数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199433, 1160532886713155590, '1', '字符', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199434, 1160532886713155590, '4', '文本', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199435, 1160532886713155589, '%', '百分比', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199436, 1160532886713155589, 'count', '次', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199437, 1160532886713155589, 'r/min', '转每分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '常用单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199438, 1160532886713155589, 'nm', '纳米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199439, 1160532886713155589, 'μm', '微米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199440, 1160532886713155589, 'mm', '毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199441, 1160532886713155589, 'cm', '厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199442, 1160532886713155589, 'm', '米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199443, 1160532886713155589, 'km', '千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '长度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199444, 1160532886713155589, 'mm²', '平方毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199445, 1160532886713155589, 'cm²', '平方厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199446, 1160532886713155589, 'm²', '平方米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199447, 1160532886713155589, 'km²', '平方千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199448, 1160532886713155589, 'hm²', '公顷', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '面积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199449, 1160532886713155589, 'd', '天', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199450, 1160532886713155589, 'h', '小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199451, 1160532886713155589, 'min', '分钟', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199452, 1160532886713155589, 's', '秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199453, 1160532886713155589, 'ms', '毫秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199454, 1160532886713155589, 'μs', '微秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199455, 1160532886713155589, 'ns', '纳秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '时间单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199456, 1160532886713155589, 'mm³', '立方毫米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '体积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199457, 1160532886713155589, 'cm³', '立方厘米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '体积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199458, 1160532886713155589, 'm³', '立方米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '体积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199459, 1160532886713155589, 'km³', '立方千米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '体积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199460, 1160532886713155589, 'm³/s', '立方米每秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199461, 1160532886713155589, 'km³/s', '立方千米每秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199462, 1160532886713155589, 'cm³/s', '立方厘米每秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199463, 1160532886713155589, 'l/s', '升每秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199464, 1160532886713155589, 'm³/h', '立方米每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199465, 1160532886713155589, 'km³/h', '立方千米每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199466, 1160532886713155589, 'cm³/h', '立方厘米每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199467, 1160532886713155589, 'l/h', '升每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '流量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199468, 1160532886713155589, 'mL', '毫升', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '容积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199469, 1160532886713155589, 'L', '升', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '容积单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199470, 1160532886713155589, 'mg', '毫克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199471, 1160532886713155589, 'g', '克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199472, 1160532886713155589, 'kg', '千克', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199473, 1160532886713155589, 't', '吨', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '质量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199474, 1160532886713155589, 'Pa', '帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199475, 1160532886713155589, 'kPa', '千帕斯卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '压力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199476, 1160532886713155589, 'N', '牛顿', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199477, 1160532886713155589, 'N.m', '牛·米', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199432, 1160532886713155590, '0', '浮点数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199478, 1160532886713155589, 'K', '开尔文', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199479, 1160532886713155589, '℃', '摄氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199480, 1160532886713155589, '℉', '华氏度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '温度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199481, 1160532886713155589, 'J', '焦耳', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199482, 1160532886713155589, 'cal', '卡', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能量单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199483, 1160532886713155589, 'W', '瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199484, 1160532886713155589, 'kW', '千瓦特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '功率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199485, 1160532886713155589, 'rad', '弧度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199486, 1160532886713155589, '°', '度', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199487, 1160532886713155589, '′', '[角]分', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199488, 1160532886713155589, '″', '[角]秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '角度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199489, 1160532886713155589, 'Hz', '赫兹', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '频率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199490, 1160532886713155589, 'MHz', '兆赫兹', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '频率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199491, 1160532886713155589, 'GHz', 'G赫兹', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '频率单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199492, 1160532886713155589, 'm/s', '米每秒', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '速度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199493, 1160532886713155589, 'km/h', '千米每小时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '速度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199494, 1160532886713155589, 'kn', '节', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '速度单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199495, 1160532886713155589, 'V', '伏特', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199496, 1160532886713155589, 'kV', '千伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199497, 1160532886713155589, 'mV', '毫伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199498, 1160532886713155589, 'μV', '微伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199499, 1160532886713155589, 'A', '安培', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199500, 1160532886713155589, 'Ω', '欧姆', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199501, 1160532886713155589, 'KΩ', '千欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199502, 1160532886713155589, 'MΩ', '兆欧', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199503, 1160532886713155589, 'eV', '电子伏', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199504, 1160532886713155589, 'kW·h', '千瓦·时', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '电力单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199505, 1160532886713155589, 'kgce', 'Kg标准煤', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '能源单位'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199506, 1160532886713155591, '25', 'Replace', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199507, 1160532886713155591, '4', 'Trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199508, 1160532886713155591, '2', 'Right trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199509, 1160532886713155591, '3', 'Left trim', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '文本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199510, 1160532886713155591, '11', 'XML XPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199511, 1160532886713155591, '12', 'JSONPath', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '结构化数据'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199512, 1160532886713155591, '13', 'In range', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '验证'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199514, 1160532886713155591, '1', '自定义倍数', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义计算'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199517, 1160532886713155591, '7', '八进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199518, 1160532886713155591, '8', '十六进制转十进制', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '数制转换'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199519, 1160532886713155591, '21', 'JavaScript', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, '自定义脚本'); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199525, 1440492220332449792, '5', '紧急', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199526, 1440492220332449792, '4', '高级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199527, 1440492220332449792, '3', '中级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199528, 1440492220332449792, '1', '信息', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199529, 1440492220332449792, '2', '低级', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199531, 1160532886713155588, '0', 'Agent 采集', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1428599180229115911, 1428599180229115904, '0', '', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199532, 1440492220332449793, '8', 'CoAp', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199533, 1440492220332449793, '7', 'WEBSOCKET SSL', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199534, 1440492220332449793, '6', 'WEBSOCKET', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199535, 1440492220332449793, '5', 'HTTP', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199536, 1440492220332449793, '4', 'UDP', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199537, 1440492220332449793, '3', 'TCP', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199538, 1440492220332449793, '1', 'MQTT', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199539, 1440492220332449793, '2', 'MQTT TLS', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199540, 1440492220332449793, '9', 'CoAp DTLS', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199541, 1440492220332449794, '0', '待上传', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199542, 1440492220332449794, '1', '未发布', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199543, 1440492220332449794, '2', '已发布', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199544, 1440492220332449795, '0', 'MQTT 服务端', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199545, 1440492220332449795, '1', 'MQTT 客户端', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199546, 1440492220332449795, '2', 'TCP 服务端', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199547, 1440492220332449795, '3', 'TCP 客户端', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199548, 1440492220332449795, '4', 'UDP', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199549, 1440492220332449795, '5', 'HTTP 服务端', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199550, 1440492220332449795, '6', 'HTTP 客户端', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199551, 1440492220332449795, '7', 'WEBSOKCET 服务端', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199552, 1440492220332449795, '8', 'WEBSOKCET 客户端', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199553, 1440492220332449795, '9', 'CoAP 服务端', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199554, 1440492220332449795, '10', 'CoAP 客户端', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1428599180229115912, 1428599180229115904, '1', '是', 'ENABLE', 1, NULL, NULL, '2021-11-09 10:13:24.229', NULL, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1429987619034984449, 1142859918022911591, '1', '异步', 'ENABLE', NULL, NULL, NULL, '2021-11-09 10:19:22.483', NULL, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1429987619034984450, 1142859918022911591, '0', '同步', 'ENABLE', NULL, NULL, NULL, '2021-11-09 10:19:45.177', NULL, 1, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199555, 1440492220332449796, '1', '已停止', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); +INSERT INTO "public"."sys_dict" VALUES (1423897784372199556, 1440492220332449796, '0', '已启动', 'ENABLE', 1, NULL, NULL, NULL, NULL, NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_dict_type +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_dict_type"; +CREATE TABLE "public"."sys_dict_type" ( + "dict_type_id" int8 NOT NULL, + "code" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "remark" varchar(1000) COLLATE "pg_catalog"."default", + "system_flag" char(1) COLLATE "pg_catalog"."default" NOT NULL, + "status" varchar(10) COLLATE "pg_catalog"."default" NOT NULL, + "sort" int4, + "create_time" timestamp(6), + "create_user" int8, + "update_time" timestamp(6), + "update_user" int8 +) +; +COMMENT ON COLUMN "public"."sys_dict_type"."dict_type_id" IS '字典类型id'; +COMMENT ON COLUMN "public"."sys_dict_type"."code" IS '字典类型编码'; +COMMENT ON COLUMN "public"."sys_dict_type"."name" IS '字典类型名称'; +COMMENT ON COLUMN "public"."sys_dict_type"."remark" IS '字典描述'; +COMMENT ON COLUMN "public"."sys_dict_type"."system_flag" IS '是否是系统字典,Y-是,N-否'; +COMMENT ON COLUMN "public"."sys_dict_type"."status" IS '状态(字典)'; +COMMENT ON COLUMN "public"."sys_dict_type"."sort" IS '排序'; +COMMENT ON COLUMN "public"."sys_dict_type"."create_time" IS '添加时间'; +COMMENT ON COLUMN "public"."sys_dict_type"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."sys_dict_type"."update_time" IS '修改时间'; +COMMENT ON COLUMN "public"."sys_dict_type"."update_user" IS '修改人'; +COMMENT ON TABLE "public"."sys_dict_type" IS '字典类型表'; + +-- ---------------------------- +-- Records of sys_dict_type +-- ---------------------------- +INSERT INTO "public"."sys_dict_type" VALUES (1106120208097067009, 'SEX', '性别', '', 'Y', 'ENABLE', 4, '2019-03-14 17:09:43', 1, NULL, NULL); +INSERT INTO "public"."sys_dict_type" VALUES (1106120265689055233, 'STATUS', '状态', '', 'Y', 'ENABLE', 3, '2019-03-14 17:09:57', 1, NULL, NULL); +INSERT INTO "public"."sys_dict_type" VALUES (1106120322450571266, 'ACCOUNT_STATUS', '账号状态', '', 'Y', 'ENABLE', 40, '2019-03-14 17:10:10', 1, '2019-08-11 20:46:38', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1106120388036902914, 'DEL_FLAG', '是否删除', '', 'Y', 'ENABLE', 2, '2019-03-14 17:10:26', 1, '2019-03-27 16:26:31', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1149217131989069826, 'SYSTEM_TYPE', '系统分类', '系统所有分类的维护', 'Y', 'ENABLE', 50, '2019-07-11 15:21:30', 1, '2019-08-11 20:46:47', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532704105742337, 'FLOW_CATEGARY', '工作流分类', '工作流分类', 'Y', 'ENABLE', 60, '2019-08-11 20:45:33', 1, NULL, NULL); +INSERT INTO "public"."sys_dict_type" VALUES (1160532775455047681, 'FLOW_KEY', '工作流标识', '工作流标识', 'Y', 'ENABLE', 70, '2019-08-11 20:45:50', 1, NULL, NULL); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155585, 'LEAVE_TYPE', '请假类型', '请假类型', 'Y', 'ENABLE', 80, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155586, 'DEVICE_TYPE', '设备类型', '设备类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155587, 'MEDIA_TYPE', '通知类型', '通知类型', 'N', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155588, 'ATTR_TYPE', '产品属性类型', '产品属性类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155589, 'UNITS', '产品属性单位', '产品属性单位', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155590, 'DATA_TYPE', '产品属性值类型', '产品属性值类型', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1160532886713155591, 'DATA_PRE_TYPE', '数据预处理方法名称', '数据预处理方法名称', 'Y', 'ENABLE', 1, '2019-08-11 20:46:17', 1, '2019-08-11 20:46:23', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1423160140530053120, 'DICTTYPE', '字典类型', '测试', 'N', 'ENABLE', NULL, '2021-08-05 13:53:13.196', 1, '2021-08-05 13:53:13.196', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1428599180229115904, 'WHETHER', '是否', '是否', 'N', 'ENABLE', NULL, '2021-08-20 14:06:01.311', 1, '2021-08-20 14:06:01.311', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1440492220332449792, 'EVENT_LEVEL', '告警级别', '告警级别', 'N', 'ENABLE', NULL, '2021-09-22 09:44:43.035', 1, '2021-09-22 09:44:43.102', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1440492220332449793, 'PROTOCOL_TYPE', '协议类型', '协议类型', 'N', 'ENABLE', NULL, '2021-09-22 09:44:43.035', 1, '2021-09-22 09:44:43.102', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1440492220332449794, 'PROTOCOL_COMPONENT_STATUS', '协议組件状态', '协议組件状态', 'N', 'ENABLE', NULL, '2021-09-22 09:44:43.035', 1, '2021-09-22 09:44:43.102', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1440492220332449795, 'PROTOCOL_SERVICE_TYPE', '协议服务类型', '协议服务类型', 'N', 'ENABLE', NULL, '2021-09-22 09:44:43.035', 1, '2021-09-22 09:44:43.102', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1440492220332449796, 'PROTOCOL_GATEWAY_STATUS', '协议网关状态', '协议网关状态', 'N', 'ENABLE', NULL, '2021-09-22 09:44:43.035', 1, '2021-09-22 09:44:43.102', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1455807294571880448, '456456', '456456', '', 'N', 'ENABLE', NULL, '2021-11-03 16:01:21.274', 1, '2021-11-09 10:13:16.934', 1); +INSERT INTO "public"."sys_dict_type" VALUES (1142859918022911591, 'EXECUTE_TYPE', '服务执行方式', '服务执行方式', 'N', 'ENABLE', 1, NULL, NULL, '2021-11-09 10:33:52.458', 1); + +-- ---------------------------- +-- Table structure for sys_login_log +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_login_log"; +CREATE TABLE "public"."sys_login_log" ( + "log_name" varchar(255) COLLATE "pg_catalog"."default", + "user_id" int8, + "succeed" varchar(255) COLLATE "pg_catalog"."default", + "message" text COLLATE "pg_catalog"."default", + "ip_address" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "login_log_id" int8 NOT NULL, + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."sys_login_log"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of sys_login_log +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_menu +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_menu"; +CREATE TABLE "public"."sys_menu" ( + "menu_id" int8 NOT NULL, + "code" varchar(255) COLLATE "pg_catalog"."default", + "pcode" varchar(255) COLLATE "pg_catalog"."default", + "pcodes" varchar(255) COLLATE "pg_catalog"."default", + "name" varchar(255) COLLATE "pg_catalog"."default", + "icon" varchar(255) COLLATE "pg_catalog"."default", + "url" varchar(255) COLLATE "pg_catalog"."default", + "sort" int2, + "levels" int2, + "menu_flag" varchar(32) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "status" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "update_time" timestamp(6), + "create_user" int8, + "update_user" int8, + "admin_flag" varchar(32) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."sys_menu"."menu_id" IS '菜单ID'; +COMMENT ON COLUMN "public"."sys_menu"."code" IS '菜单编号'; +COMMENT ON COLUMN "public"."sys_menu"."pcode" IS '菜单父编号'; +COMMENT ON COLUMN "public"."sys_menu"."pcodes" IS '当前菜单的所有父菜单编号'; +COMMENT ON COLUMN "public"."sys_menu"."name" IS '菜单名称'; +COMMENT ON COLUMN "public"."sys_menu"."icon" IS '菜单图标'; +COMMENT ON COLUMN "public"."sys_menu"."url" IS 'URL地址'; +COMMENT ON COLUMN "public"."sys_menu"."sort" IS '菜单排序号'; +COMMENT ON COLUMN "public"."sys_menu"."levels" IS '菜单层级'; +COMMENT ON COLUMN "public"."sys_menu"."menu_flag" IS '是否是菜单(字典)'; +COMMENT ON COLUMN "public"."sys_menu"."remark" IS '备注'; +COMMENT ON COLUMN "public"."sys_menu"."status" IS '菜单状态(字典)'; +COMMENT ON COLUMN "public"."sys_menu"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."sys_menu"."update_time" IS '修改时间'; +COMMENT ON COLUMN "public"."sys_menu"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."sys_menu"."update_user" IS '修改人'; +COMMENT ON COLUMN "public"."sys_menu"."admin_flag" IS '是否是超级管理员菜单'; + +-- ---------------------------- +-- Records of sys_menu +-- ---------------------------- +INSERT INTO "public"."sys_menu" VALUES (169, 'analyse', '0', '[0],', '统计分析', NULL, '/analyse', 1, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (179, 'alarmList', 'alarm', '[0],[alarm],', '告警记录', NULL, '/alarm/alarmList', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (191, 'alarmAnalyse', 'alarm', '[0],[alarm],', '告警分析', NULL, '/alarm/analyse', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (193, 'scene ', 'rule', '[0],[rule],', '场景联动', NULL, '/rule/scene', 3, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (105, 'system', '0', '[0],', '系统管理', NULL, '/system', 11, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (106, 'userMgr', '0', '[0],', '用户管理', NULL, '/userMgr', 10, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (107, 'mgr_add', 'mgr', '[0],[userMgr],[mgr],', '添加用户', NULL, '/mgr/add', 1, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (108, 'mgr_edit', 'mgr', '[0],[userMgr],[mgr],', '修改用户', NULL, '/mgr/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (109, 'mgr_delete', 'mgr', '[0],[userMgr],[mgr],', '删除用户', NULL, '/mgr/delete', 3, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (110, 'reset', 'mgr', '[0],[userMgr],[mgr],', '重置密码', NULL, '/mgr/reset', 4, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (113, 'mgr_setRole', 'mgr', '[0],[userMgr],[mgr],', '分配角色', NULL, '/mgr/setRole', 7, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (114, 'role', 'system', '[0],[system],', '角色管理', NULL, '/system/role', 111, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (115, 'role_add', 'role', '[0],[system],[role],', '添加角色', NULL, '/role/add', 1, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (116, 'role_edit', 'role', '[0],[system],[role],', '修改角色', NULL, '/role/edit', 2, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (117, 'role_remove', 'role', '[0],[system],[role],', '删除角色', NULL, '/role/remove', 3, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (119, 'menu', 'system', '[0],[system],', '菜单管理', NULL, '/menu', 50, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (128, 'businessLog', 'log', '[0],[log],', '业务日志', NULL, '/log/businessLog', 91, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (132, 'dict', 'system', '[0],[system],', '系统字典', NULL, '/system/dictType', 113, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (133, 'loginLog', 'log', '[0],[log],', '登录日志', NULL, '/log/loginLog', 92, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (138, 'dict_add', 'dict', '[0],[system],[dict],', '添加字典', NULL, '/dictType/addItem', 1, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (139, 'dict_update', 'dict', '[0],[system],[dict],', '修改字典', NULL, '/dictType/editItem', 1, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (140, 'dict_delete', 'dict', '[0],[system],[dict],', '删除字典', NULL, '/dictType/delete', 1, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (151, 'menu_list', 'menu', '[0],[system],[menu],', '菜单列表', NULL, '/menu/list', 5, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (156, 'dict_list', 'dict', '[0],[system],[dict],', '字典列表', NULL, '/dict/list', 5, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (158, 'log_list', 'log', '[0],[system],[log],', '日志列表', NULL, '/log/list', 2, 3, 'N', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (164, 'role_list', 'role', '[0],[system],[role],', '角色列表', NULL, '/role/list', 7, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (167, 'mgr_list', 'mgr', '[0],[userMgr],[mgr],', '用户列表', NULL, '/mgr/list', 10, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (168, 'usrGrp', 'userMgr', '[0],[userMgr],', '用户组管理', NULL, '/userMgr/userGroup', 102, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (170, 'dev_mgr', '0', '[0],', '设备管理', NULL, '/deviceMgr', 3, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (171, 'product_mgr', '0', '[0],', '产品管理', NULL, '/productMgr', 4, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (173, 'view', '0', '[0],', '可视化', NULL, '/view', 99, 1, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (174, 'auth', 'system', '[0],[system],', '平台授权', NULL, '/system/auth', 60, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (176, 'dev_log', 'analyse', '[0],[analyse],', '设备日志', NULL, '/analyse/devLog', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (177, 'dev', 'dev_mgr', '[0],[dev_mgr],', '设备', NULL, '/deviceMgr/device', 41, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (178, 'dev_group', 'dev_mgr', '[0],[dev_mgr],', '设备组', NULL, '/deviceMgr/deviceGroup', 42, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (180, 'product', 'product_mgr', '[0],[product_mgr],', '产品', NULL, '/productMgr/product', 51, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (181, 'product_type', 'product_mgr', '[0],[product_mgr],', '产品分类', NULL, '/productMgr/productType', 52, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (183, 'grafana', 'view', '[0],[view],', 'Grafana配置', NULL, '/view/grafana', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (184, 'log', '0', '[0],', '系统日志', NULL, '/log', 9, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (186, 'sysParam', 'system', '[0],[system],', '系统参数', NULL, '/system/sysParam', 114, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (187, 'media', 'system', '[0],[system],', '通知配置', NULL, '/system/media', 115, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (189, 'home', 'analyse', '[0],[analyse],', '全局概览', NULL, '/analyse/home', 1, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (190, 'latest', 'analyse', '[0],[analyse],', '最新数据', NULL, '/analyse/latest', 1, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (192, 'alarm', '0', '[0],', '告警管理', NULL, '/alarm', 6, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (194, 'rule', '0', '[0],', '规则引擎', NULL, '/rule', 5, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (195, 'process', 'rule', '[0],[rule],', '流程配置', NULL, '/rule/process', 4, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (196, 'api', 'dev_mgr', '[0],[dev_mgr],', '设备调试', NULL, '/deviceMgr/debug', 43, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (197, 'about', '0', '[0],', '关于我们', NULL, '/about', 99, 1, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (198, 'realTime', '0', '[0],', '平台监控', NULL, '/realTime', 7, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (199, 'proxyInfo', 'system', '[0],[system],', '代理配置', NULL, '/system/proxyInfo', 116, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (200, 'proxyMonitor', 'realTime', '[0],[realTime],', '代理监控', NULL, '/realTime/proxy', 82, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (201, 'grafana', 'analyse', '[0],[analyse],', '数据大屏', NULL, '/analyse/grafana', 5, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (202, 'dev_add', 'dev', '[0],[dev_mgr],[dev],', '增加设备', NULL, '/deviceMgr/device/add', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (203, 'dev_update', 'dev', '[0],[dev_mgr],[dev],', '修改设备', NULL, '/deviceMgr/device/update', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (204, 'dev_delete', 'dev', '[0],[dev_mgr],[dev],', '删除设备', NULL, '/deviceMgr/device/delete', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (205, 'dev_list', 'dev', '[0],[dev_mgr],[dev],', '设备列表', NULL, '/deviceMgr/device/list', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (206, 'dev_detail', 'dev', '[0],[dev_mgr],[dev],', '设备详情', NULL, '/deviceMgr/device/detail', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (207, 'product_add', 'product', '[0],[product_mgr],[product],', '增加产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (208, 'product_update', 'product', '[0],[product_mgr],[product],', '修改产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (209, 'product_delete', 'product', '[0],[product_mgr],[product],', '删除产品', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (210, 'product_list', 'product', '[0],[product_mgr],[product],', '产品列表', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (118, 'role_setAuthority', 'role', '[0],[system],[role],', '配置菜单', NULL, '/role/setAuthority', 4, 3, 'N', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (120, 'menu_add', 'menu', '[0],[system],[menu],', '添加菜单', NULL, '/menu/add', 1, 3, 'N', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (121, 'menu_edit', 'menu', '[0],[system],[menu],', '修改菜单', NULL, '/menu/edit', 2, 3, 'N', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (122, 'menu_remove', 'menu', '[0],[system],[menu],', '删除菜单', NULL, '/menu/remove', 3, 3, 'N', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (219, 'distributed', 'dev_mgr', '[0],[dev_mgr],', '设备分布', NULL, '/deviceMgr/distributed', 3, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (220, 'platformLog', '0', '[0],', '平台日志', NULL, '/platformLog', 8, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (221, 'platformLog_event', 'platformLog', '[0],[platformLog],', '事件日志', NULL, '/platformLog/event', 34, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (222, 'platformLog_service', 'platformLog', '[0],[platformLog],', '服务日志', NULL, '/platformLog/service', 33, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (223, 'platformLog_alert', 'platformLog', '[0],[platformLog],', '告警日志', NULL, '/platformLog/alert', 31, 2, 'Y', NULL, 'DISABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (224, 'platformLog_linkage', 'platformLog', '[0],[platformLog],', '联动日志', NULL, '/platformLog/linkage', 32, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (225, 'visualization', '0', '[0],', '可视化', NULL, '/visualization', 2, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (226, 'visualization_distributed', 'visualization', '[0],[visualization],', '设备分布', NULL, '/visualization/distributed', 21, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (227, 'visualization_grafana', 'visualization', '[0],[visualization],', 'Grafana', NULL, '/visualization/grafana', 22, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (228, 'visualization_building', 'visualization', '[0],[visualization],', '楼宇场景', NULL, '/visualization/building', 23, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (229, 'agreement', '0', '[0],', '协议管理', NULL, '/agreement', 6, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (230, 'agreement_module', 'agreement', '[0],[agreement],', '协议组件', NULL, '/agreement/module', 6, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (231, 'agreement_communication', 'agreement', '[0],[agreement],', '通信服务', NULL, '/agreement/communication', 6, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (232, 'agreement_gateway', 'agreement', '[0],[agreement],', '协议网关', NULL, '/agreement/gateway', 6, 1, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (211, 'product_detail', 'product', '[0],[product_mgr],[product],', '产品详情', NULL, '/productMgr/product', 3, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (212, 'tenant', 'system', '[0],[system],', '租户管理', NULL, '/system/tenant', 112, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'Y'); +INSERT INTO "public"."sys_menu" VALUES (213, 'tenant_add', 'tenant', '[0],[system],', '租户增加', NULL, '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (214, 'tenant_update', 'tenant', '[0],[system],', '租户修改', NULL, '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (215, 'tenant_list', 'tenant', '[0],[system],', '租户列表', NULL, '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (216, 'tenant_delete', 'tenant', '[0],[system],', '租户删除', NULL, '/system/tenant', 10, 3, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (217, 'mgr', 'userMgr', '[0],[userMgr],', '用户', NULL, '/userMgr/user', 101, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); +INSERT INTO "public"."sys_menu" VALUES (218, 'platform', 'realTime', '[0],[realTime],', '主服务监控', NULL, '/realTime/platform', 81, 2, 'Y', NULL, 'ENABLE', NULL, NULL, NULL, NULL, 'N'); + +-- ---------------------------- +-- Table structure for sys_operation_log +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_operation_log"; +CREATE TABLE "public"."sys_operation_log" ( + "operation_log_id" int8 NOT NULL, + "log_type" varchar(32) COLLATE "pg_catalog"."default", + "log_name" varchar(255) COLLATE "pg_catalog"."default", + "user_id" int8, + "class_name" varchar(255) COLLATE "pg_catalog"."default", + "method" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(6), + "succeed" varchar(32) COLLATE "pg_catalog"."default", + "message" text COLLATE "pg_catalog"."default", + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."sys_operation_log"."operation_log_id" IS '操作日志ID'; +COMMENT ON COLUMN "public"."sys_operation_log"."log_type" IS '日志类型【字典】'; +COMMENT ON COLUMN "public"."sys_operation_log"."log_name" IS '日志名称'; +COMMENT ON COLUMN "public"."sys_operation_log"."user_id" IS '用户ID'; +COMMENT ON COLUMN "public"."sys_operation_log"."class_name" IS '类名称'; +COMMENT ON COLUMN "public"."sys_operation_log"."method" IS '方法名称'; +COMMENT ON COLUMN "public"."sys_operation_log"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."sys_operation_log"."succeed" IS '是否成功【字典】'; +COMMENT ON COLUMN "public"."sys_operation_log"."message" IS '备注'; +COMMENT ON COLUMN "public"."sys_operation_log"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of sys_operation_log +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_role +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_role"; +CREATE TABLE "public"."sys_role" ( + "role_id" int8 NOT NULL, + "name" varchar(255) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "sort" int2, + "create_user" int8, + "update_user" int8, + "create_time" timestamp(6), + "update_time" timestamp(6) +) +; + +-- ---------------------------- +-- Records of sys_role +-- ---------------------------- +INSERT INTO "public"."sys_role" VALUES (1, '超级管理员', 'administrator', 1, NULL, 1, NULL, '2021-08-17 10:57:36.612'); + +-- ---------------------------- +-- Table structure for sys_role_menu +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_role_menu"; +CREATE TABLE "public"."sys_role_menu" ( + "role_id" int8, + "menu_id" int8 +) +; + +-- ---------------------------- +-- Records of sys_role_menu +-- ---------------------------- +INSERT INTO "public"."sys_role_menu" VALUES (1, 232); +INSERT INTO "public"."sys_role_menu" VALUES (1, 231); +INSERT INTO "public"."sys_role_menu" VALUES (1, 230); +INSERT INTO "public"."sys_role_menu" VALUES (1, 229); +INSERT INTO "public"."sys_role_menu" VALUES (1, 228); +INSERT INTO "public"."sys_role_menu" VALUES (2, 227); +INSERT INTO "public"."sys_role_menu" VALUES (1, 227); +INSERT INTO "public"."sys_role_menu" VALUES (2, 226); +INSERT INTO "public"."sys_role_menu" VALUES (1, 226); +INSERT INTO "public"."sys_role_menu" VALUES (2, 225); +INSERT INTO "public"."sys_role_menu" VALUES (1, 225); +INSERT INTO "public"."sys_role_menu" VALUES (1, 224); +INSERT INTO "public"."sys_role_menu" VALUES (2, 224); +INSERT INTO "public"."sys_role_menu" VALUES (1, 223); +INSERT INTO "public"."sys_role_menu" VALUES (2, 222); +INSERT INTO "public"."sys_role_menu" VALUES (1, 222); +INSERT INTO "public"."sys_role_menu" VALUES (1, 221); +INSERT INTO "public"."sys_role_menu" VALUES (2, 221); +INSERT INTO "public"."sys_role_menu" VALUES (2, 220); +INSERT INTO "public"."sys_role_menu" VALUES (1, 220); +INSERT INTO "public"."sys_role_menu" VALUES (1, 219); +INSERT INTO "public"."sys_role_menu" VALUES (2, 218); +INSERT INTO "public"."sys_role_menu" VALUES (1, 218); +INSERT INTO "public"."sys_role_menu" VALUES (2, 217); +INSERT INTO "public"."sys_role_menu" VALUES (1, 217); +INSERT INTO "public"."sys_role_menu" VALUES (1, 217); +INSERT INTO "public"."sys_role_menu" VALUES (1, 216); +INSERT INTO "public"."sys_role_menu" VALUES (1, 215); +INSERT INTO "public"."sys_role_menu" VALUES (1, 214); +INSERT INTO "public"."sys_role_menu" VALUES (1, 213); +INSERT INTO "public"."sys_role_menu" VALUES (1, 212); +INSERT INTO "public"."sys_role_menu" VALUES (1, 211); +INSERT INTO "public"."sys_role_menu" VALUES (2, 211); +INSERT INTO "public"."sys_role_menu" VALUES (2, 210); +INSERT INTO "public"."sys_role_menu" VALUES (1, 210); +INSERT INTO "public"."sys_role_menu" VALUES (1, 209); +INSERT INTO "public"."sys_role_menu" VALUES (2, 209); +INSERT INTO "public"."sys_role_menu" VALUES (1, 208); +INSERT INTO "public"."sys_role_menu" VALUES (2, 208); +INSERT INTO "public"."sys_role_menu" VALUES (1, 207); +INSERT INTO "public"."sys_role_menu" VALUES (2, 207); +INSERT INTO "public"."sys_role_menu" VALUES (1, 206); +INSERT INTO "public"."sys_role_menu" VALUES (2, 206); +INSERT INTO "public"."sys_role_menu" VALUES (1, 205); +INSERT INTO "public"."sys_role_menu" VALUES (2, 205); +INSERT INTO "public"."sys_role_menu" VALUES (1, 204); +INSERT INTO "public"."sys_role_menu" VALUES (2, 204); +INSERT INTO "public"."sys_role_menu" VALUES (2, 203); +INSERT INTO "public"."sys_role_menu" VALUES (1, 203); +INSERT INTO "public"."sys_role_menu" VALUES (1, 202); +INSERT INTO "public"."sys_role_menu" VALUES (2, 202); +INSERT INTO "public"."sys_role_menu" VALUES (1, 201); +INSERT INTO "public"."sys_role_menu" VALUES (1, 200); +INSERT INTO "public"."sys_role_menu" VALUES (2, 200); +INSERT INTO "public"."sys_role_menu" VALUES (2, 199); +INSERT INTO "public"."sys_role_menu" VALUES (1, 199); +INSERT INTO "public"."sys_role_menu" VALUES (2, 198); +INSERT INTO "public"."sys_role_menu" VALUES (1, 198); +INSERT INTO "public"."sys_role_menu" VALUES (1, 197); +INSERT INTO "public"."sys_role_menu" VALUES (2, 196); +INSERT INTO "public"."sys_role_menu" VALUES (1, 196); +INSERT INTO "public"."sys_role_menu" VALUES (1, 195); +INSERT INTO "public"."sys_role_menu" VALUES (2, 194); +INSERT INTO "public"."sys_role_menu" VALUES (1, 194); +INSERT INTO "public"."sys_role_menu" VALUES (2, 193); +INSERT INTO "public"."sys_role_menu" VALUES (1, 193); +INSERT INTO "public"."sys_role_menu" VALUES (2, 192); +INSERT INTO "public"."sys_role_menu" VALUES (1, 192); +INSERT INTO "public"."sys_role_menu" VALUES (1, 191); +INSERT INTO "public"."sys_role_menu" VALUES (1, 190); +INSERT INTO "public"."sys_role_menu" VALUES (1, 189); +INSERT INTO "public"."sys_role_menu" VALUES (2, 189); +INSERT INTO "public"."sys_role_menu" VALUES (1, 188); +INSERT INTO "public"."sys_role_menu" VALUES (1, 187); +INSERT INTO "public"."sys_role_menu" VALUES (2, 187); +INSERT INTO "public"."sys_role_menu" VALUES (1, 186); +INSERT INTO "public"."sys_role_menu" VALUES (1, 185); +INSERT INTO "public"."sys_role_menu" VALUES (1, 184); +INSERT INTO "public"."sys_role_menu" VALUES (2, 184); +INSERT INTO "public"."sys_role_menu" VALUES (1, 183); +INSERT INTO "public"."sys_role_menu" VALUES (1, 182); +INSERT INTO "public"."sys_role_menu" VALUES (1, 181); +INSERT INTO "public"."sys_role_menu" VALUES (2, 181); +INSERT INTO "public"."sys_role_menu" VALUES (2, 180); +INSERT INTO "public"."sys_role_menu" VALUES (1, 180); +INSERT INTO "public"."sys_role_menu" VALUES (2, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1, 179); +INSERT INTO "public"."sys_role_menu" VALUES (1, 178); +INSERT INTO "public"."sys_role_menu" VALUES (2, 178); +INSERT INTO "public"."sys_role_menu" VALUES (2, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1, 177); +INSERT INTO "public"."sys_role_menu" VALUES (1, 176); +INSERT INTO "public"."sys_role_menu" VALUES (1, 175); +INSERT INTO "public"."sys_role_menu" VALUES (1, 174); +INSERT INTO "public"."sys_role_menu" VALUES (1, 173); +INSERT INTO "public"."sys_role_menu" VALUES (1, 172); +INSERT INTO "public"."sys_role_menu" VALUES (1, 171); +INSERT INTO "public"."sys_role_menu" VALUES (2, 171); +INSERT INTO "public"."sys_role_menu" VALUES (2, 170); +INSERT INTO "public"."sys_role_menu" VALUES (1, 170); +INSERT INTO "public"."sys_role_menu" VALUES (2, 169); +INSERT INTO "public"."sys_role_menu" VALUES (1, 169); +INSERT INTO "public"."sys_role_menu" VALUES (2, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1, 168); +INSERT INTO "public"."sys_role_menu" VALUES (1, 167); +INSERT INTO "public"."sys_role_menu" VALUES (2, 167); +INSERT INTO "public"."sys_role_menu" VALUES (1, 167); +INSERT INTO "public"."sys_role_menu" VALUES (1, 164); +INSERT INTO "public"."sys_role_menu" VALUES (1, 156); +INSERT INTO "public"."sys_role_menu" VALUES (1, 140); +INSERT INTO "public"."sys_role_menu" VALUES (1, 139); +INSERT INTO "public"."sys_role_menu" VALUES (1, 138); +INSERT INTO "public"."sys_role_menu" VALUES (1, 133); +INSERT INTO "public"."sys_role_menu" VALUES (2, 133); +INSERT INTO "public"."sys_role_menu" VALUES (1, 132); +INSERT INTO "public"."sys_role_menu" VALUES (1, 128); +INSERT INTO "public"."sys_role_menu" VALUES (2, 128); +INSERT INTO "public"."sys_role_menu" VALUES (1, 122); +INSERT INTO "public"."sys_role_menu" VALUES (1, 121); +INSERT INTO "public"."sys_role_menu" VALUES (1, 120); +INSERT INTO "public"."sys_role_menu" VALUES (1, 119); +INSERT INTO "public"."sys_role_menu" VALUES (1, 118); +INSERT INTO "public"."sys_role_menu" VALUES (1, 117); +INSERT INTO "public"."sys_role_menu" VALUES (1, 116); +INSERT INTO "public"."sys_role_menu" VALUES (1, 115); +INSERT INTO "public"."sys_role_menu" VALUES (1, 114); +INSERT INTO "public"."sys_role_menu" VALUES (1, 113); +INSERT INTO "public"."sys_role_menu" VALUES (1, 113); +INSERT INTO "public"."sys_role_menu" VALUES (2, 113); +INSERT INTO "public"."sys_role_menu" VALUES (1, 112); +INSERT INTO "public"."sys_role_menu" VALUES (1, 111); +INSERT INTO "public"."sys_role_menu" VALUES (1, 110); +INSERT INTO "public"."sys_role_menu" VALUES (2, 110); +INSERT INTO "public"."sys_role_menu" VALUES (1, 110); +INSERT INTO "public"."sys_role_menu" VALUES (1, 109); +INSERT INTO "public"."sys_role_menu" VALUES (2, 109); +INSERT INTO "public"."sys_role_menu" VALUES (1, 109); +INSERT INTO "public"."sys_role_menu" VALUES (1, 108); +INSERT INTO "public"."sys_role_menu" VALUES (1, 108); +INSERT INTO "public"."sys_role_menu" VALUES (2, 108); +INSERT INTO "public"."sys_role_menu" VALUES (2, 107); +INSERT INTO "public"."sys_role_menu" VALUES (1, 107); +INSERT INTO "public"."sys_role_menu" VALUES (1, 107); +INSERT INTO "public"."sys_role_menu" VALUES (1, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1, 106); +INSERT INTO "public"."sys_role_menu" VALUES (2, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1, 106); +INSERT INTO "public"."sys_role_menu" VALUES (1, 105); +INSERT INTO "public"."sys_role_menu" VALUES (2, 105); + +-- ---------------------------- +-- Table structure for sys_user +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_user"; +CREATE TABLE "public"."sys_user" ( + "account" varchar(32) COLLATE "pg_catalog"."default", + "password" varchar(32) COLLATE "pg_catalog"."default", + "salt" varchar(32) COLLATE "pg_catalog"."default", + "name" varchar(64) COLLATE "pg_catalog"."default", + "email" varchar(64) COLLATE "pg_catalog"."default", + "phone" varchar(16) COLLATE "pg_catalog"."default", + "role_id" int8, + "user_group_id" int8, + "status" varchar(32) COLLATE "pg_catalog"."default", + "create_user" int8, + "update_user" int8, + "create_time" timestamp(6), + "update_time" timestamp(6), + "user_id" int8 NOT NULL DEFAULT nextval('sys_user_user_id_seq'::regclass), + "zbx_token" varchar(255) COLLATE "pg_catalog"."default", + "zbx_id" varchar(64) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."sys_user"."account" IS '登陆账号名'; +COMMENT ON COLUMN "public"."sys_user"."password" IS '密码'; +COMMENT ON COLUMN "public"."sys_user"."salt" IS '密码盐'; +COMMENT ON COLUMN "public"."sys_user"."name" IS '用户名'; +COMMENT ON COLUMN "public"."sys_user"."email" IS '电子邮箱地址'; +COMMENT ON COLUMN "public"."sys_user"."phone" IS '手机号'; +COMMENT ON COLUMN "public"."sys_user"."role_id" IS '角色ID'; +COMMENT ON COLUMN "public"."sys_user"."user_group_id" IS '用户组ID'; +COMMENT ON COLUMN "public"."sys_user"."status" IS '状态'; +COMMENT ON COLUMN "public"."sys_user"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."sys_user"."update_user" IS '修改人'; +COMMENT ON COLUMN "public"."sys_user"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."sys_user"."update_time" IS '更新时间'; +COMMENT ON COLUMN "public"."sys_user"."user_id" IS '用户ID'; +COMMENT ON COLUMN "public"."sys_user"."zbx_token" IS 'zabbix 登陆 token'; +COMMENT ON COLUMN "public"."sys_user"."zbx_id" IS 'zabbix 用户ID'; +COMMENT ON COLUMN "public"."sys_user"."remark" IS '备注'; +COMMENT ON COLUMN "public"."sys_user"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of sys_user +-- ---------------------------- +INSERT INTO "public"."sys_user" VALUES ('root', '17db03c22596b7609c7c9704f16663e0', 'abcdef', '超级管理员', '888888@qq.com', '13812345678', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-07-30 21:43:02.686', '2021-07-30 21:43:02.686', 1, '5859e004e8d2a23e6c330c3f9cd277e2', '4', NULL, NULL); +INSERT INTO "public"."sys_user" VALUES ('Admin', 'cbde417443393372dbac9c185a6ec159', 'gt3zs', '超级管理员', '', '', 1, 1437232484602372096, 'ENABLE', 1, 1, '2021-09-28 09:38:33.668', '2021-09-28 09:38:33.668', 122, 'f6ce31c5f70bf40fae2067087254202c', '1', NULL, NULL); + +-- ---------------------------- +-- Table structure for sys_user_group +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_user_group"; +CREATE TABLE "public"."sys_user_group" ( + "group_name" varchar(255) COLLATE "pg_catalog"."default", + "zbx_id" varchar(32) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(0), + "create_user" int8, + "update_time" timestamp(0), + "update_user" int8, + "status" varchar(32) COLLATE "pg_catalog"."default" DEFAULT 1, + "user_group_id" int8 NOT NULL, + "tenant_id" int8 +) +; +COMMENT ON COLUMN "public"."sys_user_group"."tenant_id" IS '租户ID'; + +-- ---------------------------- +-- Records of sys_user_group +-- ---------------------------- + +-- ---------------------------- +-- Table structure for sys_usrgrp_devicegrp +-- ---------------------------- +DROP TABLE IF EXISTS "public"."sys_usrgrp_devicegrp"; +CREATE TABLE "public"."sys_usrgrp_devicegrp" ( + "user_group_id" int8, + "device_group_id" int8 +) +; + +-- ---------------------------- +-- Records of sys_usrgrp_devicegrp +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tag +-- ---------------------------- +DROP TABLE IF EXISTS "public"."tag"; +CREATE TABLE "public"."tag" ( + "sid" varchar(64) COLLATE "pg_catalog"."default" NOT NULL, + "tag" varchar(64) COLLATE "pg_catalog"."default", + "value" varchar(64) COLLATE "pg_catalog"."default", + "id" int4 NOT NULL DEFAULT nextval('tag_id_seq'::regclass), + "template_id" int4, + "create_user" int8, + "update_user" int8, + "create_time" timestamp(6), + "update_time" timestamp(6) +) +; +COMMENT ON COLUMN "public"."tag"."sid" IS '所属ID'; +COMMENT ON COLUMN "public"."tag"."tag" IS '标签'; +COMMENT ON COLUMN "public"."tag"."value" IS '标签值'; +COMMENT ON COLUMN "public"."tag"."id" IS 'ID'; +COMMENT ON COLUMN "public"."tag"."template_id" IS '继承的ID'; +COMMENT ON COLUMN "public"."tag"."create_user" IS '创建人'; +COMMENT ON COLUMN "public"."tag"."update_user" IS '修改人'; +COMMENT ON COLUMN "public"."tag"."create_time" IS '创建时间'; +COMMENT ON COLUMN "public"."tag"."update_time" IS '更新时间'; + +-- ---------------------------- +-- Records of tag +-- ---------------------------- + +-- ---------------------------- +-- Table structure for task_info +-- ---------------------------- +DROP TABLE IF EXISTS "public"."task_info"; +CREATE TABLE "public"."task_info" ( + "id" int4 NOT NULL DEFAULT nextval('task_info_id_seq'::regclass), + "remark" varchar(255) COLLATE "pg_catalog"."default", + "task_timeout" int4 NOT NULL, + "task_fail_retry_count" int4 NOT NULL, + "trigger_status" varchar(8) COLLATE "pg_catalog"."default" NOT NULL, + "trigger_last_time" int8 NOT NULL, + "trigger_next_time" int8 NOT NULL, + "misfire_strategy" varchar(255) COLLATE "pg_catalog"."default" NOT NULL, + "schedule_type" varchar(255) COLLATE "pg_catalog"."default", + "schedule_conf" varchar(255) COLLATE "pg_catalog"."default", + "executor_param" text COLLATE "pg_catalog"."default", + "create_time" timestamp(0), + "create_user" int8, + "update_time" timestamp(0), + "update_user" int8 +) +; +COMMENT ON COLUMN "public"."task_info"."id" IS '任务ID'; +COMMENT ON COLUMN "public"."task_info"."remark" IS '任务描述'; +COMMENT ON COLUMN "public"."task_info"."task_timeout" IS '任务执行超时时间'; +COMMENT ON COLUMN "public"."task_info"."task_fail_retry_count" IS '失败重试次数'; +COMMENT ON COLUMN "public"."task_info"."trigger_status" IS '调度状态:DISABLE-停止,ENABLE-运行'; +COMMENT ON COLUMN "public"."task_info"."trigger_last_time" IS '上次调度时间'; +COMMENT ON COLUMN "public"."task_info"."trigger_next_time" IS '下次调度时间'; +COMMENT ON COLUMN "public"."task_info"."misfire_strategy" IS '调度过期策略'; +COMMENT ON COLUMN "public"."task_info"."schedule_type" IS '调度类型'; +COMMENT ON COLUMN "public"."task_info"."schedule_conf" IS '调度配置,值含义取决于调度类型'; +COMMENT ON COLUMN "public"."task_info"."executor_param" IS '任务执行参数'; + +-- ---------------------------- +-- Records of task_info +-- ---------------------------- + +-- ---------------------------- +-- Table structure for tenant_info +-- ---------------------------- +DROP TABLE IF EXISTS "public"."tenant_info"; +CREATE TABLE "public"."tenant_info" ( + "tenant_id" int8 NOT NULL, + "name" varchar(64) COLLATE "pg_catalog"."default", + "remark" varchar(255) COLLATE "pg_catalog"."default", + "create_time" timestamp(0), + "create_user" int8, + "update_time" timestamp(0), + "update_user" int8, + "account" varchar(32) COLLATE "pg_catalog"."default", + "contact" varchar(16) COLLATE "pg_catalog"."default", + "phone" varchar(16) COLLATE "pg_catalog"."default", + "status" varchar(8) COLLATE "pg_catalog"."default" +) +; +COMMENT ON COLUMN "public"."tenant_info"."name" IS '租户名称'; +COMMENT ON COLUMN "public"."tenant_info"."account" IS '租户管理员 账号'; +COMMENT ON COLUMN "public"."tenant_info"."contact" IS '联系人'; +COMMENT ON COLUMN "public"."tenant_info"."phone" IS '电话'; +COMMENT ON COLUMN "public"."tenant_info"."status" IS '状态'; + +-- ---------------------------- +-- Records of tenant_info +-- ---------------------------- + +-- ---------------------------- +-- Table structure for token +-- ---------------------------- +DROP TABLE IF EXISTS "public"."token"; +CREATE TABLE "public"."token" ( + "name" varchar(64) COLLATE "pg_catalog"."default" DEFAULT ''::character varying, + "description" text COLLATE "pg_catalog"."default" DEFAULT ''::text, + "user_id" int8 NOT NULL, + "token" varchar(256) COLLATE "pg_catalog"."default" NOT NULL, + "status" varchar(8) COLLATE "pg_catalog"."default" NOT NULL DEFAULT 0, + "expires_at" int4 NOT NULL DEFAULT 0, + "token_id" int4 NOT NULL DEFAULT nextval('token_token_id_seq'::regclass), + "account" varchar(32) COLLATE "pg_catalog"."default" +) +; + +-- ---------------------------- +-- Records of token +-- ---------------------------- + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."device_online_report_id_seq" +OWNED BY "public"."device_online_report"."id"; +SELECT setval('"public"."device_online_report_id_seq"', 21, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."devices_groups_id_seq" +OWNED BY "public"."devices_groups"."id"; +SELECT setval('"public"."devices_groups_id_seq"', 196, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."event_trigger_record_id_seq" +OWNED BY "public"."event_trigger_record"."id"; +SELECT setval('"public"."event_trigger_record_id_seq"', 2, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."mail_setting_id_seq" +OWNED BY "public"."mail_setting"."id"; +SELECT setval('"public"."mail_setting_id_seq"', 2, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."media_type_setting_id_seq" +OWNED BY "public"."media_type_setting"."id"; +SELECT setval('"public"."media_type_setting_id_seq"', 2, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."messages_id_seq" +OWNED BY "public"."messages"."id"; +SELECT setval('"public"."messages_id_seq"', 234, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."notice_record_record_id_seq" +OWNED BY "public"."notice_record"."record_id"; +SELECT setval('"public"."notice_record_record_id_seq"', 2, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."product_event_relation_id_seq" +OWNED BY "public"."product_event_relation"."id"; +SELECT setval('"public"."product_event_relation_id_seq"', 62, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."product_event_tags_id_seq" +OWNED BY "public"."product_event_tags"."id"; +SELECT setval('"public"."product_event_tags_id_seq"', 3, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."product_event_time_interval_event_time_id_seq" +OWNED BY "public"."product_event_time_interval"."event_time_id"; +SELECT setval('"public"."product_event_time_interval_event_time_id_seq"', 9, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."product_service_relation_id_seq" +OWNED BY "public"."product_service_relation"."id"; +SELECT setval('"public"."product_service_relation_id_seq"', 24, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."product_status_function_relation_id_seq" +OWNED BY "public"."product_status_function_relation"."id"; +SELECT setval('"public"."product_status_function_relation_id_seq"', 8, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."product_type_product_type_id_seq" +OWNED BY "public"."product_type"."id"; +SELECT setval('"public"."product_type_product_type_id_seq"', 226, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."protocol_component_protocol_component_id_seq" +OWNED BY "public"."protocol_component"."protocol_component_id"; +SELECT setval('"public"."protocol_component_protocol_component_id_seq"', 7, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."protocol_gateway_protocol_gateway_id_seq" +OWNED BY "public"."protocol_gateway"."protocol_gateway_id"; +SELECT setval('"public"."protocol_gateway_protocol_gateway_id_seq"', 9, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."protocol_service_protocol_service_id_seq" +OWNED BY "public"."protocol_service"."protocol_service_id"; +SELECT setval('"public"."protocol_service_protocol_service_id_seq"', 6, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."scenes_trigger_record_id_seq" +OWNED BY "public"."scenes_trigger_record"."id"; +SELECT setval('"public"."scenes_trigger_record_id_seq"', 3, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."service_execute_record_id_seq" +OWNED BY "public"."service_execute_record"."id"; +SELECT setval('"public"."service_execute_record_id_seq"', 2, false); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."service_id_seq" +OWNED BY "public"."product_service"."id"; +SELECT setval('"public"."service_id_seq"', 33, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."service_param_id_seq" +OWNED BY "public"."product_service_param"."id"; +SELECT setval('"public"."service_param_id_seq"', 19, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."session_id_seq" +OWNED BY "public"."session"."id"; +SELECT setval('"public"."session_id_seq"', 6, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."sys_user_group_user_group_id_seq" +OWNED BY "public"."sys_user_group"."user_group_id"; +SELECT setval('"public"."sys_user_group_user_group_id_seq"', 30, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."sys_user_user_id_seq" +OWNED BY "public"."sys_user"."user_id"; +SELECT setval('"public"."sys_user_user_id_seq"', 123, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."tag_id_seq" +OWNED BY "public"."tag"."id"; +SELECT setval('"public"."tag_id_seq"', 196, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."task_info_id_seq" +OWNED BY "public"."task_info"."id"; +SELECT setval('"public"."task_info_id_seq"', 3, true); + +-- ---------------------------- +-- Alter sequences owned by +-- ---------------------------- +ALTER SEQUENCE "public"."token_token_id_seq" +OWNED BY "public"."token"."token_id"; +SELECT setval('"public"."token_token_id_seq"', 19, true); + +-- ---------------------------- +-- Primary Key structure for table device +-- ---------------------------- +ALTER TABLE "public"."device" ADD CONSTRAINT "device_pkey" PRIMARY KEY ("device_id"); + +-- ---------------------------- +-- Primary Key structure for table device_group +-- ---------------------------- +ALTER TABLE "public"."device_group" ADD CONSTRAINT "device_group_pkey" PRIMARY KEY ("device_group_id"); + +-- ---------------------------- +-- Primary Key structure for table device_online_report +-- ---------------------------- +ALTER TABLE "public"."device_online_report" ADD CONSTRAINT "device_online_report_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table devices_groups +-- ---------------------------- +ALTER TABLE "public"."devices_groups" ADD CONSTRAINT "devices_groups_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table event_trigger_record +-- ---------------------------- +ALTER TABLE "public"."event_trigger_record" ADD CONSTRAINT "event_trigger_record_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table mail_setting +-- ---------------------------- +ALTER TABLE "public"."mail_setting" ADD CONSTRAINT "mail_setting_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table media_type_setting +-- ---------------------------- +ALTER TABLE "public"."media_type_setting" ADD CONSTRAINT "media_type_setting_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table messages +-- ---------------------------- +ALTER TABLE "public"."messages" ADD CONSTRAINT "messages_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table notice_record +-- ---------------------------- +ALTER TABLE "public"."notice_record" ADD CONSTRAINT "notice_record_pkey" PRIMARY KEY ("record_id"); + +-- ---------------------------- +-- Primary Key structure for table problem +-- ---------------------------- +ALTER TABLE "public"."problem" ADD CONSTRAINT "problem_pkey" PRIMARY KEY ("event_id"); + +-- ---------------------------- +-- Primary Key structure for table product +-- ---------------------------- +ALTER TABLE "public"."product" ADD CONSTRAINT "product_pkey" PRIMARY KEY ("product_id"); + +-- ---------------------------- +-- Primary Key structure for table product_attribute +-- ---------------------------- +ALTER TABLE "public"."product_attribute" ADD CONSTRAINT "product_attribute_pkey" PRIMARY KEY ("attr_id"); + +-- ---------------------------- +-- Primary Key structure for table product_attribute_event +-- ---------------------------- +ALTER TABLE "public"."product_attribute_event" ADD CONSTRAINT "product_attribute_copy1_pkey" PRIMARY KEY ("attr_id"); + +-- ---------------------------- +-- Primary Key structure for table product_event +-- ---------------------------- +ALTER TABLE "public"."product_event" ADD CONSTRAINT "product_event_pkey" PRIMARY KEY ("event_rule_id"); + +-- ---------------------------- +-- Primary Key structure for table product_event_expression +-- ---------------------------- +ALTER TABLE "public"."product_event_expression" ADD CONSTRAINT "product_event_copy1_pkey1" PRIMARY KEY ("event_exp_id"); + +-- ---------------------------- +-- Primary Key structure for table product_event_relation +-- ---------------------------- +ALTER TABLE "public"."product_event_relation" ADD CONSTRAINT "product_event_relation_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Indexes structure for table product_event_service +-- ---------------------------- +CREATE INDEX "eventRuleId" ON "public"."product_event_service" USING btree ( + "event_rule_id" "pg_catalog"."int8_ops" ASC NULLS LAST +); +CREATE INDEX "serviceId" ON "public"."product_event_service" USING btree ( + "service_id" "pg_catalog"."int8_ops" ASC NULLS LAST +); + +-- ---------------------------- +-- Primary Key structure for table product_event_tags +-- ---------------------------- +ALTER TABLE "public"."product_event_tags" ADD CONSTRAINT "product_event_tags_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table product_event_time_interval +-- ---------------------------- +ALTER TABLE "public"."product_event_time_interval" ADD CONSTRAINT "product_event_time_interval_pkey" PRIMARY KEY ("event_time_id"); + +-- ---------------------------- +-- Primary Key structure for table product_service +-- ---------------------------- +ALTER TABLE "public"."product_service" ADD CONSTRAINT "service_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table product_service_param +-- ---------------------------- +ALTER TABLE "public"."product_service_param" ADD CONSTRAINT "service_param_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table product_service_relation +-- ---------------------------- +ALTER TABLE "public"."product_service_relation" ADD CONSTRAINT "product_service_relation_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table product_status_function +-- ---------------------------- +ALTER TABLE "public"."product_status_function" ADD CONSTRAINT "product_status_function_pkey" PRIMARY KEY ("rule_id"); + +-- ---------------------------- +-- Primary Key structure for table product_status_function_relation +-- ---------------------------- +ALTER TABLE "public"."product_status_function_relation" ADD CONSTRAINT "product_status_function_relation_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table product_type +-- ---------------------------- +ALTER TABLE "public"."product_type" ADD CONSTRAINT "product_type_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table protocol_component +-- ---------------------------- +ALTER TABLE "public"."protocol_component" ADD CONSTRAINT "protocol_component_pkey" PRIMARY KEY ("protocol_component_id"); + +-- ---------------------------- +-- Primary Key structure for table protocol_gateway +-- ---------------------------- +ALTER TABLE "public"."protocol_gateway" ADD CONSTRAINT "protocol_gateway_pkey" PRIMARY KEY ("protocol_gateway_id"); + +-- ---------------------------- +-- Primary Key structure for table protocol_service +-- ---------------------------- +ALTER TABLE "public"."protocol_service" ADD CONSTRAINT "protocol_service_pkey" PRIMARY KEY ("protocol_service_id"); + +-- ---------------------------- +-- Primary Key structure for table proxy +-- ---------------------------- +ALTER TABLE "public"."proxy" ADD CONSTRAINT "proxy_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table scenes_trigger_record +-- ---------------------------- +ALTER TABLE "public"."scenes_trigger_record" ADD CONSTRAINT "scenes_trigger_record_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table service_execute_record +-- ---------------------------- +ALTER TABLE "public"."service_execute_record" ADD CONSTRAINT "service_execute_record_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table session +-- ---------------------------- +ALTER TABLE "public"."session" ADD CONSTRAINT "session_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table sys_config +-- ---------------------------- +ALTER TABLE "public"."sys_config" ADD CONSTRAINT "sys_config_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table sys_dict +-- ---------------------------- +ALTER TABLE "public"."sys_dict" ADD CONSTRAINT "sys_dict_pkey" PRIMARY KEY ("dict_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_dict_type +-- ---------------------------- +ALTER TABLE "public"."sys_dict_type" ADD CONSTRAINT "sys_dict_type_pkey" PRIMARY KEY ("dict_type_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_login_log +-- ---------------------------- +ALTER TABLE "public"."sys_login_log" ADD CONSTRAINT "sys_login_log_pkey" PRIMARY KEY ("login_log_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_menu +-- ---------------------------- +ALTER TABLE "public"."sys_menu" ADD CONSTRAINT "sys_menu_pkey" PRIMARY KEY ("menu_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_operation_log +-- ---------------------------- +ALTER TABLE "public"."sys_operation_log" ADD CONSTRAINT "sys_operation_log_pkey" PRIMARY KEY ("operation_log_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_role +-- ---------------------------- +ALTER TABLE "public"."sys_role" ADD CONSTRAINT "sys_role_pkey" PRIMARY KEY ("role_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_user +-- ---------------------------- +ALTER TABLE "public"."sys_user" ADD CONSTRAINT "sys_user_pkey" PRIMARY KEY ("user_id"); + +-- ---------------------------- +-- Primary Key structure for table sys_user_group +-- ---------------------------- +ALTER TABLE "public"."sys_user_group" ADD CONSTRAINT "sys_user_group_pkey" PRIMARY KEY ("user_group_id"); + +-- ---------------------------- +-- Primary Key structure for table tag +-- ---------------------------- +ALTER TABLE "public"."tag" ADD CONSTRAINT "tag_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table task_info +-- ---------------------------- +ALTER TABLE "public"."task_info" ADD CONSTRAINT "task_info_pkey" PRIMARY KEY ("id"); + +-- ---------------------------- +-- Primary Key structure for table tenant_info +-- ---------------------------- +ALTER TABLE "public"."tenant_info" ADD CONSTRAINT "tenant_pkey" PRIMARY KEY ("tenant_id"); + +-- ---------------------------- +-- Primary Key structure for table token +-- ---------------------------- +ALTER TABLE "public"."token" ADD CONSTRAINT "token_pkey" PRIMARY KEY ("token_id"); diff --git a/dist-material/bin/startup.bat b/dist-material/bin/startup.bat new file mode 100644 index 00000000..611631e0 --- /dev/null +++ b/dist-material/bin/startup.bat @@ -0,0 +1,22 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +@echo off + +setlocal +call "%~dp0"\IoTServer.bat start +call "%~dp0"\webappService.bat start +endlocal diff --git a/dist-material/bin/startup.sh b/dist-material/bin/startup.sh new file mode 100644 index 00000000..0ff60e71 --- /dev/null +++ b/dist-material/bin/startup.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +source /etc/profile +PRG="$0" +PRGDIR=`dirname "$PRG"` +IOT_EXE=IoTServer.sh +WEBAPP_EXE=webappService.sh + +"$PRGDIR"/"$IOT_EXE" + +"$PRGDIR"/"$WEBAPP_EXE" diff --git a/dist-material/bin/stop.sh b/dist-material/bin/stop.sh new file mode 100755 index 00000000..a8c8db0f --- /dev/null +++ b/dist-material/bin/stop.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -x + +status=`ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}' | wc -l` + +while [ $status -ne 0 ] +do + for i in `ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}'` + do + kill -9 $i + done + status=`ps -ef | grep zeus-iot-bin | grep java | grep -v grep | awk '{print $2}' | wc -l` +done \ No newline at end of file diff --git a/dist-material/bin/webappService.bat b/dist-material/bin/webappService.bat new file mode 100644 index 00000000..33879bbf --- /dev/null +++ b/dist-material/bin/webappService.bat @@ -0,0 +1,41 @@ +@REM +@REM Licensed to the Apache Software Foundation (ASF) under one or more +@REM contributor license agreements. See the NOTICE file distributed with +@REM this work for additional information regarding copyright ownership. +@REM The ASF licenses this file to You under the Apache License, Version 2.0 +@REM (the "License"); you may not use this file except in compliance with +@REM the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, software +@REM distributed under the License is distributed on an "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@REM See the License for the specific language governing permissions and +@REM limitations under the License. + +@echo off + +setlocal +set WEBAPP_PROCESS_TITLE=Zeus-Webapp +set WEBAPP_HOME=%~dp0%.. +set JARPATH=%WEBAPP_HOME%\webapp +set WEBAPP_LOG_DIR=%WEBAPP_HOME%\logs + +if not exist "%WEBAPP_LOG_DIR%" ( + mkdir "%WEBAPP_LOG_DIR%" +) + +set LOG_FILE_LOCATION=%WEBAPP_LOG_DIR%\webapp.log + +if defined JAVA_HOME ( + set _EXECJAVA="%JAVA_HOME%\bin\java" +) + +if not defined JAVA_HOME ( + echo "JAVA_HOME not set." + set _EXECJAVA=java +) + +start "%WEBAPP_PROCESS_TITLE%" %_EXECJAVA% -jar %JARPATH%/zeus-webapp.jar --spring.config.location=%JARPATH%/webapp.yml --logging.file=%LOG_FILE_LOCATION% +endlocal diff --git a/dist-material/bin/webappService.sh b/dist-material/bin/webappService.sh new file mode 100644 index 00000000..235fd0de --- /dev/null +++ b/dist-material/bin/webappService.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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 +# +# http://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. + +PRG="$0" +PRGDIR=$(dirname "$PRG") +[ -z "$WEBAPP_HOME" ] && WEBAPP_HOME=$(cd "$PRGDIR/.." > /dev/null || exit 1; pwd) + +WEBAPP_LOG_DIR="${WEBAPP_LOG_DIR:-${WEBAPP_HOME}/logs}" +JAVA_OPTS="${JAVA_OPTS:- -Xms512M -Xmx1024M}" +JAR_PATH="${WEBAPP_HOME}/webapp" + +if [ ! -d "${WEBAPP_LOG_DIR}" ]; then + mkdir -p "${WEBAPP_LOG_DIR}" +fi + +LOG_FILE_LOCATION=${WEBAPP_LOG_DIR}/webapp.log + +_RUNJAVA=${JAVA_HOME}/bin/java +[ -z "$JAVA_HOME" ] && _RUNJAVA=java + +eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} -jar ${JAR_PATH}/zeus-webapp.jar \ + --spring.config.location=${JAR_PATH}/webapp.yml \ + --logging.file=${LOG_FILE_LOCATION} \ + &> ${WEBAPP_LOG_DIR}/webapp-console.log &" + +if [ $? -eq 0 ]; then + sleep 1 + echo "Zeus Web Application started successfully!" +else + echo "Zeus Web Application started failure!" + exit 1 +fi diff --git a/dist-material/log4j2.xml b/dist-material/log4j2.xml new file mode 100644 index 00000000..094421a4 --- /dev/null +++ b/dist-material/log4j2.xml @@ -0,0 +1,44 @@ + + + + + + ${sys:iot.logDir} + + + + + %d - %c - %L [%t] %-5p %x - %m%n + + + + + + + + + + + + + + + + + diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml new file mode 100644 index 00000000..740e9b7a --- /dev/null +++ b/docker/docker-compose.yaml @@ -0,0 +1,237 @@ +version: '3.5' +services: + zabbix-server: + image: zabbix/zabbix-server-pgsql:alpine-5.4-latest + ports: + - "10051:10051" + volumes: + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + - ./zbx_env/usr/lib/zabbix/alertscripts:/usr/lib/zabbix/alertscripts:ro + - ./zbx_env/usr/lib/zabbix/externalscripts:/usr/lib/zabbix/externalscripts:ro + - ./zbx_env/var/lib/zabbix/export:/var/lib/zabbix/export:rw + - ./zbx_env/var/lib/zabbix/modules:/var/lib/zabbix/modules:ro + - ./zbx_env/var/lib/zabbix/enc:/var/lib/zabbix/enc:ro + - ./zbx_env/var/lib/zabbix/ssh_keys:/var/lib/zabbix/ssh_keys:ro + - ./zbx_env/var/lib/zabbix/mibs:/var/lib/zabbix/mibs:ro + - ./zbx_env/var/lib/zabbix/snmptraps:/var/lib/zabbix/snmptraps:ro + ulimits: + nproc: 65535 + nofile: + soft: 20000 + hard: 40000 + deploy: + resources: + limits: + cpus: '0.70' + memory: 1G + reservations: + cpus: '0.5' + memory: 512M + env_file: + - ./env_vars/.env_db_pgsql + - ./env_vars/.env_srv + secrets: + - POSTGRES_USER + - POSTGRES_PASSWORD + depends_on: + - postgres-server + networks: + zbx_net_backend: + aliases: + - zabbix-server + - zabbix-server-pgsql + - zabbix-server-alpine-pgsql + - zabbix-server-pgsql-alpine + zbx_net_frontend: +# devices: +# - "/dev/ttyUSB0:/dev/ttyUSB0" + stop_grace_period: 30s + sysctls: + - net.ipv4.ip_local_port_range=1024 65000 + - net.ipv4.conf.all.accept_redirects=0 + - net.ipv4.conf.all.secure_redirects=0 + - net.ipv4.conf.all.send_redirects=0 + labels: + com.zabbix.description: "Zabbix server with PostgreSQL database support" + com.zabbix.company: "Zabbix LLC" + com.zabbix.component: "zabbix-server" + com.zabbix.dbtype: "pgsql" + com.zabbix.os: "alpine" + + + zabbix-web-nginx-pgsql: + image: zabbix/zabbix-web-nginx-pgsql:alpine-5.4-latest + ports: + - "80:8080" + - "443:8443" + volumes: + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + - ./zbx_env/etc/ssl/nginx:/etc/ssl/nginx:ro + - ./zbx_env/usr/share/zabbix/modules/:/usr/share/zabbix/modules/:ro +# - ./env_vars/.ZBX_DB_CA_FILE:/run/secrets/root-ca.pem:ro +# - ./env_vars/.ZBX_DB_CERT_FILE:/run/secrets/client-cert.pem:ro +# - ./env_vars/.ZBX_DB_KEY_FILE:/run/secrets/client-key.pem:ro + deploy: + resources: + limits: + cpus: '0.70' + memory: 512M + reservations: + cpus: '0.5' + memory: 256M + env_file: + - ./env_vars/.env_db_pgsql + - ./env_vars/.env_web + secrets: + - POSTGRES_USER + - POSTGRES_PASSWORD + depends_on: + - postgres-server + - zabbix-server + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/"] + interval: 10s + timeout: 5s + retries: 3 + start_period: 30s + networks: + zbx_net_backend: + aliases: + - zabbix-web-nginx-pgsql + - zabbix-web-nginx-alpine-pgsql + - zabbix-web-nginx-pgsql-alpine + zbx_net_frontend: + stop_grace_period: 10s + sysctls: + - net.core.somaxconn=65535 + labels: + com.zabbix.description: "Zabbix frontend on Nginx web-server with PostgreSQL database support" + com.zabbix.company: "Zabbix LLC" + com.zabbix.component: "zabbix-frontend" + com.zabbix.webserver: "nginx" + com.zabbix.dbtype: "pgsql" + com.zabbix.os: "alpine" + + zabbix-agent: + image: zabbix/zabbix-agent:alpine-5.4-latest + ports: + - "10050:10050" + volumes: + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + - ./zbx_env/etc/zabbix/zabbix_agentd.d:/etc/zabbix/zabbix_agentd.d:ro + - ./zbx_env/var/lib/zabbix/modules:/var/lib/zabbix/modules:ro + - ./zbx_env/var/lib/zabbix/enc:/var/lib/zabbix/enc:ro + - ./zbx_env/var/lib/zabbix/ssh_keys:/var/lib/zabbix/ssh_keys:ro + deploy: + resources: + limits: + cpus: '0.2' + memory: 128M + reservations: + cpus: '0.1' + memory: 64M + mode: global + env_file: + - ./env_vars/.env_agent + privileged: true + pid: "host" + networks: + zbx_net_backend: + aliases: + - zabbix-agent + - zabbix-agent-passive + - zabbix-agent-alpine + stop_grace_period: 5s + labels: + com.zabbix.description: "Zabbix agent" + com.zabbix.company: "Zabbix LLC" + com.zabbix.component: "zabbix-agentd" + com.zabbix.os: "alpine" + + + postgres-server: + image: postgres:13-alpine +# command: -c ssl=on -c ssl_cert_file=/run/secrets/server-cert.pem -c ssl_key_file=/run/secrets/server-key.pem -c ssl_ca_file=/run/secrets/root-ca.pem + volumes: + - ./zbx_env/var/lib/postgresql/data:/var/lib/postgresql/data:rw + - ./env_vars/.ZBX_DB_CA_FILE:/run/secrets/root-ca.pem:ro + - ./env_vars/.ZBX_DB_CERT_FILE:/run/secrets/server-cert.pem:ro + - ./env_vars/.ZBX_DB_KEY_FILE:/run/secrets/server-key.pem:ro + env_file: + - ./env_vars/.env_pg_db + secrets: + - POSTGRES_USER + - POSTGRES_PASSWORD + stop_grace_period: 1m + networks: + zbx_net_backend: + aliases: + - postgres-server + - pgsql-server + - pgsql-database + + + zeus-iot-server: + build: . + ports: + - "9090:9090" + - "9080:9080" + - "12800:12800" + - "12900:12900" + env_file: + - ./env_vars/.env_zeus_iot + - ./env_vars/.env_pg_db + stop_grace_period: 1m + depends_on: + - postgres-server + - zabbix-server + - zabbix-web-nginx-pgsql + networks: + zeus_net: + aliases: + - zeus-iot-server + - zeus-iot-web + zbx_net_frontend: + zbx_net_backend: + db_data_pgsql: + image: busybox + volumes: + - ./zbx_env/var/lib/postgresql/data:/var/lib/postgresql/data:rw + + +networks: + zbx_net_frontend: + driver: bridge + driver_opts: + com.docker.network.enable_ipv6: "false" + ipam: + driver: default + config: + - subnet: 172.16.238.0/24 + zbx_net_backend: + driver: bridge + driver_opts: + com.docker.network.enable_ipv6: "false" + internal: true + ipam: + driver: default + config: + - subnet: 172.16.239.0/24 + zeus_net: + driver: bridge + driver_opts: + com.docker.network.enable_ipv6: "false" + internal: true + ipam: + driver: default + config: + - subnet: 172.16.240.0/24 + +secrets: + POSTGRES_USER: + file: ./env_vars/.POSTGRES_USER + POSTGRES_PASSWORD: + file: ./env_vars/.POSTGRES_PASSWORD diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh new file mode 100755 index 00000000..e7a84abb --- /dev/null +++ b/docker/docker-entrypoint.sh @@ -0,0 +1,342 @@ +#!/bin/bash + +set -o pipefail + +set +e +set -x +# Script trace mode +if [ "${DEBUG_MODE,,}" == "true" ]; then + set -o xtrace +fi + +# usage: file_env VAR [DEFAULT] +# as example: file_env 'MYSQL_PASSWORD' 'zabbix' +# (will allow for "$MYSQL_PASSWORD_FILE" to fill in the value of "$MYSQL_PASSWORD" from a file) +# unsets the VAR_FILE afterwards and just leaving VAR +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local defaultValue="${2:-}" + + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo "**** Both variables $var and $fileVar are set (but are exclusive)" + exit 1 + fi + + local val="$defaultValue" + + if [ "${!var:-}" ]; then + val="${!var}" + echo "** Using ${var} variable from ENV" + elif [ "${!fileVar:-}" ]; then + if [ ! -f "${!fileVar}" ]; then + echo "**** Secret file \"${!fileVar}\" is not found" + exit 1 + fi + val="$(< "${!fileVar}")" + echo "** Using ${var} variable from secret file" + fi + export "$var"="$val" + unset "$fileVar" +} + +escape_spec_char() { + local var_value=$1 + + var_value="${var_value//\\/\\\\}" + var_value="${var_value//[$'\n']/}" + var_value="${var_value//\//\\/}" + var_value="${var_value//./\\.}" + var_value="${var_value//\*/\\*}" + var_value="${var_value//^/\\^}" + var_value="${var_value//\$/\\\$}" + var_value="${var_value//\&/\\\&}" + var_value="${var_value//\[/\\[}" + var_value="${var_value//\]/\\]}" + + echo "$var_value" +} + + + +# Check prerequisites for PostgreSQL database +check_variables_postgresql() { + file_env POSTGRES_USER + file_env POSTGRES_PASSWORD + + : ${DB_SERVER_HOST:="postgres-server"} + : ${DB_SERVER_PORT:="5432"} + + DB_SERVER_ROOT_USER=${POSTGRES_USER:-"postgres"} + DB_SERVER_ROOT_PASS=${POSTGRES_PASSWORD:-""} + + DB_SERVER_ZEUS_USER=${POSTGRES_USER:-"postgres"} + DB_SERVER_ZEUS_PASS=${POSTGRES_PASSWORD:-"postgres"} + + : ${DB_SERVER_SCHEMA:="public"} + + DB_SERVER_DBNAME=${POSTGRES_DB:-"zeus-iot"} + + : ${POSTGRES_USE_IMPLICIT_SEARCH_PATH:="false"} +} + +check_db_connect_postgresql() { + echo "********************" + echo "* DB_SERVER_HOST: ${DB_SERVER_HOST}" + echo "* DB_SERVER_PORT: ${DB_SERVER_PORT}" + echo "* DB_SERVER_DBNAME: ${DB_SERVER_DBNAME}" + echo "* DB_SERVER_SCHEMA: ${DB_SERVER_SCHEMA}" + if [ "${DEBUG_MODE,,}" == "true" ]; then + echo "* DB_SERVER_ZEUS_USER: ${DB_SERVER_ZEUS_USER}" + echo "* DB_SERVER_ZEUS_PASS: ${DB_SERVER_ZEUS_PASS}" + fi + echo "********************" + + if [ -n "${DB_SERVER_ZEUS_PASS}" ]; then + export PGPASSWORD="${DB_SERVER_ZEUS_PASS}" + fi + + WAIT_TIMEOUT=5 + + if [ "${POSTGRES_USE_IMPLICIT_SEARCH_PATH,,}" == "false" ] && [ -n "${DB_SERVER_SCHEMA}" ]; then + PGOPTIONS="--search_path=${DB_SERVER_SCHEMA}" + export PGOPTIONS + fi + + if [ -n "${ZEUS_DBTLSCONNECT}" ]; then + export PGSSLMODE=${ZEUS_DBTLSCONNECT//_/-} + export PGSSLROOTCERT=${ZEUS_DBTLSCAFILE} + export PGSSLCERT=${ZEUS_DBTLSCERTFILE} + export PGSSLKEY=${ZEUS_DBTLSKEYFILE} + fi + + while true : + do + psql --host ${DB_SERVER_HOST} --port ${DB_SERVER_PORT} --username ${DB_SERVER_ROOT_USER} --list --quiet 1>/dev/null 2>&1 && break + psql --host ${DB_SERVER_HOST} --port ${DB_SERVER_PORT} --username ${DB_SERVER_ROOT_USER} --list --dbname ${DB_SERVER_DBNAME} --quiet 1>/dev/null 2>&1 && break + + echo "**** PostgreSQL server is not available. Waiting $WAIT_TIMEOUT seconds..." + sleep $WAIT_TIMEOUT + done + + unset PGPASSWORD + unset PGOPTIONS + unset PGSSLMODE + unset PGSSLROOTCERT + unset PGSSLCERT + unset PGSSLKEY +} + +psql_query() { + query=$1 + db=$2 + + local result="" + + if [ -n "${DB_SERVER_ZEUS_PASS}" ]; then + export PGPASSWORD="${DB_SERVER_ZEUS_PASS}" + fi + + if [ "${POSTGRES_USE_IMPLICIT_SEARCH_PATH,,}" == "false" ] && [ -n "${DB_SERVER_SCHEMA}" ]; then + PGOPTIONS="--search_path=${DB_SERVER_SCHEMA}" + export PGOPTIONS + fi + + if [ -n "${ZBX_DBTLSCONNECT}" ]; then + export PGSSLMODE=${ZBX_DBTLSCONNECT//_/-} + export PGSSLROOTCERT=${ZBX_DBTLSCAFILE} + export PGSSLCERT=${ZBX_DBTLSCERTFILE} + export PGSSLKEY=${ZBX_DBTLSKEYFILE} + fi + + result=$(psql --no-align --quiet --tuples-only --host "${DB_SERVER_HOST}" --port "${DB_SERVER_PORT}" \ + --username "${DB_SERVER_ROOT_USER}" --command "$query" --dbname "$db" 2>/dev/null); + + unset PGPASSWORD + unset PGOPTIONS + unset PGSSLMODE + unset PGSSLROOTCERT + unset PGSSLCERT + unset PGSSLKEY + + echo $result +} + +create_db_database_postgresql() { + DB_EXISTS=$(psql_query "SELECT 1 AS result FROM pg_database WHERE datname='${DB_SERVER_DBNAME}'" "${DB_SERVER_DBNAME}") + + if [ -z ${DB_EXISTS} ]; then + echo "** Database '${DB_SERVER_DBNAME}' does not exist. Creating..." + + if [ -n "${DB_SERVER_ZEUS_PASS}" ]; then + export PGPASSWORD="${DB_SERVER_ZEUS_PASS}" + fi + + if [ "${POSTGRES_USE_IMPLICIT_SEARCH_PATH,,}" == "false" ] && [ -n "${DB_SERVER_SCHEMA}" ]; then + PGOPTIONS="--search_path=${DB_SERVER_SCHEMA}" + export PGOPTIONS + fi + + if [ -n "${ZBX_DBTLSCONNECT}" ]; then + export PGSSLMODE=${ZBX_DBTLSCONNECT//_/-} + export PGSSLROOTCERT=${ZBX_DBTLSCAFILE} + export PGSSLCERT=${ZBX_DBTLSCERTFILE} + export PGSSLKEY=${ZBX_DBTLSKEYFILE} + fi + + createdb --host "${DB_SERVER_HOST}" --port "${DB_SERVER_PORT}" --username "${DB_SERVER_ROOT_USER}" \ + --owner "${DB_SERVER_ZEUS_USER}" "${DB_SERVER_DBNAME}" + + unset PGPASSWORD + unset PGOPTIONS + unset PGSSLMODE + unset PGSSLROOTCERT + unset PGSSLCERT + unset PGSSLKEY + else + echo "** Database '${DB_SERVER_DBNAME}' already exists. Please be careful with database owner!" + fi + + psql_query "CREATE SCHEMA IF NOT EXISTS ${DB_SERVER_SCHEMA}" "${DB_SERVER_DBNAME}" 1>/dev/null +} + +create_db_schema_postgresql() { + ZEUS_TABLE_EXISTS=$(psql_query "SELECT 1 FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = + c.relnamespace WHERE n.nspname = '$DB_SERVER_SCHEMA' AND c.relname = 'tag'" "${DB_SERVER_DBNAME}") + +# if [ -n "${DBVERSION_TABLE_EXISTS}" ]; then +# echo "** Table '${DB_SERVER_DBNAME}.dbversion' already exists." +# ZEUS_DB_VERSION=$(psql_query "SELECT mandatory FROM ${DB_SERVER_SCHEMA}.dbversion" "${DB_SERVER_DBNAME}") +# fi + + if [ -z "${ZEUS_TABLE_EXISTS}" ]; then + echo "** Creating '${DB_SERVER_DBNAME}' schema in PostgreSQL" + + + if [ -n "${DB_SERVER_ZEUS_PASS}" ]; then + export PGPASSWORD="${DB_SERVER_ZEUS_PASS}" + fi + + if [ "${POSTGRES_USE_IMPLICIT_SEARCH_PATH,,}" == "false" ] && [ -n "${DB_SERVER_SCHEMA}" ]; then + PGOPTIONS="--search_path=${DB_SERVER_SCHEMA}" + export PGOPTIONS + fi + + if [ -n "${ZBX_DBTLSCONNECT}" ]; then + export PGSSLMODE=${ZBX_DBTLSCONNECT//_/-} + export PGSSLROOTCERT=${ZBX_DBTLSCAFILE} + export PGSSLCERT=${ZBX_DBTLSCERTFILE} + export PGSSLKEY=${ZBX_DBTLSKEYFILE} + fi + + cat /zeus-iot-bin/bin/sql/zeus-iot.sql | psql --quiet \ + --host "${DB_SERVER_HOST}" --port "${DB_SERVER_PORT}" \ + --username "${DB_SERVER_ZEUS_USER}" --dbname "${DB_SERVER_DBNAME}" 1>/dev/null || exit 1 + + unset PGPASSWORD + unset PGOPTIONS + unset PGSSLMODE + unset PGSSLROOTCERT + unset PGSSLCERT + unset PGSSLKEY + fi +} + + +# Get zabbix api token + +get_zbx_apitoken() { + + WAIT_TIMEOUT=5 + + ZBX_API_URL="http://${ZEUS_ZABBIX_HOST}:${ZEUS_ZABBIX_PORT}/api_jsonrpc.php" + + data='{"jsonrpc": "2.0","method": "user.login","params":{"user":"Admin","password":"zabbix"},"id":1,"auth":null}' + + # Check zbx ui is ok + + while true : + do + + res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $ZBX_API_URL"` + + if auth=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"])' 2> /dev/null`;then + break + fi + echo "**** zabbix-web-nginx-pgsql is not available. Waiting $WAIT_TIMEOUT seconds..." + sleep $WAIT_TIMEOUT + done + + + # Check token + data='{"jsonrpc": "2.0","method": "token.get","params":{"output": ["tokenid"], "filter": {"name": "zeus"}},"id":1,"auth":"'${auth}'"}' + res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $ZBX_API_URL"` + if ! tokenid=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"][0]["tokenid"])' 2> /dev/null`;then + data='{"jsonrpc": "2.0","method": "token.create","params":{"name":"zeus","userid":"1"},"id":1,"auth":"'${auth}'"}' + res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $ZBX_API_URL"` + tokenid=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"]["tokenids"][0])'` + fi + + # Get API token + data='{"jsonrpc": "2.0","method": "token.generate","params":["'${tokenid}'"],"id":1,"auth":"'${auth}'"}' + res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $ZBX_API_URL"` + token=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"][0]["token"])'` + export ZBXAPITOKEN=$token + +} + + + +prepare_server() { + echo "** Preparing Zeus IoT Server" + + check_variables_postgresql + check_db_connect_postgresql + create_db_database_postgresql + create_db_schema_postgresql + get_zbx_apitoken + +} + +################################################# +startiot() { + + [ -z "$IOT_HOME" ] && IOT_HOME=/zeus-iot-bin + JAVA_OPTS="${JAVA_OPTS:- -Xms256M -Xmx512M}" + _RUNJAVA=${JAVA_HOME}/bin/java + [ -z "$JAVA_HOME" ] && _RUNJAVA=java + + CLASSPATH="$IOT_HOME/config" + for i in "$IOT_HOME"/iot-server-libs/*.jar + do + CLASSPATH="$i:$CLASSPATH" + done + + IOT_OPTIONS=" -Duser.timezone=GMT+08" + + eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${IOT_OPTIONS} -classpath $CLASSPATH com.zmops.zeus.iot.server.starter.IoTServerStartUp &> /dev/stdout &" +} + +startwebapp() { + + [ -z "$WEBAPP_HOME" ] && WEBAPP_HOME=/zeus-iot-bin + + JAVA_OPTS="${JAVA_OPTS:- -Xms512M -Xmx1024M}" + JAR_PATH="${WEBAPP_HOME}/webapp" + + _RUNJAVA=${JAVA_HOME}/bin/java + [ -z "$JAVA_HOME" ] && _RUNJAVA=java + + sed -i "s%\(zbxApiToken: \).*%\1${ZBXAPITOKEN}%g" ${JAR_PATH}/webapp.yml + + eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} -jar ${JAR_PATH}/zeus-webapp.jar \ + --spring.config.location=${JAR_PATH}/webapp.yml" + +} + + +prepare_server +startiot +startwebapp + +################################################# diff --git a/docker/dockerfile b/docker/dockerfile new file mode 100644 index 00000000..5d17aec1 --- /dev/null +++ b/docker/dockerfile @@ -0,0 +1,18 @@ +FROM alpine:latest + +RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories + +RUN apk update \ + && apk add --no-cache tzdata curl python2 openjdk8-jre bash postgresql-client \ + && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ + && echo Asia/Shanghai > /etc/timezone \ + && rm -rf /var/cache/apk/* + +ADD https://xxxxx/zeus-iot/zeus-iot-bin.tar.gz / +RUN tar -xf zeus-iot-bin.tar.gz +COPY log4j2.xml /zeus-iot-bin/config/log4j2.xml +COPY docker-entrypoint.sh /usr/bin/docker-entrypoint.sh +EXPOSE 9090 +ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"] + + diff --git a/docker/env_vars/.POSTGRES_PASSWORD b/docker/env_vars/.POSTGRES_PASSWORD new file mode 100644 index 00000000..f1349944 --- /dev/null +++ b/docker/env_vars/.POSTGRES_PASSWORD @@ -0,0 +1 @@ +postgres diff --git a/docker/env_vars/.POSTGRES_USER b/docker/env_vars/.POSTGRES_USER new file mode 100644 index 00000000..f1349944 --- /dev/null +++ b/docker/env_vars/.POSTGRES_USER @@ -0,0 +1 @@ +postgres diff --git a/docker/env_vars/.env_agent b/docker/env_vars/.env_agent new file mode 100644 index 00000000..a2f9be2a --- /dev/null +++ b/docker/env_vars/.env_agent @@ -0,0 +1,37 @@ +# ZBX_SOURCEIP= +# ZBX_DEBUGLEVEL=3 +# ZBX_ENABLEREMOTECOMMANDS=0 # Deprecated since 5.0.0 +# ZBX_LOGREMOTECOMMANDS=0 +# ZBX_HOSTINTERFACE= # Available since 4.4.0 +# ZBX_HOSTINTERFACEITEM= # Available since 4.4.0 +# ZBX_SERVER_HOST=zabbix-server +# ZBX_PASSIVE_ALLOW=true +# ZBX_PASSIVESERVERS= +# ZBX_ACTIVE_ALLOW=true +# ZBX_ACTIVESERVERS= +# ZBX_LISTENIP= +# ZBX_STARTAGENTS=3 +# ZBX_HOSTNAME= +# ZBX_HOSTNAMEITEM=system.hostname +# ZBX_METADATA= +# ZBX_METADATAITEM= +# ZBX_REFRESHACTIVECHECKS=120 +# ZBX_BUFFERSEND=5 +# ZBX_BUFFERSIZE=100 +# ZBX_MAXLINESPERSECOND=20 +# ZBX_ALIAS="" +# ZBX_TIMEOUT=3 +# ZBX_UNSAFEUSERPARAMETERS=0 +# ZBX_LOADMODULE="dummy1.so,dummy2.so,dummy10.so" +# ZBX_TLSCONNECT=unencrypted +# ZBX_TLSACCEPT=unencrypted +# ZBX_TLSCAFILE= +# ZBX_TLSCRLFILE= +# ZBX_TLSSERVERCERTISSUER= +# ZBX_TLSSERVERCERTSUBJECT= +# ZBX_TLSCERTFILE= +# ZBX_TLSKEYFILE= +# ZBX_TLSPSKIDENTITY= +# ZBX_TLSPSKFILE= +# ZBX_DENYKEY=system.run[*] +# ZBX_ALLOWKEY= diff --git a/docker/env_vars/.env_db_pgsql b/docker/env_vars/.env_db_pgsql new file mode 100644 index 00000000..30be4ad2 --- /dev/null +++ b/docker/env_vars/.env_db_pgsql @@ -0,0 +1,11 @@ +# DB_SERVER_HOST=postgres-server +# DB_SERVER_PORT=5432 +# POSTGRES_USER=zabbix +POSTGRES_USER_FILE=/run/secrets/POSTGRES_USER +# POSTGRES_PASSWORD=zabbix +POSTGRES_PASSWORD_FILE=/run/secrets/POSTGRES_PASSWORD +# POSTGRES_DB=zabbix +POSTGRES_DB=zabbix +# DB_SERVER_SCHEMA=public +# ENABLE_TIMESCALEDB=true +# POSTGRES_USE_IMPLICIT_SEARCH_PATH=false diff --git a/docker/env_vars/.env_pg_db b/docker/env_vars/.env_pg_db new file mode 100644 index 00000000..e1d285ef --- /dev/null +++ b/docker/env_vars/.env_pg_db @@ -0,0 +1,10 @@ +# DB_SERVER_HOST=postgres-server +# DB_SERVER_PORT=5432 +POSTGRES_USER=postgres +# POSTGRES_USER_FILE=/run/secrets/POSTGRES_USER +POSTGRES_PASSWORD=postgres +# POSTGRES_PASSWORD_FILE=/run/secrets/POSTGRES_PASSWORD +# POSTGRES_DB=zabbix +# DB_SERVER_SCHEMA=public +# ENABLE_TIMESCALEDB=true +# POSTGRES_USE_IMPLICIT_SEARCH_PATH=false diff --git a/docker/env_vars/.env_srv b/docker/env_vars/.env_srv new file mode 100644 index 00000000..35c1ce6e --- /dev/null +++ b/docker/env_vars/.env_srv @@ -0,0 +1,62 @@ +# ZBX_LISTENIP= +# ZBX_HISTORYSTORAGEURL=http://elasticsearch:9200/ # Available since 3.4.5 +# ZBX_HISTORYSTORAGETYPES=uint,dbl,str,log,text # Available since 3.4.5 +# ZBX_DBTLSCONNECT=required # Available since 5.0.0 +# ZBX_DBTLSCAFILE=/run/secrets/root-ca.pem # Available since 5.0.0 +# ZBX_DBTLSCERTFILE=/run/secrets/client-cert.pem # Available since 5.0.0 +# ZBX_DBTLSKEYFILE=/run/secrets/client-key.pem # Available since 5.0.0 +# ZBX_DBTLSCIPHER= # Available since 5.0.0 +# ZBX_DBTLSCIPHER13= # Available since 5.0.0 +# ZBX_DEBUGLEVEL=3 +# ZBX_STARTPOLLERS=5 +# ZBX_IPMIPOLLERS=0 +# ZBX_STARTPREPROCESSORS=3 # Available since 3.4.0 +# ZBX_STARTPOLLERSUNREACHABLE=1 +# ZBX_STARTTRAPPERS=5 +# ZBX_STARTPINGERS=1 +# ZBX_STARTDISCOVERERS=1 +# ZBX_STARTHTTPPOLLERS=1 +# ZBX_STARTTIMERS=1 +# ZBX_STARTESCALATORS=1 +# ZBX_STARTALERTERS=3 # Available since 3.4.0 +ZBX_JAVAGATEWAY_ENABLE=true +# ZBX_JAVAGATEWAY=zabbix-java-gateway +# ZBX_JAVAGATEWAYPORT=10052 +ZBX_STARTJAVAPOLLERS=5 +# ZBX_STARTVMWARECOLLECTORS=0 +# ZBX_VMWAREFREQUENCY=60 +# ZBX_VMWAREPERFFREQUENCY=60 +# ZBX_VMWARECACHESIZE=8M +# ZBX_VMWARETIMEOUT=10 +ZBX_ENABLE_SNMP_TRAPS=true +# ZBX_SOURCEIP= +# ZBX_HOUSEKEEPINGFREQUENCY=1 +# ZBX_MAXHOUSEKEEPERDELETE=5000 +# ZBX_SENDERFREQUENCY=30 +# ZBX_CACHESIZE=8M +# ZBX_CACHEUPDATEFREQUENCY=60 +# ZBX_STARTDBSYNCERS=4 +# ZBX_HISTORYCACHESIZE=16M +# ZBX_HISTORYINDEXCACHESIZE=4M +# ZBX_TRENDCACHESIZE=4M +# ZBX_VALUECACHESIZE=8M +# ZBX_TIMEOUT=4 +# ZBX_TRAPPERTIMEOUT=300 +# ZBX_UNREACHABLEPERIOD=45 +# ZBX_UNAVAILABLEDELAY=60 +# ZBX_UNREACHABLEDELAY=15 +# ZBX_LOGSLOWQUERIES=3000 +# ZBX_EXPORTFILESIZE= +# ZBX_STARTPROXYPOLLERS=1 +# ZBX_PROXYCONFIGFREQUENCY=3600 +# ZBX_PROXYDATAFREQUENCY=1 +# ZBX_LOADMODULE="dummy1.so,dummy2.so,dummy10.so" +# ZBX_TLSCAFILE= +# ZBX_TLSCRLFILE= +# ZBX_TLSCERTFILE= +# ZBX_TLSKEYFILE= +# ZBX_VAULTDBPATH= +# ZBX_VAULTURL=https://127.0.0.1:8200 +# VAULT_TOKEN= +# ZBX_STARTREPORTWRITERS=0 +# ZBX_WEBSERVICEURL=http://zabbix-web-service:10053/report diff --git a/docker/env_vars/.env_web b/docker/env_vars/.env_web new file mode 100644 index 00000000..ae96d1ad --- /dev/null +++ b/docker/env_vars/.env_web @@ -0,0 +1,27 @@ +# ZBX_SERVER_HOST=zabbix-server +# ZBX_SERVER_PORT=10051 +ZBX_SERVER_NAME=Composed installation +# ZBX_DB_ENCRYPTION=true # Available since 5.0.0 +# ZBX_DB_KEY_FILE=/run/secrets/client-key.pem # Available since 5.0.0 +# ZBX_DB_CERT_FILE=/run/secrets/client-cert.pem # Available since 5.0.0 +# ZBX_DB_CA_FILE=/run/secrets/root-ca.pem # Available since 5.0.0 +# ZBX_DB_VERIFY_HOST=false # Available since 5.0.0 +# ZBX_DB_CIPHER_LIST= # Available since 5.0.0 +# ZBX_VAULTDBPATH= +# ZBX_VAULTURL=https://127.0.0.1:8200 +# VAULT_TOKEN= +# ZBX_HISTORYSTORAGEURL=http://elasticsearch:9200/ # Available since 3.4.5 +# ZBX_HISTORYSTORAGETYPES=['uint', 'dbl', 'str', 'text', 'log'] # Available since 3.4.5 +# ZBX_SSO_SETTINGS=[] # Available since 5.0.0 +# ENABLE_WEB_ACCESS_LOG=true +# ZBX_MAXEXECUTIONTIME=600 +# ZBX_MEMORYLIMIT=128M +# ZBX_POSTMAXSIZE=16M +# ZBX_UPLOADMAXFILESIZE=2M +# ZBX_MAXINPUTTIME=300 +# ZBX_SESSION_NAME=zbx_sessionid +# Timezone one of: http://php.net/manual/en/timezones.php +# PHP_TZ=Europe/Riga +# ZBX_DENY_GUI_ACCESS=false +# ZBX_GUI_ACCESS_IP_RANGE=['127.0.0.1'] +# ZBX_GUI_WARNING_MSG=Zabbix is under maintenance. diff --git a/docker/env_vars/.env_web_service b/docker/env_vars/.env_web_service new file mode 100644 index 00000000..1d473f10 --- /dev/null +++ b/docker/env_vars/.env_web_service @@ -0,0 +1,9 @@ +# ZBX_DEBUGLEVEL=3 +ZBX_ALLOWEDIP=zabbix-server +# ZBX_LISTENPORT=10053 +# ZBX_LISTENIP= +# ZBX_TIMEOUT=3 +# ZBX_TLSACCEPT=unencrypted +# ZBX_TLSCAFILE= +# ZBX_TLSCERTFILE= +# ZBX_TLSKEYFILE= diff --git a/docker/env_vars/.env_zeus_iot b/docker/env_vars/.env_zeus_iot new file mode 100644 index 00000000..e4251021 --- /dev/null +++ b/docker/env_vars/.env_zeus_iot @@ -0,0 +1,5 @@ +ZEUS_ZABBIX_HOST=zabbix-web-nginx-pgsql +ZEUS_ZABBIX_PORT=8080 +ZEUS_ZABBIX_API_URL=/api_jsonrpc.php +ZEUS_DB_HOST=postgres-server + diff --git a/docker/log4j2.xml b/docker/log4j2.xml new file mode 100644 index 00000000..ddb7b819 --- /dev/null +++ b/docker/log4j2.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/docs/README.md b/docs/README.md index 61dd488d..94fb7d69 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1 +1,326 @@ -### Zeus IOT Document \ No newline at end of file +[toc] + +# Zeus IoT Document + +> Zeus IoT 基于 zabbix-5.4 安装。 + +## Zeus IoT 系统安装配置要求 + +- **硬件依赖** + + 目前 Zeus IoT 支持 Linux x86_64 系统平台,其它系统平台测试中。 + + | 配置规格 | 系统平台 | CPU | 内存 | 存储 | + | -------- | ------------ | ---- | ---- | ------ | + | 最低配置 | Linux x86_64 | 2 核 | 4 GB | 100 GB | + | 推荐配置 | Linux x86_64 | 4 核 | 8 GB | 500 GB | + +- **软件依赖** + + | 操作系统 | Centos 7.0+/Redhat 7.0+/Ubuntu 18.04+ | + | -------- | ------------------------------------- | + | JDK | 1.8 | + | 数据库 | PostgreSQL 12+/InfluxDB/TDengine-2.2x | + | 数据采集 | Zabbix Server 5.4.x | + | 数据代理 | Zabbix Proxy 5.4.x | + | 可视化 | Grafana 7.x | + +## 快速安装 + +> 简化 zabbix 安装部署,方便客户快速使用 Zeus IoT 产品。 + +系统终端执行以下命令快速安装 + +- Centos7/Redhat7 + + ```shell + curl -sL https://github.com/zmops/zeus-iot/raw/develop/docs/centos/install.sh | bash -s install + ``` + +- Ubuntu 20.04 + + ```shell + curl -sL https://github.com/zmops/zeus-iot/raw/develop/docs/ubuntu/install.sh | bash -s install + ``` + +## 自定义安装 + +> 自定义安装是在本身已有 zabbix 或需要分开部署 zabbix 和 zeus-iot 服务。 + +### 安装 zabbix 服务 + +> **zabbix 安装可参照**[zabbix官网](https://www.zabbix.com/download) 。**这里就不做详细介绍**。 + +:bulb: **建议使用 PostgreSQL 数据库,因为 zeus-iot-ui 使用的是 PostgreSQL 数据库。** + + + +#### zabbix 系统优化 + +- **修改 zabbix 时区** + - 管理员用户登录 zabbix 管理界面进入 "**管理(Administrator)**" ----- "**一般()**" ----- "**Default time zone**" 选择 "(UTC+08:00) Asia/Shanghai" + - 普通用户登录 zabbix 管理界面进入 "**User settings**" ----- "**Profile**" ----- "**Time zone**" 选择 "(UTC+08:00) Asia/Shanghai" + +### 安装 zeus-iot 系统 + +#### 安装 PostgreSQL 数据库 + +- Centos/RedHat + + ```shell + # 安装 PostgreSQL 仓库源: + sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm + + # 安装 PostgreSQL: + sudo yum install -y postgresql13-server + + # 初始化数据库并启动: + sudo /usr/pgsql-13/bin/postgresql-13-setup initdb + sudo systemctl enable postgresql-13 + sudo systemctl start postgresql-13 + ``` + + +- Ubuntu + + ```shell + # 安装 PostgreSQL 仓库源: + sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' + wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - + + # 安装 PostgreSQL: + sudo apt-get update && sudo apt-get -y install postgresql + ``` + + + +#### 获取 zeus-iot 程序包 + +- 直接下载 release 包 + + ```shell + + ``` + +- 从源码编译 + + ```shell + git clone https://github.com/zmops/zeus-iot.git + cd zeus-iot && git submodule update --init --recursive + mvn clean package -U -Dmaven.test.skip=true + ``` + + 💡 编译好的安装包在 dist 目录下。文件名为 `zeus-iot-bin.tar.gz` 。部署时只需解压即可。 + +#### 初始化系统服务 + +1、 创建数据库 + +```shell +sudo -u postgres createdb -E Unicode -T template0 zeus-iot +``` + +2、 导入 SQL + +```shell +# 解压安装包,初始化 sql 在安装目录下。 +cat zeus-iot.sql | sudo -u postgres psql zeus-iot +``` + +3、 安装 JDK 驱动 + +```shell +# Centos/Redhat 安装 +yum install java-1.8.0-openjdk.x86_64 -y +# Ubuntu 安装 +apt install openjdk-8-jdk -y +``` + +#### 服务启动配置 + +> zeus-iot 主要由 zeus-iot-server 和 webapp 两个服务组成,配置文件分别是 ``./zeus-iot-bin/conf/application.yml`` 和 ``./zeus-iot-bin/webapp/webapp.yml``。 + +##### 配置 zabbix token + +1、登录 zabbix 管理界面进入 "**User settings**" ----- "**API tokens**" ----- "**Create API token**" + +2、创建名为 zeus 的 API token, 取消 "**Set expiration date and time**" 的勾选项。确定后会生成 Auth token,点击 "**Copy to clipboard**" 复制token。 + +3、配置 zeus-iot 连接 zabbix token + + vim ./zeus-iot-bin/webapp/webapp.yml + + ... + forest: + log-enabled: false + timeout: 5000 + variables: + ... + zbxServerPort: ${ZEUS_ZABBIX_PORT:80} + zbxApiToken: 4d3ed2be23a3f325d6ccaaaeab76bbdc6a559f3c608e523f9906ea923f7d61c5 # 修改此处token信息 + ... + ... + +##### 其它启动参数配置 + +- 直接修改配置文件 + + 以修改 zabbix 信息为例: + + ``` + vim ./zeus-iot-bin/webapp/webapp.yml + + forest: + log-enabled: false + timeout: 5000 + variables: + ## Zabbix API IP And ServerIp and ServerPort + zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} + zbxServerPort: ${ZEUS_ZABBIX_PORT:80} + zbxApiToken: 4d3ed2be23a3f325d6ccaaaeab76bbdc6a559f3c608e523f9906ea923f7d61c5 + taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/${ZEUS_TAOS_DB:zeus_data} + taosUser: root + taosPwd: taosdata + ``` + + + + +- 通过配置环境变量的方式修改(临时修改) + + zeus-iot 支持环境变量配置启动,可以通过 ``export ZEUS_ZABBIX_HOST=127.0.0.1`` 申明环境变量。 + +#### 启动服务 + +> zeus-iot 默认需要连接 taos 数据库,所以启动前请先[配置taos数据库](#配置 taos 数据库) + +```shell +# 启动 +./zeus-iot-bin/bin/startup.sh + +# 停止 +./zeus-iot-bin/bin/stop.sh +``` + + + + +配置 taos 数据库 +================ + +安装 taos 数据库 +---------------- + +### 获取 taos 数据库 + +> 可通过[涛思官网](https://www.taosdata.com/en/getting-started/)获取安装包 + +:bulb: zeus-iot 默认使用 **RESTful connector** 连接涛思数据库。 + +### 安装 taos 数据库 + +- **Centos/Redhat 安装** + + ```shell +rpm -ivh TDengine-server-2.2.0.2-Linux-x64.rpm + ``` + +- **Ubuntu/Debain 安装** + + ```shell + dpkg -i TDengine-server-2.2.0.2-Linux-x64.deb + ``` + +:bulb: 这里只介绍单机版涛思安装部署,安装时是以交互式安装,只需按回车。如要安装集群版涛思需要查阅 [涛思官网文档](https://www.taosdata.com/en/documentation/) + +- **启动 taos** + + ```shell +systemctl start taosd + ``` + +- **创建 zeus_data 数据库** + + ```shell + # linux 命令行登录taos + taos + + # 创建 zeus_data 数据库 + taos> create database zeus_data; + ``` + +启用 zabbix 导出功能 +--------------------- + +修改 zabbix-server.conf 配置文件,找到如下配置项: + +```bash +### Option: ExportDir +# Directory for real time export of events, history and trends in newline delimited JSON format. +# If set, enables real time export. +# +# Mandatory: no +# Default: +ExportDir=/data + +### Option: ExportFileSize +# Maximum size per export file in bytes. +# Only used for rotation if ExportDir is set. +# +# Mandatory: no +# Range: 1M-1G +# Default: +ExportFileSize=1G + +### Option: ExportType +# List of comma delimited types of real time export - allows to control export entities by their +# type (events, history, trends) individually. +# Valid only if ExportDir is set. +# +# Mandatory: no +# Default: +ExportType=history +``` + + + +- ExportDir=/data/zabbix_history 配置导出目录 +- ExportFileSize=1G 配置导出文件的大小 +- ExportType=history 配置导出的数据表 + + +创建导出的目录并重启 zabbix-server 使配置生效 + +```shell +mkdir -p /data/zabbix_history +systemctl restart zabbix-server +``` + + +修改 zeus-iot 数据库连接 +-------------------------- + +``` +# 停止 zeus-iot 服务 +./zeus-iot-bin/bin/stop.sh + +# 修改数据连接配置如下 +vim ./zeus-iot-bin/conf/application.yml + ... + # tdengine storage realtime + storage: + selector: ${ZS_STORAGE:tdengine} + tdengine: + url: ${ZS_STORAGE_TDENGINE_URL:jdbc:TAOS://127.0.0.1:6030/zeus_data} # TDEngine jdbcUrl + user: ${ZS_STORAGE_TDENGINE_USER:root} + password: ${ZS_STORAGE_TDENGINE_PASSWORD:taosdata} + ... + +``` + +## 启动 zeus-iot 服务 + +```shell + ./zeus-iot-bin/bin/startup.sh +``` + diff --git a/docs/centos/install.sh b/docs/centos/install.sh new file mode 100755 index 00000000..1bb445af --- /dev/null +++ b/docs/centos/install.sh @@ -0,0 +1,541 @@ +#!/usr/bin/env bash + + +ROOT_UID=0 +release=Centos +basename=$(pwd) +zabbixsrc=$basename/zabbix-5.0.30 +INSTALLDIR=/opt/zeus +ZABBIX_HOME=$INSTALLDIR/zabbix +PHP_CONF=/etc/opt/rh/rh-php73 +sqldir=$basename/zabbix-5.0.30/database/postgresql +PGDATA=$INSTALLDIR/pgdata +zeusurl= + +function logprint() { + if [ $? != 0 ]; then + echo -e "\033[31m Error: $1 \033[0m" + exit + fi +} + +function syscheck() { + # 安装前准备 + ## 系统环境检测 + # + + if [ "$(uname)" != Linux ]; then + echo -e "\033[31m Error: 该脚本只适用 Linux 系统 \033[0m" + exit + fi + + if [ "$UID" -ne "$ROOT_UID" ]; then + echo -e "\033[31m Error: 请使用root账户执行安装 \033[0m" + exit + fi + ### 操作系统 + if [ ! -f /etc/redhat-release ]; then + if [[ "$(cat /etc/issue)" =~ ^Ubuntu* ]]; then + release=Ubuntu + fi + fi + ### 网络 + if ! ping -c 3 mirrors.tuna.tsinghua.edu.cn &>/dev/null; then + echo -e "\033[31m Error: 无法访问外网 。。。 \033[0m" + exit + fi + + ### cpu、mem、disk + cores=$(grep 10)printf("%s\t%d\n",$7,$3/1024/1024)}' | grep -v -c "/boot") + + if [ "$cores" -lt 0 ] || [ "$memstotal" -lt 0 ] || [ "$disks" -eq 0 ]; then + echo -e "\033[31m Error: 要求系统最低配置为 CPU 2核 内存 4GB 存储空间 100G \033[0m" + exit + fi +} + +## 系统环境初始化 +function InitSystem() { + echo -e -n "\033[32mStep1: 初始化系统安装环境 .... \033[0m" + if ! hostnamectl set-hostname zeus-server; then + echo -e "\033[31m Error: 主机名修改失败\033[0m" + exit + fi + + ### 修改时区 + if ! ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; then + echo -e "\033[31m Error: 时区修改失败\033[0m" + exit 0 + fi + + ### 关闭Selinux + setenforce 0 || true + sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config + + ### 加强对抗SYN Flood的能力 + echo "net.ipv4.tcp_syncookies = 1" >>/etc/sysctl.conf + + ### linux文件打开数量限制 + ###/etc/security/limits.conf & /etc/rc.local + echo "* soft nofile 65535" >>/etc/security/limits.conf + echo "* hard nofile 65535 " >>/etc/security/limits.conf + echo "ulimit -SHn 65535" >>/etc/rc.local + + ### 添加用户 + if ! id zeus &> /dev/null; then + groupadd --system zeus || true + useradd --system -g zeus zeus || true + fi + + ### 添加安装目录 + [ ! -d $INSTALLDIR ] && mkdir -p $INSTALLDIR + echo -e "\033[32m [ OK ] \033[0m" +} + +# 开始安装 +## 配置 YUM 源 +function AddInstallRepo() { + + echo -e -n "\033[32mStep2: 配置安装 YUM 源 .... \033[0m" + ### 备份原有yum + mv /etc/yum.repos.d/* /tmp/ + ### 基础 YUM 源 + ### Postgresql && php + tee /etc/yum.repos.d/Centos-Base.repo </dev/null +[base] +name=CentOS-\$releasever - Base +baseurl=http://mirrors.tuna.tsinghua.edu.cn/centos/\$releasever/os/\$basearch/ +gpgcheck=0 + +[updates] +name=CentOS-\$releasever - Updates +baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/\$releasever/updates/\$basearch/ +gpgcheck=0 +enabled=1 + +[extras] +name=CentOS-\$releasever - Extras +baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos/\$releasever/extras/\$basearch/ +gpgcheck=0 +enabled=1 + +[epel] +name=Extra Packages for Enterprise Linux 7 - \$basearch +baseurl=https://mirrors.tuna.tsinghua.edu.cn/epel/7/\$basearch +failovermethod=priority +enabled=1 +gpgcheck=0 + +[centos-sclo-rh] +name=CentOS-7 - SCLo rh +baseurl=http://mirrors.tuna.tsinghua.edu.cn/centos/7/sclo/\$basearch/rh/ +gpgcheck=0 +enabled=1 + +[pgdg13] +name=PostgreSQL 13 for RHEL/CentOS \$releasever - \$basearch +baseurl=https://mirrors.tuna.tsinghua.edu.cn/postgresql/repos/yum/13/redhat/rhel-\$releasever-\$basearch +enabled=1 +gpgcheck=0 + +EOL + + yum clean all 1>/dev/null && yum makecache 1>/dev/null + yum -y install java-1.8.0-openjdk expect 1> /dev/null + logprint "yum源配置失败" + echo -e "\033[32m [ OK ] \033[0m" +} + +## 安装 PostgreSQL +function PGInstall() { + echo -e -n "\033[32mStep3: 安装 PostgreSQL .... \033[0m" + yum -y install postgresql13.x86_64 \ + postgresql13-devel.x86_64 \ + postgresql13-plpython3.x86_64 1>/dev/null + + logprint "yum安装postgresql失败" + + ### 创建 PostgreSQL 用户 + ### 修改启动文件 + + [ ! -d $PGDATA ] && mkdir -p $PGDATA + if ! chown postgres. $PGDATA; then + echo "修改PGDATA用户失败" + exit + fi + + startfile=/usr/lib/systemd/system/postgresql-13.service + #sed -i 's/\(^User\=\).*/\1zeus/g' $startfile + #sed -i 's/\(^Group\=\).*/\1zeus/g' $startfile + sed -i "s#\(^Environment\=PGDATA\=\).*#\1$INSTALLDIR\/pgdata#g" $startfile + systemctl daemon-reload + ### 初始化数据库 + /usr/pgsql-13/bin/postgresql-13-setup initdb 1>/dev/null + logprint "初始化PG错误" + + #echo "shared_preload_libraries = 'timescaledb'" >>/opt/zeus/pgdata/postgresql.conf + ### 启动数据库 + systemctl enable postgresql-13 &>/dev/null + systemctl start postgresql-13 + ### 修改数据库管理员密码 + cd /tmp || exit + sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER postgres WITH PASSWORD 'postgres';" 1> /dev/null + echo -e "\033[32m [ OK ] \033[0m" +} + +## 编译安装 zabbix 5.4 +function ZbxInstall() { + echo -e -n "\033[32mStep4: 编译安装 zabbix .... \033[0m" + ### 安装编译依赖 + cd "$basename" || exit + yum -y install vim \ + wget \ + gcc \ + gcc-c++ \ + net-snmp \ + net-snmp-libs \ + net-snmp-utils \ + net-snmp-devel \ + libssh2-devel \ + OpenIPMI-devel \ + libevent-devel \ + libcurl-devel \ + libxml2 \ + libxml2-devel 1>/dev/null + + ### 创建 zabbix 用户 + groupadd --system zabbix || true + useradd --system -g zabbix -d $INSTALLDIR/zabbix -s /sbin/nologin -c "Zabbix Monitoring System" zabbix || true + + wget -c https://cdn.zabbix.com/zabbix/sources/stable/5.0/zabbix-5.0.30.tar.gz -o /dev/null -O - | tar -xz + logprint "下载zabbix源码失败,请检查网络。。。" + + cd "$zabbixsrc" && ./configure --prefix=$ZABBIX_HOME \ + --enable-server \ + --enable-agent \ + --with-postgresql=/usr/pgsql-13/bin/pg_config \ + --with-net-snmp \ + --with-libcurl \ + --with-libxml2 \ + --with-openipmi \ + --with-openssl \ + --with-ssh2 1>/dev/null + logprint "zabbix编译异常" + + make install 1>/dev/null + logprint "zabbix编译异常" + ### 前端内容部署 + mv ui $ZABBIX_HOME/zabbix && chown zeus. $ZABBIX_HOME/zabbix -R + mv $ZABBIX_HOME/zabbix/conf/zabbix.conf.php.example $ZABBIX_HOME/zabbix/conf/zabbix.conf.php + sed -i "s/\($DB\['PASSWORD'\]\s*=\).*/\1 'zabbix';/g" $ZABBIX_HOME/zabbix/conf/zabbix.conf.php + sed -i "s/\($DB\['TYPE'\]\s*=\).*/\1 \'POSTGRESQL\';/g" $ZABBIX_HOME/zabbix/conf/zabbix.conf.php + echo -e "\033[32m [ OK ] \033[0m" + ### 数据初始化 + echo -e -n "\033[32mStep5: 初始化 zabbix 数据库 .... \033[0m" + cd /tmp/ || exit + sudo -u postgres createuser zabbix + sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER zabbix WITH PASSWORD 'zabbix';" 1> /dev/null + sudo -u postgres createdb -O zabbix -E Unicode -T template0 zabbix + cat $zabbixsrc/database/postgresql/schema.sql | sudo -u zabbix psql zabbix 1>/dev/null + cat $zabbixsrc/database/postgresql/images.sql | sudo -u zabbix psql zabbix 1>/dev/null + cat $zabbixsrc/database/postgresql/data.sql | sudo -u zabbix psql zabbix 1>/dev/null +# echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix &>/dev/null +# cat $zabbixsrc/database/postgresql/timescaledb.sql | sudo -u zabbix psql zabbix 1>/dev/null +# + echo -e "\033[32m [ OK ] \033[0m" + cd "$basename" || exit + ### 配置zabbix配置文件 + echo -e -n "\033[32mStep6: 启动 zabbix .... \033[0m" + sed -i 's/^# DBPassword=/DBPassword=zabbix/g' $ZABBIX_HOME/etc/zabbix_server.conf + ### 配置启动文件 + tee /usr/lib/systemd/system/zabbix-server.service </dev/null +[Unit] +Description=Zabbix Server + +After=network.target +After=postgresql-13.service + +[Service] +Environment="CONFFILE=$ZABBIX_HOME/etc/zabbix_server.conf" +EnvironmentFile=-/etc/default/zabbix-server +Type=forking +Restart=on-failure +PIDFile=/tmp/zabbix_server.pid +KillMode=control-group +ExecStart=$ZABBIX_HOME/sbin/zabbix_server -c \$CONFFILE +ExecStop=/bin/kill -SIGTERM \$MAINPID +RestartSec=10s +TimeoutSec=0 + +[Install] +WantedBy=multi-user.target +EOL + + tee /usr/lib/systemd/system/zabbix-agent.service </dev/null +[Unit] +Description=Zabbix Agent +After=network.target + +[Service] +Environment="CONFFILE=$ZABBIX_HOME/etc/zabbix_agentd.conf" +EnvironmentFile=-/etc/default/zabbix-agent +Type=forking +Restart=on-failure +PIDFile=/tmp/zabbix_agentd.pid +KillMode=control-group +ExecStart=$ZABBIX_HOME/sbin/zabbix_agentd -c \$CONFFILE +ExecStop=/bin/kill -SIGTERM \$MAINPID +RestartSec=10s +User=zabbix +Group=zabbix + +[Install] +WantedBy=multi-user.target +EOL + + systemctl daemon-reload + systemctl enable zabbix-server &> /dev/null + systemctl enable zabbix-agent &> /dev/null + systemctl start zabbix-server + systemctl start zabbix-agent + echo -e "\033[32m [ OK ] \033[0m" +} +## 安装 php +function PHPInstall() { + echo -e -n "\033[32mStep7: 安装 zabbix-web .... \033[0m" + yum -y install rh-php73.x86_64 \ + rh-php73-php-fpm.x86_64 \ + rh-php73-php-bcmath.x86_64 \ + rh-php73-php-gd.x86_64 \ + rh-php73-php-mbstring.x86_64 \ + rh-php73-php-ldap.x86_64 \ + rh-php73-php-pgsql.x86_64 1>/dev/null + + ### php配置文件修改 + sed -i 's/post_max_size = 8M/post_max_size = 16M/' $PHP_CONF/php.ini + sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 20M/' $PHP_CONF/php.ini + sed -i 's/max_execution_time = 30/max_execution_time = 300/' $PHP_CONF/php.ini + sed -i 's/max_input_time = 60/max_input_time = 300/' $PHP_CONF/php.ini + sed -i 's/; date.timezone =/date.timezone = "Asia\/Shanghai"/' $PHP_CONF/php.ini + sed -i 's/user = apache/user = zeus/g' $PHP_CONF/php-fpm.d/www.conf + sed -i 's/group = apache/group = zeus/g' $PHP_CONF/php-fpm.d/www.conf + sed -i 's/;listen.owner = nobody/listen.owner = zeus/g' $PHP_CONF/php-fpm.d/www.conf + sed -i 's/;listen.group = nobody/listen.group = zeus/g' $PHP_CONF/php-fpm.d/www.conf + sed -i 's/\(^listen =\).*/\1\/var\/run\/php-fpm.sock/g' $PHP_CONF/php-fpm.d/www.conf + chmod 777 /var/opt/rh/rh-php73/lib/php/session -R + echo -e "\033[32m [ OK ] \033[0m" +} + +function WebInstall() { + echo -e -n "\033[32mStep8: 启动 zabbix-web .... \033[0m" + ## 安装 nginx + yum -y install nginx 1>/dev/null + + + cd $INSTALLDIR + + ## 编辑 nginx 配置文件 + tee /etc/nginx/conf.d/zabbix.conf </dev/null +server { + listen 80; + + location / { + rewrite ^/(.*) http://\$host:9090/$1 permanent; + } + + location /zabbix { + alias $ZABBIX_HOME/zabbix; + index index.html index.htm index.php; + } + + location ~ ^/zabbix/.+\.php$ { + fastcgi_pass unix:/var/run/php-fpm.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $ZABBIX_HOME\$fastcgi_script_name; + include fastcgi_params; + + fastcgi_param QUERY_STRING \$query_string; + fastcgi_param REQUEST_METHOD \$request_method; + fastcgi_param CONTENT_TYPE \$content_type; + fastcgi_param CONTENT_LENGTH \$content_length; + + fastcgi_intercept_errors on; + fastcgi_ignore_client_abort off; + fastcgi_connect_timeout 60; + fastcgi_send_timeout 180; + fastcgi_read_timeout 180; + fastcgi_buffer_size 128k; + fastcgi_buffers 4 256k; + fastcgi_busy_buffers_size 256k; + fastcgi_temp_file_write_size 256k; + } +} +EOL + + ## 修改 nginx 配置用户 + sed -i 's/user nginx;/user zeus;/g' /etc/nginx/nginx.conf + systemctl enable rh-php73-php-fpm &> /dev/null + systemctl enable nginx &> /dev/null + systemctl start rh-php73-php-fpm + systemctl start nginx + echo -e "\033[32m [ OK ] \033[0m" +} + + + +function gettoken(){ + ## 获取 API 永久 token + local zabbix_api_url=http://127.0.0.1/zabbix/api_jsonrpc.php + local data='{"jsonrpc": "2.0","method": "user.login","params":{"user":"Admin","password":"zabbix"},"id":1,"auth":null}' + local res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $zabbix_api_url"` + local auth=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"])'` + local data='{"jsonrpc": "2.0","method": "token.create","params":{"name":"zeus","userid":"1"},"id":1,"auth":"'${auth}'"}' + local res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $zabbix_api_url"` + local tokenid=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"]["tokenids"][0])'` + local data='{"jsonrpc": "2.0","method": "token.generate","params":["'${tokenid}'"],"id":1,"auth":"'${auth}'"}' + local res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $zabbix_api_url"` + token=`echo $res | python -c 'import sys, json; print(json.load(sys.stdin)["result"][0]["token"])'` +} + + +function taosinstall() { + ### taos 数据安装 + echo -e -n "\033[32mStep9: 安装 taos 数据库 .... \033[0m" + expect << EOF 1> /dev/null + spawn rpm -ivh https://www.taosdata.com/assets-download/TDengine-server-2.2.0.2-Linux-x64.rpm + expect { + "*one:" { send "\n";exp_continue} + "*skip:" { send "\n" } + } +EOF + ## 启动taos + systemctl enable taosd &> /dev/null + systemctl start taosd + logprint "taos安装失败" + + echo -e "\033[32m [ OK ] \033[0m" +} + + +function ZeusInstall() { + echo -e -n "\033[32mStep11: 安装 Zeus-IoT 服务 .... \033[0m" + cd $INSTALLDIR || exit + ## 创建taos 数据库 + taos -s "create database zeus_data" 1> /dev/null + wget -c $zeusurl -o /dev/null -O - | tar -xz + logprint "zeusiot下载失败,检查网络" + gettoken + logprint "zabbix-token获取失败" + ## 数据库导入 + sudo -u postgres createdb -E Unicode -T template0 zeus-iot + logprint "数据库创建失败" + cat ./zeus-iot-bin/bin/sql/zeus-iot.sql | sudo -u postgres psql zeus-iot &>/dev/null + logprint "文件未找到" + sed -i "s%\(zbxApiToken: \).*%\1$token%" ./zeus-iot-bin/webapp/webapp.yml + ./zeus-iot-bin/bin/startup.sh 1> /dev/null + echo -e "\033[32m [ OK ] \033[0m" +} + +function clearsys() { + + + # 清理用户 + if ! id zeus; then + userdell zeus + fi + + function kill9() { + status=`ps -ef | grep $1 | grep -v grep | awk '{print $2}' | wc -l` + + if [ $status -ne 0 ] + then + for i in `ps -ef | grep $1 | grep -v grep | awk '{print $2}'` + do + kill -9 $i + done + fi + } + + # 清理应用 + ## 清理 zeus + kill9 zeus-iot-bin + + [ -d /opt/zeus/zeus-iot-bin ] && rm -rf /opt/zeus/zeus-iot-bin + + ## 清理 taos + systemctl stop taosd &> /dev/null + + kill9 taosd + + rpm -e tdengine-2.2.0.2-3.x86_64 &> /dev/null + + [ -d /usr/local/taos ] && rm -rf /usr/local/taos + + ## 清理 zabbix + systemctl stop zabbix-server zabbix-agent &> /dev/null + + kill9 zabbix_server + kill9 zabbix_agent + + [ -d /opt/zeus/zabbix ] && rm -rf /opt/zeus/zabbix + [ -f /usr/lib/systemd/system/zabbix-server.service ] && rm -rf /usr/lib/systemd/system/zabbix-server.service + [ -f /usr/lib/systemd/system/zabbix-agent.service ] && rm -rf /usr/lib/systemd/system/zabbix-agent.service + + ## 清理 postgresql 数据库 + systemctl stop postgresql-13 &> /dev/null + + kill9 postmaster + + yum remove postgresql13 -y &> /dev/null + + [ -d /opt/zeus/pgdata ] && rm -rf /opt/zeus/pgdata + [ -f /usr/lib/systemd/system/postgresql-13.service ] && rm -rf /usr/lib/systemd/system/postgresql-13.service + + ## 清理 nginx + systemctl stop nginx &> nginx + + kill9 nginx + yum remove nginx -y &> /dev/null + [ -f /usr/lib/systemd/system/nginx ] && rm -rf /usr/lib/systemd/system/nginx +} + + +function sendmsg() { + echo "zabbix 部分已安装成功,zeus iot 可以参照 www.zmops.com 官方文档自定义安装。" + echo "" + echo "zabbix server 访问地址: http:///zabbix" + echo "" + echo "登录用户名:Admin" + echo "登录密 码:zabbix" +} + +## + + +function main() { + case $1 in + install) + syscheck + InitSystem + AddInstallRepo + PGInstall + ZbxInstall + PHPInstall + WebInstall + taosinstall + ;; + clear) + clearsys + ;; + *) + echo "请输入 install|clear" + exit 1 + ;; + esac +} + +if main $1 ;then + sendmsg +fi diff --git a/docs/images/arch.gif b/docs/images/arch.gif new file mode 100644 index 00000000..26e047c7 Binary files /dev/null and b/docs/images/arch.gif differ diff --git a/docs/images/snapshot_1.jpg b/docs/images/snapshot_1.jpg new file mode 100644 index 00000000..030a22ef Binary files /dev/null and b/docs/images/snapshot_1.jpg differ diff --git a/docs/images/snapshot_2.jpg b/docs/images/snapshot_2.jpg new file mode 100644 index 00000000..9f41a22f Binary files /dev/null and b/docs/images/snapshot_2.jpg differ diff --git a/docs/images/snapshot_3.jpg b/docs/images/snapshot_3.jpg new file mode 100644 index 00000000..7eea22b9 Binary files /dev/null and b/docs/images/snapshot_3.jpg differ diff --git a/docs/images/snapshot_4.jpg b/docs/images/snapshot_4.jpg new file mode 100644 index 00000000..691ceb7e Binary files /dev/null and b/docs/images/snapshot_4.jpg differ diff --git a/docs/images/zeus-iot-logo-1.png b/docs/images/zeus-iot-logo-1.png new file mode 100644 index 00000000..b219ed98 Binary files /dev/null and b/docs/images/zeus-iot-logo-1.png differ diff --git a/docs/images/zeus-iot-logo.png b/docs/images/zeus-iot-logo.png new file mode 100644 index 00000000..5d495582 Binary files /dev/null and b/docs/images/zeus-iot-logo.png differ diff --git a/docs/quick-install.sh b/docs/quick-install.sh deleted file mode 100755 index 4b8379ae..00000000 --- a/docs/quick-install.sh +++ /dev/null @@ -1,383 +0,0 @@ -#!/usr/bin/env bash -set -e - -ROOT_UID=0 -E_NOTROOT=67 -E_BADOD=68 -release=Centos -basename=$(pwd) -zabbixsrc=$basename/zabbix-5.4.3 -ZABBIX_HOME=/opt/zeus/zabbix -PHP_CONF=/etc/opt/rh/rh-php73 -sqldir=$basename/zabbix-5.4.3/database/postgresql -PGDATA=/opt/zeus/pgdata - -function logprint() { - if [ $? != 0 ]; then - echo "$1" - exit - fi -} - -# 安装前准备 -## 系统环境检测 -if [ "$(uname)" != Linux ]; then - echo "该脚本只使用 Linux 系统" - exit $E_BADOD -fi - -if [ "$UID" -ne "$ROOT_UID" ]; then - echo "Must be root to install" - exit $E_NOTROOT -fi -### 操作系统 -if [ ! -f /etc/redhat-release ]; then - if [[ "$(cat /etc/issue)" =~ ^Ubuntu* ]]; then - release=Ubuntu - fi -fi -### 网络 -if ! ping -c 3 mirrors.aliyun.com &>/dev/null; then - echo "网络异常。。。" - exit -fi - -### cpu、mem、disk -cores=$(grep 10)printf("%s\t%d\n",$7,$3/1024/1024)}' | grep -v -c "/boot") - -if [ "$cores" -lt 0 ] || [ "$memstotal" -lt 0 ] || [ "$disks" -eq 0 ]; then - echo "要求最低配置为 CPU 2核 内存 4GB 存储空间 100G" - exit 70 -fi - -## 系统环境初始化 -echo "初始化系统环境" -if ! hostnamectl set-hostname zeus-server; then - echo "主机名修改失败" - exit -fi - -### 修改时区 -if ! ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; then - echo "时区修改失败" - exit 0 -fi - -### 关闭Selinux -setenforce 0 || true -sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config - -### 加强对抗SYN Flood的能力 -echo "net.ipv4.tcp_syncookies = 1" >>/etc/sysctl.conf - -### linux文件打开数量限制 -###/etc/security/limits.conf & /etc/rc.local -echo "* soft nofile 65535" >>/etc/security/limits.conf -echo "* hard nofile 65535 " >>/etc/security/limits.conf -echo "ulimit -SHn 65535" >>/etc/rc.local - -### 添加用户 -groupadd --system zeus || true -useradd --system -g zeus zeus || true - -### 添加安装目录 -[ ! -d /opt/zeus ] && mkdir -p /opt/zeus - -# 开始安装 -## 配置 YUM 源 -### 基础 YUM 源 -if ! curl -s -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo; then - echo "YUM 仓库配置异常,请检查网络" -fi -sed -i '/mirrors.aliyuncs.com/,/mirrors.cloud.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo -### Postgresql && timescaleDB -tee /etc/yum.repos.d/postgresql_timescaledb.repo </dev/null -[epel] -name=Extra Packages for Enterprise Linux 7 - \$basearch -baseurl=http://mirrors.aliyun.com/epel/7/\$basearch -failovermethod=priority -enabled=1 -gpgcheck=0 - -[timescale_timescaledb] -name=timescale_timescaledb -baseurl=https://packagecloud.io/timescale/timescaledb/el/$(rpm -E %{rhel})/\$basearch -gpgcheck=0 -enabled=1 - -[centos-sclo-rh] -name=CentOS-7 - SCLo rh -baseurl=https://mirrors.aliyun.com/centos/7/sclo/\$basearch/rh/ -gpgcheck=0 -enabled=1 - -[pgdg-common] -name=PostgreSQL common RPMs for RHEL/CentOS \$releasever - \$basearch -baseurl=https://download.postgresql.org/pub/repos/yum/common/redhat/rhel-\$releasever-\$basearch -enabled=1 -gpgcheck=0 - - -[pgdg13] -name=PostgreSQL 13 for RHEL/CentOS \$releasever - \$basearch -baseurl=https://download.postgresql.org/pub/repos/yum/13/redhat/rhel-\$releasever-\$basearch -enabled=1 -gpgcheck=0 - -[pgdg12] -name=PostgreSQL 12 for RHEL/CentOS \$releasever - \$basearch -baseurl=https://download.postgresql.org/pub/repos/yum/12/redhat/rhel-\$releasever-\$basearch -enabled=1 -gpgcheck=0 -EOL - -echo "配置安装 YUM 源 。。。" -yum clean all 1>/dev/null && yum makecache 1>/dev/null -logprint "yum 源配置失败详细看安装日志输出" - -## 安装 PostgreSQL - -yum -y install postgresql13.x86_64 \ - postgresql13-devel.x86_64 \ - postgresql13-plpython3.x86_64 \ - timescaledb-2-postgresql-13.x86_64 1>/dev/null - -logprint "yum 源配置失败详细看安装日志输出" - -### 创建 PostgreSQL 用户 -### 修改启动文件 -echo "安装 PG-timescaledb " -[ ! -d $PGDATA ] && mkdir -p $PGDATA -if ! chown postgres. $PGDATA; then - echo "修改PGDATA用户失败" - exit -fi - -startfile=/usr/lib/systemd/system/postgresql-13.service -#sed -i 's/\(^User\=\).*/\1zeus/g' $startfile -#sed -i 's/\(^Group\=\).*/\1zeus/g' $startfile -sed -i 's/\(^Environment\=PGDATA\=\).*/\1\/opt\/zeus\/pgdata/g' $startfile -### 初始化数据库 -echo "开始初始化 PG" -/usr/pgsql-13/bin/postgresql-13-setup initdb 1>/dev/null -logprint "初始化错误" - -echo "shared_preload_libraries = 'timescaledb'" >>/opt/zeus/pgdata/postgresql.conf -### 启动数据库 -systemctl enable postgresql-13 &>/dev/null -systemctl start postgresql-13 -### 修改数据库管理员密码 -cd /tmp || exit -sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER postgres WITH PASSWORD 'zeusiot';" 2>/tmp/pg.log -cd "$basename" || exit - -## 编译安装 zabbix 5.4 -echo "编译 zabbix" -### 安装编译依赖 -yum -y install vim \ - wget \ - gcc \ - gcc-c++ \ - net-snmp \ - net-snmp-libs \ - net-snmp-utils \ - net-snmp-devel \ - libssh2-devel \ - OpenIPMI-devel \ - libevent-devel \ - libcurl-devel \ - libxml2 \ - libxml2-devel 1>/dev/null - -### 创建 zabbix 用户 -groupadd --system zabbix || true -useradd --system -g zabbix -d /opt/zeus/zabbix -s /sbin/nologin -c "Zabbix Monitoring System" zabbix || true - -wget -c https://cdn.zabbix.com/zabbix/sources/stable/5.4/zabbix-5.4.3.tar.gz -o /dev/null -O - | tar -xz -logprint "下载zabbix源码失败,请检查网络。。。" - -cd "$zabbixsrc" && ./configure --prefix=$ZABBIX_HOME \ - --enable-server \ - --enable-agent \ - --with-postgresql=/usr/pgsql-13/bin/pg_config \ - --with-net-snmp \ - --with-libcurl \ - --with-libxml2 \ - --with-openipmi \ - --with-openssl \ - --with-ssh2 1>/dev/null -logprint "zabbix 编译异常" -echo "安装 zabbix" -make install 1>/dev/null -logprint "zabbix 编译异常" -### 前端内容部署 -mv ui $ZABBIX_HOME/web && chown zeus. $ZABBIX_HOME/web -R -mv $ZABBIX_HOME/web/conf/zabbix.conf.php.example $ZABBIX_HOME/web/conf/zabbix.conf.php -sed -i "s/\($DB\['PASSWORD'\]\s*=\).*/\1 'zabbix';/g" $ZABBIX_HOME/web/conf/zabbix.conf.php -sed -i "s/\($DB\['TYPE'\]\s*=\).*/\1 \'POSTGRESQL\';/g" $ZABBIX_HOME/web/conf/zabbix.conf.php - -### 数据初始化 -echo "初始化 zabbix 数据库" -cd /tmp/ || exit -sudo -u postgres createuser zabbix -sudo -u postgres /usr/pgsql-13/bin/psql -c "ALTER USER zabbix WITH PASSWORD 'zabbix';" -sudo -u postgres createdb -O zabbix -E Unicode -T template0 zabbix -cat $zabbixsrc/database/postgresql/schema.sql | sudo -u zabbix psql zabbix 1>/dev/null -cat $zabbixsrc/database/postgresql/images.sql | sudo -u zabbix psql zabbix 1>/dev/null -cat $zabbixsrc/database/postgresql/data.sql | sudo -u zabbix psql zabbix 1>/dev/null -echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix &>/dev/null -cat $zabbixsrc/database/postgresql/timescaledb.sql | sudo -u zabbix psql zabbix 1>/dev/null -cd "$basename" || exit -### 配置zabbix配置文件 -echo "启动zabbix" -sed -i 's/^# DBPassword=/DBPassword=zabbix/g' $ZABBIX_HOME/etc/zabbix_server.conf -### 配置启动文件 -tee /usr/lib/systemd/system/zabbix-server.service </dev/null -[Unit] -Description=Zabbix Server - -After=network.target -After=postgresql-13.service - -[Service] -Environment="CONFFILE=$ZABBIX_HOME/etc/zabbix_server.conf" -EnvironmentFile=-/etc/default/zabbix-server -Type=forking -Restart=on-failure -PIDFile=/tmp/zabbix_server.pid -KillMode=control-group -ExecStart=$ZABBIX_HOME/sbin/zabbix_server -c \$CONFFILE -ExecStop=/bin/kill -SIGTERM \$MAINPID -RestartSec=10s -TimeoutSec=0 - -[Install] -WantedBy=multi-user.target -EOL - -tee /usr/lib/systemd/system/zabbix-agent.service </dev/null -[Unit] -Description=Zabbix Agent -After=network.target - -[Service] -Environment="CONFFILE=$ZABBIX_HOME/etc/zabbix_agentd.conf" -EnvironmentFile=-/etc/default/zabbix-agent -Type=forking -Restart=on-failure -PIDFile=/tmp/zabbix_agentd.pid -KillMode=control-group -ExecStart=$ZABBIX_HOME/sbin/zabbix_agentd -c \$CONFFILE -ExecStop=/bin/kill -SIGTERM \$MAINPID -RestartSec=10s -User=zabbix -Group=zabbix - -[Install] -WantedBy=multi-user.target -EOL - -systemctl daemon-reload -systemctl enable zabbix-server -systemctl enable zabbix-agent -systemctl start zabbix-server -systemctl start zabbix-agent - -## 安装 php -echo "安装 zabbix-web" -yum -y install rh-php73.x86_64 \ - rh-php73-php-fpm.x86_64 \ - rh-php73-php-bcmath.x86_64 \ - rh-php73-php-gd.x86_64 \ - rh-php73-php-mbstring.x86_64 \ - rh-php73-php-ldap.x86_64 \ - rh-php73-php-pgsql.x86_64 1>/dev/null - -### php配置文件修改 -sed -i 's/post_max_size = 8M/post_max_size = 16M/' $PHP_CONF/php.ini -sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 20M/' $PHP_CONF/php.ini -sed -i 's/max_execution_time = 30/max_execution_time = 300/' $PHP_CONF/php.ini -sed -i 's/max_input_time = 60/max_input_time = 300/' $PHP_CONF/php.ini -sed -i 's/; date.timezone =/date.timezone = "Asia\/Shanghai"/' $PHP_CONF/php.ini -sed -i 's/user = apache/user = zeus/g' $PHP_CONF/php-fpm.d/www.conf -sed -i 's/group = apache/group = zeus/g' $PHP_CONF/php-fpm.d/www.conf -sed -i 's/;listen.owner = nobody/listen.owner = zeus/g' $PHP_CONF/php-fpm.d/www.conf -sed -i 's/;listen.group = nobody/listen.group = zeus/g' $PHP_CONF/php-fpm.d/www.conf -sed -i 's/\(^listen =\).*/\1\/var\/run\/php-fpm.sock/g' $PHP_CONF/php-fpm.d/www.conf - -## 安装 nginx -yum -y install nginx 1>/dev/null - -## 编辑 nginx 配置文件 -tee /etc/nginx/conf.d/zabbix.conf </dev/null -server { - listen 80; -# server_name example.com; - - root $ZABBIX_HOME/web; - - index index.php; - - location = /favicon.ico { - log_not_found off; - } - - location / { - try_files \$uri \$uri/ =404; - } - - location /assets { - access_log off; - expires 10d; - } - - location ~ /\.ht { - deny all; - } - - location ~ /(api\/|conf[^\.]|include|locale|vendor) { - deny all; - return 404; - } - - location ~ [^/]\.php(/|$) { - fastcgi_pass unix:/var/run/php-fpm.sock; - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_index index.php; - - fastcgi_param DOCUMENT_ROOT $ZABBIX_HOME/web; - fastcgi_param SCRIPT_FILENAME $ZABBIX_HOME/web\$fastcgi_script_name; - fastcgi_param PATH_TRANSLATED $ZABBIX_HOME/web\$fastcgi_script_name; - - include fastcgi_params; - fastcgi_param QUERY_STRING \$query_string; - fastcgi_param REQUEST_METHOD \$request_method; - fastcgi_param CONTENT_TYPE \$content_type; - fastcgi_param CONTENT_LENGTH \$content_length; - - fastcgi_intercept_errors on; - fastcgi_ignore_client_abort off; - fastcgi_connect_timeout 60; - fastcgi_send_timeout 180; - fastcgi_read_timeout 180; - fastcgi_buffer_size 128k; - fastcgi_buffers 4 256k; - fastcgi_busy_buffers_size 256k; - fastcgi_temp_file_write_size 256k; - } -} -EOL - -## 修改 nginx 配置用户 -sed -i 's/user nginx;/user zeus;/g' /etc/nginx/nginx.conf -systemctl enable rh-php73-php-fpm -systemctl enable nginx -systemctl start rh-php73-php-fpm -systemctl start nginx - -echo "安装完成。。。请访问 "http://localIP"" - -## -# 安装结束 diff --git a/docs/quick-start.rst b/docs/quick-start.rst index 094b387c..76155834 100644 --- a/docs/quick-start.rst +++ b/docs/quick-start.rst @@ -1,2 +1,2 @@ -赶快体验自己的 Zeus-IOT -====================== \ No newline at end of file +Quickly experience Zeus-IOT +=========================== diff --git a/docs/ubuntu/install.sh b/docs/ubuntu/install.sh new file mode 100644 index 00000000..be3dd2c9 --- /dev/null +++ b/docs/ubuntu/install.sh @@ -0,0 +1,310 @@ +#!/usr/bin/env bash +set -e +# 初始化系统 + +function logprint() { + if [ $? != 0 ]; then + echo "$1" + exit + fi +} + +# 安装前准备 +## 系统环境检测 +function syscheck() { + + if [ "$(uname)" != Linux ]; then + echo "该脚本只使用 Linux 系统" + exit 1 + fi + + if [ "$UID" -ne 0 ]; then + echo "Must be root to install" + exit 1 + fi + ### 操作系统 + if [ ! -f /etc/redhat-release ]; then + if [[ "$(cat /etc/issue)" =~ ^Ubuntu* ]]; then + release=Ubuntu + fi + fi + ### 网络 + if ! ping -c 3 mirrors.tuna.tsinghua.edu.cn &>/dev/null; then + echo "网络异常。。。" + exit + fi + + ### cpu、mem、disk + cores=$(grep 10)printf("%s\t%d\n",$7,$3/1024/1024)}' | grep -v -c "/boot") + + if [ "$cores" -lt 0 ] || [ "$memstotal" -lt 0 ] || [ "$disks" -eq 0 ]; then + echo "要求最低配置为 CPU 2核 内存 4GB 存储空间 100G" + exit 70 + fi +} + + +function InitSystem() { + echo -e -n "\033[32mStep1: 初始化系统安装环境 .... \033[0m" + ## 修改主机名 + if ! hostnamectl set-hostname zeus-server; then + echo "主机名修改失败" + exit + fi + + + ## 修改时区 + if ! ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime; then + echo "时区修改失败" + exit 0 + fi + ## 更新下载源 + cp /etc/apt/sources.list /etc/apt/sources.listbak + sed -i 's%\(^deb http\{0,1\}\:\/\/\).*\(/ubuntu.*\)%\1mirrors.tuna.tsinghua.edu.cn\2%g' /etc/apt/sources.list + apt-get update 1> /dev/null && apt-get install -y ca-certificates 1> /dev/null + #sed -i 's/http/https/g' /etc/apt/sources.list + echo -e "\033[32m [ OK ] \033[0m" +} + +function AddInstallRepo() { + echo -e -n "\033[32mStep2: 配置安装 YUM 源 .... \033[0m" + ## 安装PGsql源 + echo "deb https://mirrors.tuna.tsinghua.edu.cn/postgresql/repos/apt/ $(lsb_release -c -s)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list &> /dev/null + wget --quiet -O - https://mirrors.tuna.tsinghua.edu.cn/postgresql/repos/apt/ACCC4CF8.asc | sudo apt-key add - 1> /dev/null + #sudo sh -c "echo 'deb https://packagecloud.io/timescale/timescaledb/ubuntu/ $(lsb_release -c -s) main' > /etc/apt/sources.list.d/timescaledb.list" + #wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey | sudo apt-key add - + ## 安装zabbix 5.4 源 + wget --quiet -c https://repo.zabbix.com/zabbix/5.4/ubuntu/pool/main/z/zabbix-release/zabbix-release_5.4-1+ubuntu$(lsb_release -r -s)_all.deb 1> /dev/null + dpkg -i zabbix-release_5.4-1+ubuntu$(lsb_release -r -s)_all.deb 1> /dev/null + apt-get update 1> /dev/null && apt-get install -y openjdk-8-jdk expect 1> /dev/null + echo -e "\033[32m [ OK ] \033[0m" +} + +function PGInstall() { + echo -e -n "\033[32mStep3: 安装 PostgreSQL .... \033[0m" + # PG 安装 + apt-get install postgresql-13 -y 1> /dev/null + #echo "shared_preload_libraries = 'timescaledb'" >> /etc/postgresql/13/main/postgresql.conf + cd /tmp || exit + sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD 'postgres';" 1> /dev/null + systemctl restart postgresql 1> /dev/null + echo -e "\033[32m [ OK ] \033[0m" +} + +function ZbxInstall() { + echo -e -n "\033[32mStep4: 安装 zabbix .... \033[0m" + # zabbix 安装 + apt-get install zabbix-server-pgsql zabbix-frontend-php php-pgsql zabbix-nginx-conf zabbix-sql-scripts zabbix-agent -y 1> /dev/null + + PHPCONF=/etc/php/$(ls /etc/php/)/fpm/php.ini + + # 初始化 zabbix 配置 + cd /tmp || exit + sudo -u postgres createuser zabbix + sudo -u postgres psql -c "ALTER USER zabbix WITH PASSWORD 'zabbix';" 1> /dev/null + sudo -u postgres createdb -O zabbix zabbix + zcat /usr/share/doc/zabbix-sql-scripts/postgresql/create.sql.gz | sudo -u zabbix psql zabbix 1> /dev/null + #echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix + #cat /usr/share/doc/zabbix-sql-scripts/postgresql/timescaledb.sql | sudo -u zabbix psql zabbix 1>/dev/null + + sed -i 's/^# DBPassword=/DBPassword=zabbix/g' /etc/zabbix/zabbix_server.conf + mv /usr/share/zabbix/conf/zabbix.conf.php.example /usr/share/zabbix/conf/zabbix.conf.php + sed -i "s/\($DB\['PASSWORD'\]\s*=\).*/\1 'zabbix';/g" /usr/share/zabbix/conf/zabbix.conf.php + sed -i "s/\($DB\['TYPE'\]\s*=\).*/\1 \'POSTGRESQL\';/g" /usr/share/zabbix/conf/zabbix.conf.php + # 修改 php 配置 + sed -i 's/post_max_size = 8M/post_max_size = 16M/' $PHPCONF + sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 20M/' $PHPCONF + sed -i 's/max_execution_time = 30/max_execution_time = 300/' $PHPCONF + sed -i 's/max_input_time = 60/max_input_time = 300/' $PHPCONF + sed -i 's/; date.timezone =/date.timezone = "Asia\/Shanghai"/' $PHPCONF + # 修改 nginx 配置 + sed -i '/sites-enabled/d' /etc/nginx/nginx.conf + sed -i '/listen/s/#//' /etc/nginx/conf.d/zabbix.conf + sed -i '/listen/s/80/8871/' /etc/nginx/conf.d/zabbix.conf + + # 配置 zabbix web + + tee /etc/nginx/conf.d/zeus.conf </dev/null +server { + listen 80; + + location /zabbix { + alias /usr/share/zabbix; + index index.html index.htm index.php; + } + + location ~ ^/zabbix/.+\.php$ { + fastcgi_pass unix:/var/run/php/zabbix.sock; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME /usr/share\$fastcgi_script_name; + include fastcgi_params; + + fastcgi_param QUERY_STRING \$query_string; + fastcgi_param REQUEST_METHOD \$request_method; + fastcgi_param CONTENT_TYPE \$content_type; + fastcgi_param CONTENT_LENGTH \$content_length; + + fastcgi_intercept_errors on; + fastcgi_ignore_client_abort off; + fastcgi_connect_timeout 60; + fastcgi_send_timeout 180; + fastcgi_read_timeout 180; + fastcgi_buffer_size 128k; + fastcgi_buffers 4 256k; + fastcgi_busy_buffers_size 256k; + fastcgi_temp_file_write_size 256k; + } + +} +EOL + + systemctl restart zabbix-server zabbix-agent nginx php$(ls /etc/php/)-fpm + echo -e "\033[32m [ OK ] \033[0m" +} + + +function gettoken(){ + ## 获取 API 永久 token + local zabbix_api_url=http://127.0.0.1/zabbix/api_jsonrpc.php + local data='{"jsonrpc": "2.0","method": "user.login","params":{"user":"Admin","password":"zabbix"},"id":1,"auth":null}' + local res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $zabbix_api_url"` + local auth=`echo $res | python3 -c 'import sys, json; print(json.load(sys.stdin)["result"])'` + local data='{"jsonrpc": "2.0","method": "token.create","params":{"name":"zeus","userid":"1"},"id":1,"auth":"'${auth}'"}' + local res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $zabbix_api_url"` + local tokenid=`echo $res | python3 -c 'import sys, json; print(json.load(sys.stdin)["result"]["tokenids"][0])'` + local data='{"jsonrpc": "2.0","method": "token.generate","params":["'${tokenid}'"],"id":1,"auth":"'${auth}'"}' + local res=`eval exec "curl -d '$data' -H 'Content-Type: application/json' -X POST -s $zabbix_api_url"` + token=`echo $res | python3 -c 'import sys, json; print(json.load(sys.stdin)["result"][0]["token"])'` +} + + +function taosinstall() { + ### taos 数据安装 + echo -e -n "\033[32mStep5: 安装 taos 数据库 .... \033[0m" + wget --quiet -c https://www.taosdata.com/assets-download/TDengine-server-2.2.0.2-Linux-x64.deb 1> /dev/null + expect << EOF 1> /dev/null + spawn dpkg -i TDengine-server-2.2.0.2-Linux-x64.deb + expect { + "*one:" { send "\n";exp_continue} + "*skip:" { send "\n" } + } +EOF + systemctl enable taosd 1> /dev/null + systemctl start taosd 1> /dev/null + echo -e "\033[32m [ OK ] \033[0m" +} + + +function ZeusInstall() { + echo -e -n "\033[32mStep6: 安装 Zeus-IoT 服务 .... \033[0m" + [ ! -d /opt/zeus ] && mkdir -p /opt/zeus + cd /opt/zeus || exit + ## 创建taos 数据库 + taos -s "create database zeus_data" 1> /dev/null + wget -c https:///zeus-iot/zeus-iot-bin.tar.gz -o /dev/null -O - | tar -xz + gettoken + ## 数据库导入 + sudo -u postgres createdb -E Unicode -T template0 zeus-iot + cat ./zeus-iot-bin/bin/sql/zeus-iot.sql | sudo -u postgres psql zeus-iot &>/dev/null + logprint "文件未找到" + sed -i "s%\(zbxApiToken: \).*%\1$token%" ./zeus-iot-bin/webapp/webapp.yml + #sed -i '19i export ZEUS_DB_PASSWORD=zeusiot' ./zeus-iot-bin/bin/startup.sh + ./zeus-iot-bin/bin/startup.sh 1> /dev/null + echo -e "\033[32m [ OK ] \033[0m" +} + + +function sendmsg() { + echo "zabbix 部分已安装成功,zeus iot 可以参照 www.zmops.com 官方文档自定义安装。" + echo "" + echo "zabbix server 访问地址: http:///zabbix" + echo "" + echo "登录用户名:Admin" + echo "登录密 码:zabbix" +} + + +function clearsys() { + + function kill9() { + status=`ps -ef | grep $1 | grep -v grep | awk '{print $2}' | wc -l` + + if [ $status -ne 0 ] + then + for i in `ps -ef | grep $1 | grep -v grep | awk '{print $2}'` + do + kill -9 $i + done + fi + } + + # 清理应用 + ## 清理 zeus + kill9 zeus-iot-bin + + [ -d /opt/zeus/zeus-iot-bin ] && rm -rf /opt/zeus/zeus-iot-bin + + ## 清理 taos + systemctl stop taosd &> /dev/null + + kill9 taosd + + apt-get remove tdengine &> /dev/null + + [ -d /usr/local/taos ] && rm -rf /usr/local/taos + + ## 清理 zabbix + systemctl stop zabbix-server zabbix-agent &> /dev/null + + kill9 zabbix_server + kill9 zabbix_agent + + [ -f /lib/systemd/system/zabbix-server.service ] && rm -rf /lib/systemd/system/zabbix-server.service + [ -f /lib/systemd/system/zabbix-agent.service ] && rm -rf /lib/systemd/system/zabbix-agent.service + + ## 清理 postgresql 数据库 + systemctl stop postgresql &> /dev/null + + kill9 postmaster + + apt-get remove postgresql-13 -y &> /dev/null + + [ -d /opt/zeus/pgdata ] && rm -rf /opt/zeus/pgdata + [ -f /lib/systemd/system/postgresql.service ] && rm -rf /lib/systemd/system/postgresql.service + + ## 清理 nginx + systemctl stop nginx &> nginx + + kill9 nginx + apt-get remove nginx -y &> /dev/null + [ -f /lib/systemd/system/nginx ] && rm -rf /lib/systemd/system/nginx +} + + + +function main() { + case $1 in + install) + syscheck + InitSystem + AddInstallRepo + PGInstall + ZbxInstall + taosinstall + ;; + clear) + clearsys + ;; + *) + echo "请输入 install|clear" + exit 1 + ;; + esac +} + +if main $1 ;then + sendmsg +fi + diff --git a/iot-common/iot-datacarrier/pom.xml b/iot-common/iot-datacarrier/pom.xml deleted file mode 100644 index 8fc7799b..00000000 --- a/iot-common/iot-datacarrier/pom.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - 4.0.0 - - com.zmops - iot-datacarrier - 1.0-beta - - iot-datacarrier - - http://www.example.com - - - UTF-8 - 1.7 - 1.7 - - - - - junit - junit - 4.11 - test - - - - - - - - - maven-clean-plugin - 3.1.0 - - - - maven-resources-plugin - 3.0.2 - - - maven-compiler-plugin - 3.8.0 - - - maven-surefire-plugin - 2.22.1 - - - maven-jar-plugin - 3.0.2 - - - maven-install-plugin - 2.5.2 - - - maven-deploy-plugin - 2.8.2 - - - - maven-site-plugin - 3.7.1 - - - maven-project-info-reports-plugin - 3.0.0 - - - - - diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/DataCarrier.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/DataCarrier.java deleted file mode 100644 index 6a33305b..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/DataCarrier.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.datacarrier; - - -import com.zmops.zeus.iot.server.datacarrier.buffer.BufferStrategy; -import com.zmops.zeus.iot.server.datacarrier.buffer.Channels; -import com.zmops.zeus.iot.server.datacarrier.consumer.ConsumeDriver; -import com.zmops.zeus.iot.server.datacarrier.consumer.ConsumerPool; -import com.zmops.zeus.iot.server.datacarrier.consumer.IConsumer; -import com.zmops.zeus.iot.server.datacarrier.consumer.IDriver; -import com.zmops.zeus.iot.server.datacarrier.partition.IDataPartitioner; -import com.zmops.zeus.iot.server.datacarrier.partition.SimpleRollingPartitioner; - -/** - * DataCarrier main class. use this instance to set Producer/Consumer Model. - */ -public class DataCarrier { - private final Channels channels; - private IDriver driver; - private final String name; - - public DataCarrier(int channelSize, int bufferSize) { - this("DEFAULT", channelSize, bufferSize); - } - - public DataCarrier(String name, int channelSize, int bufferSize) { - this(name, name, channelSize, bufferSize); - } - - public DataCarrier(String name, String envPrefix, int channelSize, int bufferSize) { - this(name, envPrefix, channelSize, bufferSize, BufferStrategy.BLOCKING); - } - - public DataCarrier(String name, String envPrefix, int channelSize, int bufferSize, BufferStrategy strategy) { - this.name = name; - bufferSize = EnvUtil.getInt(envPrefix + "_BUFFER_SIZE", bufferSize); - channelSize = EnvUtil.getInt(envPrefix + "_CHANNEL_SIZE", channelSize); - channels = new Channels<>(channelSize, bufferSize, new SimpleRollingPartitioner(), strategy); - } - - public DataCarrier(int channelSize, int bufferSize, BufferStrategy strategy) { - this("DEFAULT", "DEFAULT", channelSize, bufferSize, strategy); - } - - /** - * set a new IDataPartitioner. It will cover the current one or default one.(Default is {@link - * SimpleRollingPartitioner} - * - * @param dataPartitioner to partition data into different channel by some rules. - * @return DataCarrier instance for chain - */ - public DataCarrier setPartitioner(IDataPartitioner dataPartitioner) { - this.channels.setPartitioner(dataPartitioner); - return this; - } - - /** - * produce data to buffer, using the given {@link BufferStrategy}. - * - * @return false means produce data failure. The data will not be consumed. - */ - public boolean produce(T data) { - if (driver != null) { - if (!driver.isRunning(channels)) { - return false; - } - } - - return this.channels.save(data); - } - - /** - * set consumeDriver to this Carrier. consumer begin to run when {@link DataCarrier#produce} begin to work. - * - * @param consumerClass class of consumer - * @param num number of consumer threads - */ - public DataCarrier consume(Class> consumerClass, int num, long consumeCycle) { - if (driver != null) { - driver.close(channels); - } - driver = new ConsumeDriver(this.name, this.channels, consumerClass, num, consumeCycle); - driver.begin(channels); - return this; - } - - /** - * set consumeDriver to this Carrier. consumer begin to run when {@link DataCarrier#produce} begin to work with 20 - * millis consume cycle. - * - * @param consumerClass class of consumer - * @param num number of consumer threads - */ - public DataCarrier consume(Class> consumerClass, int num) { - return this.consume(consumerClass, num, 20); - } - - /** - * set consumeDriver to this Carrier. consumer begin to run when {@link DataCarrier#produce} begin to work. - * - * @param consumer single instance of consumer, all consumer threads will all use this instance. - * @param num number of consumer threads - */ - public DataCarrier consume(IConsumer consumer, int num, long consumeCycle) { - if (driver != null) { - driver.close(channels); - } - driver = new ConsumeDriver(this.name, this.channels, consumer, num, consumeCycle); - driver.begin(channels); - return this; - } - - /** - * set consumeDriver to this Carrier. consumer begin to run when {@link DataCarrier#produce} begin to work with 20 - * millis consume cycle. - * - * @param consumer single instance of consumer, all consumer threads will all use this instance. - * @param num number of consumer threads - */ - public DataCarrier consume(IConsumer consumer, int num) { - return this.consume(consumer, num, 20); - } - - /** - * Set a consumer pool to manage the channels of this DataCarrier. Then consumerPool could use its own consuming - * model to adjust the consumer thread and throughput. - */ - public DataCarrier consume(ConsumerPool consumerPool, IConsumer consumer) { - driver = consumerPool; - consumerPool.add(this.name, channels, consumer); - driver.begin(channels); - return this; - } - - /** - * shutdown all consumer threads, if consumer threads are running. Notice {@link BufferStrategy}: if {@link - * BufferStrategy} == {@link BufferStrategy#BLOCKING}, shutdown consumeDriver maybe cause blocking when producing. - * Better way to change consumeDriver are use {@link DataCarrier#consume} - */ - public void shutdownConsumers() { - if (driver != null) { - driver.close(channels); - } - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/EnvUtil.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/EnvUtil.java deleted file mode 100644 index a94dcdbe..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/EnvUtil.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.datacarrier; - -/** - * Read value from system env. - */ -public class EnvUtil { - public static int getInt(String envName, int defaultValue) { - int value = defaultValue; - String envValue = System.getenv(envName); - if (envValue != null) { - try { - value = Integer.parseInt(envValue); - } catch (NumberFormatException e) { - - } - } - return value; - } - - public static long getLong(String envName, long defaultValue) { - long value = defaultValue; - String envValue = System.getenv(envName); - if (envValue != null) { - try { - value = Long.parseLong(envValue); - } catch (NumberFormatException e) { - - } - } - return value; - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/ArrayBlockingQueueBuffer.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/ArrayBlockingQueueBuffer.java deleted file mode 100644 index 8cdfbc62..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/ArrayBlockingQueueBuffer.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.datacarrier.buffer; - -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; - -/** - * The buffer implementation based on JDK ArrayBlockingQueue. - *

- * This implementation has better performance in server side. We are still trying to research whether this is suitable - * for agent side, which is more sensitive about blocks. - */ -public class ArrayBlockingQueueBuffer implements QueueBuffer { - private BufferStrategy strategy; - private ArrayBlockingQueue queue; - private int bufferSize; - - ArrayBlockingQueueBuffer(int bufferSize, BufferStrategy strategy) { - this.strategy = strategy; - this.queue = new ArrayBlockingQueue(bufferSize); - this.bufferSize = bufferSize; - } - - @Override - public boolean save(T data) { - //only BufferStrategy.BLOCKING - try { - queue.put(data); - } catch (InterruptedException e) { - // Ignore the error - return false; - } - return true; - } - - @Override - public void setStrategy(BufferStrategy strategy) { - this.strategy = strategy; - } - - @Override - public void obtain(List consumeList) { - queue.drainTo(consumeList); - } - - @Override - public int getBufferSize() { - return bufferSize; - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Buffer.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Buffer.java deleted file mode 100644 index 8cf6b233..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Buffer.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.datacarrier.buffer; - - -import com.zmops.zeus.iot.server.datacarrier.common.AtomicRangeInteger; - -import java.util.List; - -/** - * Self implementation ring queue. - */ -public class Buffer implements QueueBuffer { - private final Object[] buffer; - private BufferStrategy strategy; - private final AtomicRangeInteger index; - - Buffer(int bufferSize, BufferStrategy strategy) { - buffer = new Object[bufferSize]; - this.strategy = strategy; - index = new AtomicRangeInteger(0, bufferSize); - } - - @Override - public void setStrategy(BufferStrategy strategy) { - this.strategy = strategy; - } - - @Override - public boolean save(T data) { - int i = index.getAndIncrement(); - if (buffer[i] != null) { - if (strategy == BufferStrategy.IF_POSSIBLE) { - return false; - } - } - buffer[i] = data; - return true; - } - - @Override - public int getBufferSize() { - return buffer.length; - } - - @Override - public void obtain(List consumeList) { - this.obtain(consumeList, 0, buffer.length); - } - - void obtain(List consumeList, int start, int end) { - for (int i = start; i < end; i++) { - if (buffer[i] != null) { - consumeList.add((T) buffer[i]); - buffer[i] = null; - } - } - } - -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Channels.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Channels.java deleted file mode 100644 index cb24ec37..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/Channels.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.datacarrier.buffer; - - -import com.zmops.zeus.iot.server.datacarrier.partition.IDataPartitioner; - -/** - * Channels of Buffer It contains all buffer data which belongs to this channel. It supports several strategy when - * buffer is full. The Default is BLOCKING

Created by wusheng on 2016/10/25. - */ -public class Channels { - private final QueueBuffer[] bufferChannels; - private IDataPartitioner dataPartitioner; - private final BufferStrategy strategy; - private final long size; - - public Channels(int channelSize, int bufferSize, IDataPartitioner partitioner, BufferStrategy strategy) { - this.dataPartitioner = partitioner; - this.strategy = strategy; - bufferChannels = new QueueBuffer[channelSize]; - for (int i = 0; i < channelSize; i++) { - if (BufferStrategy.BLOCKING.equals(strategy)) { - bufferChannels[i] = new ArrayBlockingQueueBuffer<>(bufferSize, strategy); - } else { - bufferChannels[i] = new Buffer<>(bufferSize, strategy); - } - } - // noinspection PointlessArithmeticExpression - size = 1L * channelSize * bufferSize; // it's not pointless, it prevents numeric overflow before assigning an integer to a long - } - - public boolean save(T data) { - int index = dataPartitioner.partition(bufferChannels.length, data); - int retryCountDown = 1; - if (BufferStrategy.IF_POSSIBLE.equals(strategy)) { - int maxRetryCount = dataPartitioner.maxRetryCount(); - if (maxRetryCount > 1) { - retryCountDown = maxRetryCount; - } - } - for (; retryCountDown > 0; retryCountDown--) { - if (bufferChannels[index].save(data)) { - return true; - } - } - return false; - } - - public void setPartitioner(IDataPartitioner dataPartitioner) { - this.dataPartitioner = dataPartitioner; - } - - /** - * override the strategy at runtime. Notice, this will override several channels one by one. So, when running - * setStrategy, each channel may use different BufferStrategy - */ - public void setStrategy(BufferStrategy strategy) { - for (QueueBuffer buffer : bufferChannels) { - buffer.setStrategy(strategy); - } - } - - /** - * get channelSize - */ - public int getChannelSize() { - return this.bufferChannels.length; - } - - public long size() { - return size; - } - - public QueueBuffer getBuffer(int index) { - return this.bufferChannels[index]; - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/common/AtomicRangeInteger.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/common/AtomicRangeInteger.java deleted file mode 100644 index dac9a527..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/common/AtomicRangeInteger.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.datacarrier.common; - -import java.io.Serializable; -import java.util.concurrent.atomic.AtomicIntegerArray; - -public class AtomicRangeInteger extends Number implements Serializable { - private static final long serialVersionUID = -4099792402691141643L; - private AtomicIntegerArray values; - - private static final int VALUE_OFFSET = 15; - - private int startValue; - private int endValue; - - public AtomicRangeInteger(int startValue, int maxValue) { - this.values = new AtomicIntegerArray(31); - this.values.set(VALUE_OFFSET, startValue); - this.startValue = startValue; - this.endValue = maxValue - 1; - } - - public final int getAndIncrement() { - int next; - do { - next = this.values.incrementAndGet(VALUE_OFFSET); - if (next > endValue && this.values.compareAndSet(VALUE_OFFSET, next, startValue)) { - return endValue; - } - } - while (next > endValue); - - return next - 1; - } - - public final int get() { - return this.values.get(VALUE_OFFSET); - } - - @Override - public int intValue() { - return this.values.get(VALUE_OFFSET); - } - - @Override - public long longValue() { - return this.values.get(VALUE_OFFSET); - } - - @Override - public float floatValue() { - return this.values.get(VALUE_OFFSET); - } - - @Override - public double doubleValue() { - return this.values.get(VALUE_OFFSET); - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/BulkConsumePool.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/BulkConsumePool.java deleted file mode 100644 index 2c5131ee..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/BulkConsumePool.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.datacarrier.consumer; - - -import com.zmops.zeus.iot.server.datacarrier.EnvUtil; -import com.zmops.zeus.iot.server.datacarrier.buffer.Channels; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; - -/** - * BulkConsumePool works for consuming data from multiple channels(DataCarrier instances), with multiple {@link - * MultipleChannelsConsumer}s. - *

- * In typical case, the number of {@link MultipleChannelsConsumer} should be less than the number of channels. - */ -public class BulkConsumePool implements ConsumerPool { - private List allConsumers; - private volatile boolean isStarted = false; - - public BulkConsumePool(String name, int size, long consumeCycle) { - size = EnvUtil.getInt(name + "_THREAD", size); - allConsumers = new ArrayList(size); - for (int i = 0; i < size; i++) { - MultipleChannelsConsumer multipleChannelsConsumer = new MultipleChannelsConsumer("DataCarrier." + name + ".BulkConsumePool." + i + ".Thread", consumeCycle); - multipleChannelsConsumer.setDaemon(true); - allConsumers.add(multipleChannelsConsumer); - } - } - - @Override - synchronized public void add(String name, Channels channels, IConsumer consumer) { - MultipleChannelsConsumer multipleChannelsConsumer = getLowestPayload(); - multipleChannelsConsumer.addNewTarget(channels, consumer); - } - - /** - * Get the lowest payload consumer thread based on current allocate status. - * - * @return the lowest consumer. - */ - private MultipleChannelsConsumer getLowestPayload() { - MultipleChannelsConsumer winner = allConsumers.get(0); - for (int i = 1; i < allConsumers.size(); i++) { - MultipleChannelsConsumer option = allConsumers.get(i); - if (option.size() < winner.size()) { - winner = option; - } - } - return winner; - } - - /** - * - */ - @Override - public boolean isRunning(Channels channels) { - return isStarted; - } - - @Override - public void close(Channels channels) { - for (MultipleChannelsConsumer consumer : allConsumers) { - consumer.shutdown(); - } - } - - @Override - public void begin(Channels channels) { - if (isStarted) { - return; - } - for (MultipleChannelsConsumer consumer : allConsumers) { - consumer.start(); - } - isStarted = true; - } - - /** - * The creator for {@link BulkConsumePool}. - */ - public static class Creator implements Callable { - private String name; - private int size; - private long consumeCycle; - - public Creator(String name, int poolSize, long consumeCycle) { - this.name = name; - this.size = poolSize; - this.consumeCycle = consumeCycle; - } - - @Override - public ConsumerPool call() { - return new BulkConsumePool(name, size, consumeCycle); - } - - public static int recommendMaxSize() { - return Runtime.getRuntime().availableProcessors() * 2; - } - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumeDriver.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumeDriver.java deleted file mode 100644 index d84c4c53..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumeDriver.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.datacarrier.consumer; - - -import com.zmops.zeus.iot.server.datacarrier.buffer.Channels; - -import java.lang.reflect.InvocationTargetException; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Pool of consumers

Created by wusheng on 2016/10/25. - */ -public class ConsumeDriver implements IDriver { - private boolean running; - private ConsumerThread[] consumerThreads; - private Channels channels; - private ReentrantLock lock; - - public ConsumeDriver(String name, Channels channels, Class> consumerClass, int num, - long consumeCycle) { - this(channels, num); - for (int i = 0; i < num; i++) { - consumerThreads[i] = new ConsumerThread("DataCarrier." + name + ".Consumer." + i + ".Thread", getNewConsumerInstance(consumerClass), consumeCycle); - consumerThreads[i].setDaemon(true); - } - } - - public ConsumeDriver(String name, Channels channels, IConsumer prototype, int num, long consumeCycle) { - this(channels, num); - prototype.init(); - for (int i = 0; i < num; i++) { - consumerThreads[i] = new ConsumerThread("DataCarrier." + name + ".Consumer." + i + ".Thread", prototype, consumeCycle); - consumerThreads[i].setDaemon(true); - } - - } - - private ConsumeDriver(Channels channels, int num) { - running = false; - this.channels = channels; - consumerThreads = new ConsumerThread[num]; - lock = new ReentrantLock(); - } - - private IConsumer getNewConsumerInstance(Class> consumerClass) { - try { - IConsumer inst = consumerClass.getDeclaredConstructor().newInstance(); - inst.init(); - return inst; - } catch (InstantiationException e) { - throw new ConsumerCannotBeCreatedException(e); - } catch (IllegalAccessException e) { - throw new ConsumerCannotBeCreatedException(e); - } catch (NoSuchMethodException e) { - throw new ConsumerCannotBeCreatedException(e); - } catch (InvocationTargetException e) { - throw new ConsumerCannotBeCreatedException(e); - } - } - - @Override - public void begin(Channels channels) { - if (running) { - return; - } - lock.lock(); - try { - this.allocateBuffer2Thread(); - for (ConsumerThread consumerThread : consumerThreads) { - consumerThread.start(); - } - running = true; - } finally { - lock.unlock(); - } - } - - @Override - public boolean isRunning(Channels channels) { - return running; - } - - private void allocateBuffer2Thread() { - int channelSize = this.channels.getChannelSize(); - /** - * if consumerThreads.length < channelSize - * each consumer will process several channels. - * - * if consumerThreads.length == channelSize - * each consumer will process one channel. - * - * if consumerThreads.length > channelSize - * there will be some threads do nothing. - */ - for (int channelIndex = 0; channelIndex < channelSize; channelIndex++) { - int consumerIndex = channelIndex % consumerThreads.length; - consumerThreads[consumerIndex].addDataSource(channels.getBuffer(channelIndex)); - } - - } - - @Override - public void close(Channels channels) { - lock.lock(); - try { - this.running = false; - for (ConsumerThread consumerThread : consumerThreads) { - consumerThread.shutdown(); - } - } finally { - lock.unlock(); - } - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerCannotBeCreatedException.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerCannotBeCreatedException.java deleted file mode 100644 index 726feec2..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerCannotBeCreatedException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.datacarrier.consumer; - -public class ConsumerCannotBeCreatedException extends RuntimeException { - ConsumerCannotBeCreatedException(Throwable t) { - super(t); - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPoolFactory.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPoolFactory.java deleted file mode 100644 index af114378..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPoolFactory.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.datacarrier.consumer; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.Callable; - -/** - * Consumer Pool Factory provides global management for all Consumer Pool. - */ -public enum ConsumerPoolFactory { - INSTANCE; - - private final Map pools; - - ConsumerPoolFactory() { - pools = new HashMap<>(); - } - - public synchronized boolean createIfAbsent(String poolName, Callable creator) throws Exception { - if (pools.containsKey(poolName)) { - return false; - } else { - pools.put(poolName, creator.call()); - return true; - } - } - - public ConsumerPool get(String poolName) { - return pools.get(poolName); - } - -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerThread.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerThread.java deleted file mode 100644 index f22d9284..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerThread.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.datacarrier.consumer; - - -import com.zmops.zeus.iot.server.datacarrier.buffer.Buffer; -import com.zmops.zeus.iot.server.datacarrier.buffer.QueueBuffer; - -import java.util.ArrayList; -import java.util.List; - -public class ConsumerThread extends Thread { - private volatile boolean running; - private IConsumer consumer; - private List dataSources; - private long consumeCycle; - - ConsumerThread(String threadName, IConsumer consumer, long consumeCycle) { - super(threadName); - this.consumer = consumer; - running = false; - dataSources = new ArrayList(1); - this.consumeCycle = consumeCycle; - } - - /** - * add whole buffer to consume - */ - void addDataSource(QueueBuffer sourceBuffer) { - this.dataSources.add(new DataSource(sourceBuffer)); - } - - @Override - public void run() { - running = true; - - final List consumeList = new ArrayList(1500); - while (running) { - if (!consume(consumeList)) { - try { - Thread.sleep(consumeCycle); - } catch (InterruptedException e) { - } - } - } - - // consumer thread is going to stop - // consume the last time - consume(consumeList); - - consumer.onExit(); - } - - private boolean consume(List consumeList) { - for (DataSource dataSource : dataSources) { - dataSource.obtain(consumeList); - } - - if (!consumeList.isEmpty()) { - try { - consumer.consume(consumeList); - } catch (Throwable t) { - consumer.onError(consumeList, t); - } finally { - consumeList.clear(); - } - return true; - } - return false; - } - - void shutdown() { - running = false; - } - - /** - * DataSource is a refer to {@link Buffer}. - */ - class DataSource { - private QueueBuffer sourceBuffer; - - DataSource(QueueBuffer sourceBuffer) { - this.sourceBuffer = sourceBuffer; - } - - void obtain(List consumeList) { - sourceBuffer.obtain(consumeList); - } - } -} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/MultipleChannelsConsumer.java b/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/MultipleChannelsConsumer.java deleted file mode 100644 index ff66d9b1..00000000 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/MultipleChannelsConsumer.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.datacarrier.consumer; - - -import com.zmops.zeus.iot.server.datacarrier.buffer.Channels; -import com.zmops.zeus.iot.server.datacarrier.buffer.QueueBuffer; - -import java.util.ArrayList; -import java.util.List; - -/** - * MultipleChannelsConsumer represent a single consumer thread, but support multiple channels with their {@link - * IConsumer}s - */ -public class MultipleChannelsConsumer extends Thread { - private volatile boolean running; - private volatile ArrayList consumeTargets; - @SuppressWarnings("NonAtomicVolatileUpdate") - private volatile long size; - private final long consumeCycle; - - public MultipleChannelsConsumer(String threadName, long consumeCycle) { - super(threadName); - this.consumeTargets = new ArrayList(); - this.consumeCycle = consumeCycle; - } - - @Override - public void run() { - running = true; - - final List consumeList = new ArrayList(2000); - while (running) { - boolean hasData = false; - for (Group target : consumeTargets) { - boolean consume = consume(target, consumeList); - hasData = hasData || consume; - } - - if (!hasData) { - try { - Thread.sleep(consumeCycle); - } catch (InterruptedException e) { - } - } - } - - // consumer thread is going to stop - // consume the last time - for (Group target : consumeTargets) { - consume(target, consumeList); - - target.consumer.onExit(); - } - } - - private boolean consume(Group target, List consumeList) { - for (int i = 0; i < target.channels.getChannelSize(); i++) { - QueueBuffer buffer = target.channels.getBuffer(i); - buffer.obtain(consumeList); - } - - if (!consumeList.isEmpty()) { - try { - target.consumer.consume(consumeList); - } catch (Throwable t) { - target.consumer.onError(consumeList, t); - } finally { - consumeList.clear(); - } - return true; - } - return false; - } - - /** - * Add a new target channels. - */ - public void addNewTarget(Channels channels, IConsumer consumer) { - Group group = new Group(channels, consumer); - // Recreate the new list to avoid change list while the list is used in consuming. - ArrayList newList = new ArrayList(); - for (Group target : consumeTargets) { - newList.add(target); - } - newList.add(group); - consumeTargets = newList; - size += channels.size(); - } - - public long size() { - return size; - } - - void shutdown() { - running = false; - } - - private static class Group { - private Channels channels; - private IConsumer consumer; - - public Group(Channels channels, IConsumer consumer) { - this.channels = channels; - this.consumer = consumer; - } - } -} diff --git a/iot-common/iot-eventbus/pom.xml b/iot-common/iot-eventbus/pom.xml deleted file mode 100644 index 6a3d5e21..00000000 --- a/iot-common/iot-eventbus/pom.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - iot-common - com.zmops - 1.0-beta - - 4.0.0 - - - iot-eventbus - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-common/iot-util/pom.xml b/iot-common/iot-util/pom.xml deleted file mode 100644 index d1bdc7a4..00000000 --- a/iot-common/iot-util/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - iot-common - com.zmops - 1.0-beta - - 4.0.0 - - iot-util - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PlaceholderConfigurerSupport.java b/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PlaceholderConfigurerSupport.java deleted file mode 100644 index 359502aa..00000000 --- a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PlaceholderConfigurerSupport.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.util; - -public class PlaceholderConfigurerSupport { - - /** - * Default placeholder prefix: {@value} - */ - public static final String DEFAULT_PLACEHOLDER_PREFIX = "${"; - - /** - * Default placeholder suffix: {@value} - */ - public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}"; - - /** - * Default value separator: {@value} - */ - public static final String DEFAULT_VALUE_SEPARATOR = ":"; - -} diff --git a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PropertyPlaceholderHelper.java b/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PropertyPlaceholderHelper.java deleted file mode 100644 index a6fcbff7..00000000 --- a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/PropertyPlaceholderHelper.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.util; - -import java.util.*; - -/** - * Utility class for working with Strings that have placeholder values in them. A placeholder takes the form {@code - * ${name}}. Using {@code PropertyPlaceholderHelper} these placeholders can be substituted for user-supplied values.

- * Values for substitution can be supplied using a {@link Properties} instance or using a {@link PlaceholderResolver}. - */ -public enum PropertyPlaceholderHelper { - - INSTANCE( - PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_PREFIX, - PlaceholderConfigurerSupport.DEFAULT_PLACEHOLDER_SUFFIX, PlaceholderConfigurerSupport.DEFAULT_VALUE_SEPARATOR, - true - ); - - private final String placeholderPrefix; - - private final String placeholderSuffix; - - private final String simplePrefix; - - private final String valueSeparator; - - private final boolean ignoreUnresolvablePlaceholders; - - /** - * Creates a new {@code PropertyPlaceholderHelper} that uses the supplied prefix and suffix. - * - * @param placeholderPrefix the prefix that denotes the start of a placeholder - * @param placeholderSuffix the suffix that denotes the end of a placeholder - * @param valueSeparator the separating character between the placeholder variable and the - * associated default value, if any - * @param ignoreUnresolvablePlaceholders indicates whether unresolvable placeholders should be ignored ({@code - * true}) or cause an exception ({@code false}) - */ - PropertyPlaceholderHelper(String placeholderPrefix, String placeholderSuffix, String valueSeparator, - boolean ignoreUnresolvablePlaceholders) { - if (StringUtil.isEmpty(placeholderPrefix) || StringUtil.isEmpty(placeholderSuffix)) { - throw new UnsupportedOperationException("'placeholderPrefix or placeholderSuffix' must not be null"); - } - - final Map wellKnownSimplePrefixes = new HashMap(4); - - wellKnownSimplePrefixes.put("}", "{"); - wellKnownSimplePrefixes.put("]", "["); - wellKnownSimplePrefixes.put(")", "("); - - this.placeholderPrefix = placeholderPrefix; - this.placeholderSuffix = placeholderSuffix; - String simplePrefixForSuffix = wellKnownSimplePrefixes.get(this.placeholderSuffix); - if (simplePrefixForSuffix != null && this.placeholderPrefix.endsWith(simplePrefixForSuffix)) { - this.simplePrefix = simplePrefixForSuffix; - } else { - this.simplePrefix = this.placeholderPrefix; - } - this.valueSeparator = valueSeparator; - this.ignoreUnresolvablePlaceholders = ignoreUnresolvablePlaceholders; - } - - /** - * Replaces all placeholders of format {@code ${name}} with the corresponding property from the supplied {@link - * Properties}. - * - * @param value the value containing the placeholders to be replaced - * @param properties the {@code Properties} to use for replacement - * @return the supplied value with placeholders replaced inline - */ - public String replacePlaceholders(String value, final Properties properties) { - return replacePlaceholders(value, new PlaceholderResolver() { - @Override - public String resolvePlaceholder(String placeholderName) { - return getConfigValue(placeholderName, properties); - } - }); - } - - private String getConfigValue(String key, final Properties properties) { - String value = System.getProperty(key); - if (value == null) { - value = System.getenv(key); - } - if (value == null) { - value = properties.getProperty(key); - } - return value; - } - - /** - * Replaces all placeholders of format {@code ${name}} with the value returned from the supplied {@link - * PlaceholderResolver}. - * - * @param value the value containing the placeholders to be replaced - * @param placeholderResolver the {@code PlaceholderResolver} to use for replacement - * @return the supplied value with placeholders replaced inline - */ - public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) { - return parseStringValue(value, placeholderResolver, new HashSet()); - } - - protected String parseStringValue(String value, PlaceholderResolver placeholderResolver, Set visitedPlaceholders) { - - StringBuilder result = new StringBuilder(value); - - int startIndex = value.indexOf(this.placeholderPrefix); - while (startIndex != -1) { - int endIndex = findPlaceholderEndIndex(result, startIndex); - if (endIndex != -1) { - String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex); - String originalPlaceholder = placeholder; - if (!visitedPlaceholders.add(originalPlaceholder)) { - throw new IllegalArgumentException("Circular placeholder reference '" + originalPlaceholder + "' in property definitions"); - } - // Recursive invocation, parsing placeholders contained in the placeholder key. - placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders); - // Now obtain the value for the fully resolved key... - String propVal = placeholderResolver.resolvePlaceholder(placeholder); - - if (propVal == null && this.valueSeparator != null) { - int separatorIndex = placeholder.indexOf(this.valueSeparator); - if (separatorIndex != -1) { - String actualPlaceholder = placeholder.substring(0, separatorIndex); - String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length()); - propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder); - if (propVal == null) { - propVal = defaultValue; - } - } - } - - if (propVal != null) { - // Recursive invocation, parsing placeholders contained in the - // previously resolved placeholder value. - propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders); - result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal); - startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length()); - } else if (this.ignoreUnresolvablePlaceholders) { - // Proceed with unprocessed value. - startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length()); - } else { - throw new IllegalArgumentException( - "Could not resolve placeholder '" + placeholder + "'" + " in value \"" + value + "\""); - } - visitedPlaceholders.remove(originalPlaceholder); - } else { - startIndex = -1; - } - } - return result.toString(); - } - - private int findPlaceholderEndIndex(CharSequence buf, int startIndex) { - int index = startIndex + this.placeholderPrefix.length(); - int withinNestedPlaceholder = 0; - while (index < buf.length()) { - if (StringUtil.substringMatch(buf, index, this.placeholderSuffix)) { - if (withinNestedPlaceholder > 0) { - withinNestedPlaceholder--; - index = index + this.placeholderSuffix.length(); - } else { - return index; - } - } else if (StringUtil.substringMatch(buf, index, this.simplePrefix)) { - withinNestedPlaceholder++; - index = index + this.simplePrefix.length(); - } else { - index++; - } - } - return -1; - } - - /** - * Strategy interface used to resolve replacement values for placeholders contained in Strings. - */ - public interface PlaceholderResolver { - - /** - * Resolve the supplied placeholder name to the replacement value. - * - * @param placeholderName the name of the placeholder to resolve - * @return the replacement value, or {@code null} if no replacement is to be made - */ - String resolvePlaceholder(String placeholderName); - } -} diff --git a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/StringUtil.java b/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/StringUtil.java deleted file mode 100644 index ba296aee..00000000 --- a/iot-common/iot-util/src/main/java/com/zmops/zeus/iot/server/util/StringUtil.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.util; - -import java.util.function.Consumer; - -public final class StringUtil { - public static boolean isEmpty(String str) { - return str == null || str.length() == 0; - } - - public static boolean isNotEmpty(String str) { - return !isEmpty(str); - } - - public static boolean isBlank(String str) { - return str == null || isEmpty(str.trim()); - } - - public static boolean isNotBlank(String str) { - return !isBlank(str); - } - - public static void setIfPresent(String value, Consumer setter) { - if (isNotEmpty(value)) { - setter.accept(value); - } - } - - public static String join(final char delimiter, final String... strings) { - if (strings.length == 0) { - return null; - } - if (strings.length == 1) { - return strings[0]; - } - int length = strings.length - 1; - for (final String s : strings) { - if (s == null) { - continue; - } - length += s.length(); - } - final StringBuilder sb = new StringBuilder(length); - if (strings[0] != null) { - sb.append(strings[0]); - } - for (int i = 1; i < strings.length; ++i) { - if (!isEmpty(strings[i])) { - sb.append(delimiter).append(strings[i]); - } else { - sb.append(delimiter); - } - } - return sb.toString(); - } - - public static boolean substringMatch(CharSequence str, int index, CharSequence substring) { - if (index + substring.length() > str.length()) { - return false; - } - for (int i = 0; i < substring.length(); i++) { - if (str.charAt(index + i) != substring.charAt(i)) { - return false; - } - } - return true; - } - - public static String cut(String str, int threshold) { - if (isEmpty(str) || str.length() <= threshold) { - return str; - } - return str.substring(0, threshold); - } - - public static String trim(final String str, final char ch) { - if (isEmpty(str)) { - return null; - } - - final char[] chars = str.toCharArray(); - - int i = 0, j = chars.length - 1; - // noinspection StatementWithEmptyBody - for (; i < chars.length && chars[i] == ch; i++) { - } - // noinspection StatementWithEmptyBody - for (; j > 0 && chars[j] == ch; j--) { - } - - return new String(chars, i, j - i + 1); - } -} diff --git a/iot-common/pom.xml b/iot-common/pom.xml deleted file mode 100644 index 5647a4c4..00000000 --- a/iot-common/pom.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - zeus-iot-server - com.zmops - 1.0-beta - ../iot-server-dist/pom.xml - - 4.0.0 - - iot-common - pom - - iot-datacarrier - iot-util - iot-eventbus - - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-server-bom/pom.xml b/iot-server-bom/pom.xml new file mode 100644 index 00000000..6c4beee9 --- /dev/null +++ b/iot-server-bom/pom.xml @@ -0,0 +1,119 @@ + + + + + com.zmops + zeus-iot + 1.0-beta + + + pom + 4.0.0 + iot-server-bom + + IoT Server 协议解析层 + + + 3.11.4 + 1.18.20 + 2.17.0 + 25.1-jre + 4.1.65.Final + 2.8.7 + + + + + + io.netty + netty-bom + ${netty.version} + import + pom + + + org.projectlombok + lombok + ${lombok.version} + + + + org.apache.logging.log4j + log4j-api + ${log4j.version} + + + org.apache.logging.log4j + log4j-slf4j-impl + ${log4j.version} + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + + + org.apache.logging.log4j + log4j-web + ${log4j.version} + + + + com.google.guava + guava + ${guava.version} + + + + org.apache.camel + camel-core + ${camel.version} + + + org.apache.camel + camel-jsonpath + ${camel.version} + + + com.google.code.gson + gson + ${gson.version} + + + + org.apache.camel + camel-netty-http + ${camel.version} + + + org.apache.camel + camel-netty + ${camel.version} + + + io.netty + netty-all + + + + + org.apache.camel + camel-paho-mqtt5 + ${camel.version} + + + com.h2database + h2 + 1.4.196 + + + + \ No newline at end of file diff --git a/iot-server-dist/pom.xml b/iot-server-dist/pom.xml deleted file mode 100644 index cc7b91d2..00000000 --- a/iot-server-dist/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - zeus-server-pom - com.zmops - 1.0-beta - ../zeus-server-pom/pom.xml - - 4.0.0 - - zeus-iot-server - pom - - ../iot-common - - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-server/pom.xml b/iot-server/pom.xml index 76d50df6..9c4f174b 100644 --- a/iot-server/pom.xml +++ b/iot-server/pom.xml @@ -3,93 +3,131 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-server-pom com.zmops + zeus-iot 1.0-beta - ../zeus-server-pom 4.0.0 - iot-server pom + + + + UTF-8 + 0.30.0 + 8 + 8 + + - server-library server-core server-starter server-bootstrap server-health-checker server-telemetry - server-receiver-plugin server-sender + server-storage-plugin + server-transfer + server-localdb + server-camel-receiver + server-web + server-client + + + + com.zmops + iot-server-bom + 1.0-beta + import + pom + + + + org.projectlombok lombok - 1.18.20 org.apache.logging.log4j log4j-api - 2.13.3 org.apache.logging.log4j log4j-slf4j-impl - 2.13.3 com.google.guava guava - 25.1-jre io.netty netty-codec-http - 4.1.65.Final io.netty netty-handler - 4.1.65.Final io.netty netty-resolver-dns - 4.1.65.Final io.netty netty-codec-dns - 4.1.65.Final org.apache.logging.log4j log4j-core - 2.13.3 org.apache.camel camel-core - ${camel.version} + + + org.slf4j + slf4j-api + + org.apache.camel camel-jsonpath - ${camel.version} com.google.code.gson gson - 2.8.7 + + + + + + org.apache.camel + camel-netty + + + io.netty + netty-example + + + io.netty + netty-all + + + + + org.apache.camel + camel-paho-mqtt5 + + + com.h2database + h2 - - 8 - 8 - \ No newline at end of file diff --git a/iot-server/readme.md b/iot-server/readme.md index a76b5c9b..ae925293 100644 --- a/iot-server/readme.md +++ b/iot-server/readme.md @@ -1,2 +1 @@ -#### 宙斯协议层服务 - - 基于Skywalking改造 \ No newline at end of file +#### 宙斯多协议网关 V1.0 \ No newline at end of file diff --git a/iot-server/server-bootstrap/pom.xml b/iot-server/server-bootstrap/pom.xml index 27b4cbb8..48c4d112 100644 --- a/iot-server/server-bootstrap/pom.xml +++ b/iot-server/server-bootstrap/pom.xml @@ -16,17 +16,29 @@ server-core ${project.version} + + + com.zmops + toolkit-util + 1.0.3-RELEASE + + + + com.zmops + server-web + 1.0-beta + + com.zmops library-module - ${project.version} + 1.0.3-RELEASE org.yaml snakeyaml 1.26 - com.zmops server-health-checker @@ -42,7 +54,6 @@ telemetry-prometheus ${project.version} - com.zmops server-sender @@ -50,19 +61,44 @@ com.zmops - http-receiver-plugin + server-tdengine-plugin ${project.version} com.zmops - tcp-receiver-plugin + server-transfer ${project.version} com.zmops - mqtt-receiver-plugin + server-none-storage ${project.version} + + com.zmops + server-camel-receiver + 1.0-beta + + + + com.zmops + server-localdb + 1.0-beta + + + + + + + + + + @@ -86,7 +122,6 @@ maven-jar-plugin - application.yml log4j2.xml @@ -94,9 +129,4 @@ - - 8 - 8 - - \ No newline at end of file diff --git a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerBootstrap.java b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java similarity index 86% rename from iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerBootstrap.java rename to iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java index a2901dbd..f31ee7a7 100644 --- a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerBootstrap.java +++ b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerBootstrap.java @@ -20,13 +20,15 @@ import com.zmops.zeus.iot.server.core.RunningMode; import com.zmops.zeus.iot.server.starter.config.ApplicationConfigLoader; -import com.zmops.zeus.iot.server.library.module.ApplicationConfiguration; -import com.zmops.zeus.iot.server.library.module.ModuleManager; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import com.zmops.zeus.server.library.module.ApplicationConfiguration; +import com.zmops.zeus.server.library.module.ModuleManager; import lombok.extern.slf4j.Slf4j; +import java.util.TimeZone; + /** * Starter core. Load the core configuration file, and initialize the startup sequence through {@link ModuleManager}. @@ -34,13 +36,16 @@ * 模块加载启动器,动态加载模块。 */ @Slf4j -public class IOTServerBootstrap { +public class IoTServerBootstrap { public static void start() { + TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); + String mode = System.getProperty("mode"); RunningMode.setMode(mode); ApplicationConfigLoader configLoader = new ApplicationConfigLoader(); - ModuleManager manager = new ModuleManager(); + + ModuleManager manager = new ModuleManager(); try { ApplicationConfiguration applicationConfiguration = configLoader.load(); manager.init(applicationConfiguration); @@ -53,9 +58,10 @@ public static void start() { .setValue(System.currentTimeMillis() / 1000d); if (RunningMode.isInitMode()) { - log.info("Zeus IOT starts up in init mode successfully, exit now..."); + log.info("Zeus IoT starts up in init mode successfully, exit now..."); System.exit(0); } + } catch (Throwable t) { log.error(t.getMessage(), t); System.exit(1); diff --git a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java index 11304f41..62676bda 100644 --- a/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java +++ b/iot-server/server-bootstrap/src/main/java/com/zmops/zeus/iot/server/starter/config/ApplicationConfigLoader.java @@ -18,13 +18,13 @@ package com.zmops.zeus.iot.server.starter.config; -import com.zmops.zeus.iot.server.library.util.CollectionUtils; -import com.zmops.zeus.iot.server.library.util.ResourceUtils; -import com.zmops.zeus.iot.server.library.module.ApplicationConfiguration; -import com.zmops.zeus.iot.server.library.module.ProviderNotFoundException; -import com.zmops.zeus.iot.server.util.PropertyPlaceholderHelper; -import lombok.extern.slf4j.Slf4j; +import com.zmops.zeus.server.library.module.ApplicationConfiguration; +import com.zmops.zeus.server.library.module.ProviderNotFoundException; +import com.zmops.zeus.server.library.util.CollectionUtils; +import com.zmops.zeus.server.library.util.ResourceUtils; +import com.zmops.zeus.server.util.PropertyPlaceholderHelper; +import lombok.extern.slf4j.Slf4j; import org.yaml.snakeyaml.Yaml; import java.io.FileNotFoundException; @@ -44,7 +44,7 @@ @Slf4j public class ApplicationConfigLoader implements ConfigLoader { private static final String DISABLE_SELECTOR = "-"; - private static final String SELECTOR = "selector"; + private static final String SELECTOR = "selector"; private final Yaml yaml = new Yaml(); @@ -59,23 +59,21 @@ public ApplicationConfiguration load() throws ConfigFileNotFoundException { @SuppressWarnings("unchecked") private void loadConfig(ApplicationConfiguration configuration) throws ConfigFileNotFoundException { try { - Reader applicationReader = ResourceUtils.read("application.yml"); - Map> moduleConfig = yaml.loadAs(applicationReader, Map.class); + Reader applicationReader = ResourceUtils.read("application.yml"); + Map> moduleConfig = yaml.loadAs(applicationReader, Map.class); if (CollectionUtils.isNotEmpty(moduleConfig)) { selectConfig(moduleConfig); moduleConfig.forEach((moduleName, providerConfig) -> { if (providerConfig.size() > 0) { log.info("Get a module define from application.yml, module name: {}", moduleName); - ApplicationConfiguration.ModuleConfiguration moduleConfiguration = configuration.addModule( - moduleName); + ApplicationConfiguration.ModuleConfiguration moduleConfiguration = configuration.addModule(moduleName); providerConfig.forEach((providerName, config) -> { - log.info( - "Get a provider define belong to {} module, provider name: {}", moduleName, - providerName - ); + log.info("Get a provider define belong to {} module, provider name: {}", moduleName, providerName); + final Map propertiesConfig = (Map) config; - final Properties properties = new Properties(); + final Properties properties = new Properties(); + if (propertiesConfig != null) { propertiesConfig.forEach((propertyName, propertyValue) -> { if (propertyValue instanceof Map) { @@ -91,6 +89,7 @@ private void loadConfig(ApplicationConfiguration configuration) throws ConfigFil } }); } + moduleConfiguration.addProviderConfiguration(providerName, properties); }); } else { @@ -103,10 +102,9 @@ private void loadConfig(ApplicationConfiguration configuration) throws ConfigFil } } - private void replacePropertyAndLog(final Object propertyName, final Object propertyValue, final Properties target, - final Object providerName) { - final String valueString = PropertyPlaceholderHelper.INSTANCE - .replacePlaceholders(propertyValue + "", target); + private void replacePropertyAndLog(final Object propertyName, final Object propertyValue, final Properties target, final Object providerName) { + final String valueString = PropertyPlaceholderHelper.INSTANCE.replacePlaceholders(propertyValue + "", target); + if (valueString != null) { if (valueString.trim().length() == 0) { target.replace(propertyName, valueString); @@ -136,16 +134,20 @@ private void overrideConfigBySystemEnv(ApplicationConfiguration configuration) { private void selectConfig(final Map> moduleConfiguration) { Iterator>> moduleIterator = moduleConfiguration.entrySet().iterator(); while (moduleIterator.hasNext()) { - Map.Entry> entry = moduleIterator.next(); - final String moduleName = entry.getKey(); - final Map providerConfig = entry.getValue(); + Map.Entry> entry = moduleIterator.next(); + + final String moduleName = entry.getKey(); + final Map providerConfig = entry.getValue(); + if (!providerConfig.containsKey(SELECTOR)) { continue; } + final String selector = (String) providerConfig.get(SELECTOR); final String resolvedSelector = PropertyPlaceholderHelper.INSTANCE.replacePlaceholders( selector, System.getProperties() ); + providerConfig.entrySet().removeIf(e -> !resolvedSelector.equals(e.getKey())); if (!providerConfig.isEmpty()) { @@ -171,27 +173,32 @@ private void overrideModuleSettings(ApplicationConfiguration configuration, Stri if (moduleAndConfigSeparator <= 0) { return; } - String moduleName = key.substring(0, moduleAndConfigSeparator); - String providerSettingSubKey = key.substring(moduleAndConfigSeparator + 1); - ApplicationConfiguration.ModuleConfiguration moduleConfiguration = configuration.getModuleConfiguration(moduleName); + String moduleName = key.substring(0, moduleAndConfigSeparator); + String providerSettingSubKey = key.substring(moduleAndConfigSeparator + 1); + + ApplicationConfiguration.ModuleConfiguration moduleConfiguration = configuration.getModuleConfiguration(moduleName); if (moduleConfiguration == null) { return; } + int providerAndConfigSeparator = providerSettingSubKey.indexOf('.'); if (providerAndConfigSeparator <= 0) { return; } + String providerName = providerSettingSubKey.substring(0, providerAndConfigSeparator); - String settingKey = providerSettingSubKey.substring(providerAndConfigSeparator + 1); + String settingKey = providerSettingSubKey.substring(providerAndConfigSeparator + 1); if (!moduleConfiguration.has(providerName)) { return; } + Properties providerSettings = moduleConfiguration.getProviderConfiguration(providerName); if (!providerSettings.containsKey(settingKey)) { return; } - Object originValue = providerSettings.get(settingKey); - Class type = originValue.getClass(); + + Object originValue = providerSettings.get(settingKey); + Class type = originValue.getClass(); if (type.equals(int.class) || type.equals(Integer.class)) providerSettings.put(settingKey, Integer.valueOf(value)); else if (type.equals(String.class)) @@ -204,8 +211,12 @@ else if (type.equals(boolean.class) || type.equals(Boolean.class)) { return; } - log.info("The setting has been override by key: {}, value: {}, in {} provider of {} module through {}", settingKey, - value, providerName, moduleName, "System.properties" + log.info("The setting has been override by key: {}, value: {}, in {} provider of {} module through {}", + settingKey, + value, + providerName, + moduleName, + "System.properties" ); } } diff --git a/iot-server/server-bootstrap/src/main/resources/application.yml b/iot-server/server-bootstrap/src/main/resources/application.yml index 4962fbe2..3d35cd90 100644 --- a/iot-server/server-bootstrap/src/main/resources/application.yml +++ b/iot-server/server-bootstrap/src/main/resources/application.yml @@ -1,4 +1,17 @@ -# 核心模块 +# Apache Camel Protocol Entry +camel-receiver: + selector: default + default: + version: v1.0.0 + +# Zabbix Trapper Sender +zabbix-sender: + selector: ${ZS_RECEIVER_ZABBIX_SENDER:default} + default: + port: ${ZS_RECEIVER_ZABBIX_PORT:10051} + host: ${ZS_RECEIVER_ZABBIX_HOST:127.0.0.1} + +# core module config core: selector: ${ZS_CORE:default} default: @@ -13,44 +26,42 @@ core: restAcceptQueueSize: ${ZS_CORE_REST_JETTY_QUEUE_SIZE:0} httpMaxRequestHeaderSize: ${ZS_CORE_HTTP_MAX_REQUEST_HEADER_SIZE:8192} -# 健康检查 +# local db h2, must be default +local-h2: + selector: default + default: + version: v1.0.0 + +# ndjson file read realtime +server-transfer: + selector: ${ZS_SERVER_TRANSFER:-} + default: + name: ${ZS_TRANSFER_NAME:zeus-transfer} + pattern: ${ZS_TRANSFER_PATTERN:/home/data/history-history-syncer-[0-9]{1}.ndjson} + fileMaxWait: ${ZS_TRANSFER_FILE_MAXWAIT:30} + +# tdengine storage realtime +storage: + selector: ${ZS_STORAGE:none} + none: + tdengine: + url: ${ZS_STORAGE_TDENGINE_URL:jdbc:TAOS://127.0.0.1:6030/zeus_data} # TDEngine jdbcUrl + user: ${ZS_STORAGE_TDENGINE_USER:root} + password: ${ZS_STORAGE_TDENGINE_PASSWORD:taosdata} + +# health check health-checker: selector: ${ZS_HEALTH_CHECKER:default} default: checkIntervalSeconds: ${ZS_HEALTH_CHECKER_INTERVAL_SECONDS:5} -# 健康遥测 +# health telemetry telemetry: selector: ${ZS_TELEMETRY:prometheus} none: prometheus: host: ${ZS_TELEMETRY_PROMETHEUS_HOST:0.0.0.0} - port: ${ZS_TELEMETRY_PROMETHEUS_PORT:1234} + port: ${ZS_TELEMETRY_PROMETHEUS_PORT:12900} sslEnabled: ${ZS_TELEMETRY_PROMETHEUS_SSL_ENABLED:false} sslKeyPath: ${ZS_TELEMETRY_PROMETHEUS_SSL_KEY_PATH:""} - sslCertChainPath: ${ZS_TELEMETRY_PROMETHEUS_SSL_CERT_CHAIN_PATH:""} - -# Zabbix Trapper Sender -zabbix-sender: - selector: ${ZS_RECEIVER_ZABBIX_SENDER:default} - default: - host: 172.16.3.72 - port: 10051 - -# Http Server -receiver-http: - selector: ${ZS_RECEIVER_HTTP:-} - default: - port: 9010 - -# TCP Server -receiver-tcp: - selector: ${ZS_RECEIVER_TCP:-} - default: - port: 9020 - -# MQTT Client -receiver-mqtt: - selector: ${ZS_RECEIVER_MQTT:-} - default: - port: 1883 \ No newline at end of file + sslCertChainPath: ${ZS_TELEMETRY_PROMETHEUS_SSL_CERT_CHAIN_PATH:""} \ No newline at end of file diff --git a/iot-server/server-bootstrap/src/main/resources/log4j2.xml b/iot-server/server-bootstrap/src/main/resources/log4j2.xml index f197f205..11749966 100644 --- a/iot-server/server-bootstrap/src/main/resources/log4j2.xml +++ b/iot-server/server-bootstrap/src/main/resources/log4j2.xml @@ -1,4 +1,4 @@ - + diff --git a/iot-server/server-camel-receiver/pom.xml b/iot-server/server-camel-receiver/pom.xml new file mode 100644 index 00000000..fa384fa5 --- /dev/null +++ b/iot-server/server-camel-receiver/pom.xml @@ -0,0 +1,79 @@ + + + + iot-server + com.zmops + 1.0-beta + + 4.0.0 + + server-camel-receiver + + 基于 CamelContext 的动态话配置服务模块 + + + com.zmops + library-module + 1.0.3-RELEASE + + + com.zmops + telemetry-api + 1.0-beta + + + com.zmops + server-sender + 1.0-beta + + + com.zmops + toolkit-datacarrier + 1.0.3-RELEASE + + + + org.apache.camel + camel-paho-mqtt5 + + + org.apache.camel + camel-netty-http + + + org.apache.camel + camel-pgevent + 3.11.4 + + + org.postgresql + postgresql + 42.2.20 + + + com.zmops + runtime-server + 1.0.3-RELEASE + + + com.zmops + zeus-commons + 1.0.3-RELEASE + compile + + + com.zmops + server-localdb + 1.0-beta + compile + + + + + 8 + 8 + + + \ No newline at end of file diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/Const.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/Const.java new file mode 100644 index 00000000..02a660ad --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/Const.java @@ -0,0 +1,8 @@ +package com.zmops.zeus.iot.server.receiver; + +public class Const { + + public static final String CAMEL_ZABBIX_COMPONENT_NAME = "Zabbix"; + + public static final String CAMEL_ARK_COMPONENT_NAME = "ArkBiz"; +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/ProtocolAction.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/ProtocolAction.java new file mode 100644 index 00000000..b4aaac53 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/ProtocolAction.java @@ -0,0 +1,9 @@ +package com.zmops.zeus.iot.server.receiver; + +/** + * 协议服务启停 + */ +public enum ProtocolAction { + + stop, start +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/ProtocolEnum.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/ProtocolEnum.java new file mode 100644 index 00000000..9218517f --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/ProtocolEnum.java @@ -0,0 +1,9 @@ +package com.zmops.zeus.iot.server.receiver; + +/** + * @author nantian created at 2021/10/24 13:47 + */ +public enum ProtocolEnum { + + HttpServer, MqttClient, TcpServer, UdpServer, CoapServer, WebSocketServer +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/ReceiverServerRoute.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/ReceiverServerRoute.java new file mode 100644 index 00000000..e2bb4c21 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/ReceiverServerRoute.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.server.receiver; + +import lombok.Setter; +import org.apache.camel.builder.RouteBuilder; + +import java.util.Map; + +/** + * @author nantian created at 2021/10/24 14:38 + */ +public abstract class ReceiverServerRoute extends RouteBuilder { + + @Setter + protected String routeId; + + @Setter + protected Map options; + + public ReceiverServerRoute(String routeId, Map options) { + this.routeId = routeId; + this.options = options; + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizComponent.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizComponent.java new file mode 100644 index 00000000..cf60a6dc --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizComponent.java @@ -0,0 +1,28 @@ +package com.zmops.zeus.iot.server.receiver.handler.ark; + +import com.zmops.zeus.server.library.module.ModuleManager; +import org.apache.camel.Endpoint; +import org.apache.camel.support.DefaultComponent; + +import java.util.Map; + +/** + * @author nantian created at 2021/12/2 22:35 + */ +public class ArkBizComponent extends DefaultComponent { + + private final ModuleManager moduleManager; + + public ArkBizComponent(ModuleManager moduleManager) { + this.moduleManager = moduleManager; + } + + @Override + protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { + + String uniqueId = getAndRemoveParameter(parameters, "uniqueId", String.class); + String methodName = getAndRemoveParameter(parameters, "methodName", String.class); + + return new ArkBizEndpoint(uri, this, moduleManager, uniqueId, methodName); + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizConsumer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizConsumer.java new file mode 100644 index 00000000..a81401ea --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizConsumer.java @@ -0,0 +1,15 @@ +package com.zmops.zeus.iot.server.receiver.handler.ark; + +import org.apache.camel.Endpoint; +import org.apache.camel.Processor; +import org.apache.camel.support.DefaultConsumer; + +/** + * @author nantian created at 2021/12/2 22:35 + */ +public class ArkBizConsumer extends DefaultConsumer { + + public ArkBizConsumer(Endpoint endpoint, Processor processor) { + super(endpoint, processor); + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizEndpoint.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizEndpoint.java new file mode 100644 index 00000000..a7dac2db --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizEndpoint.java @@ -0,0 +1,43 @@ +package com.zmops.zeus.iot.server.receiver.handler.ark; + +import com.zmops.zeus.server.library.module.ModuleManager; +import org.apache.camel.Component; +import org.apache.camel.Consumer; +import org.apache.camel.Processor; +import org.apache.camel.Producer; + + +import org.apache.camel.support.DefaultEndpoint; + +/** + * @author nantian created at 2021/12/2 22:34 + */ +@SuppressWarnings("all") +public class ArkBizEndpoint extends DefaultEndpoint { + + private final ModuleManager moduleManager; + private final ArkBizProducer producer; + + public ArkBizEndpoint(String endpointUri, Component component, ModuleManager moduleManager, + String uniqueId, String methodName) { + super(endpointUri, component); + this.moduleManager = moduleManager; + this.producer = new ArkBizProducer(this, moduleManager, uniqueId, methodName); + } + + + @Override + public Producer createProducer() throws Exception { + return this.producer; + } + + @Override + public Consumer createConsumer(Processor processor) throws Exception { + return new ArkBizConsumer(this, processor); + } + + @Override + public boolean isSingleton() { + return false; + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java new file mode 100644 index 00000000..6d38188f --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/ark/ArkBizProducer.java @@ -0,0 +1,50 @@ +package com.zmops.zeus.iot.server.receiver.handler.ark; + +import com.zmops.zeus.dto.DataMessage; +import com.zmops.zeus.dto.ItemValue; +import com.zmops.zeus.facade.DynamicProcotol; +import com.zmops.zeus.iot.server.receiver.module.CamelReceiverModule; +import com.zmops.zeus.iot.server.receiver.service.ReferenceClientService; +import com.zmops.zeus.server.library.module.ModuleManager; +import org.apache.camel.Endpoint; +import org.apache.camel.Exchange; +import org.apache.camel.support.DefaultProducer; + +import java.util.Collections; +import java.util.List; + +/** + * @author nantian created at 2021/12/2 22:35 + */ +@SuppressWarnings("all") +public class ArkBizProducer extends DefaultProducer { + + private final ModuleManager moduleManager; + + private final DynamicProcotol dynamicProcotol; + + public ArkBizProducer(Endpoint endpoint, ModuleManager moduleManager, String uniqueId, String methodName) { + super(endpoint); + this.moduleManager = moduleManager; + + ReferenceClientService referenceClientService = moduleManager.find(CamelReceiverModule.NAME) + .provider().getService(ReferenceClientService.class); + dynamicProcotol = referenceClientService.getDynamicProtocolClient(uniqueId); + } + + @Override + public void process(Exchange exchange) throws Exception { + + DataMessage message = new DataMessage(); + message.setBody(exchange.getMessage().getBody()); + message.setHeaders(exchange.getMessage().getHeaders()); + + List itemValueList = dynamicProcotol.protocolHandler(message); + + if (itemValueList == null) { + itemValueList = Collections.emptyList(); + } + + exchange.getIn().setBody(itemValueList); + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/IoTDeviceValue.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/IoTDeviceValue.java new file mode 100644 index 00000000..42c8b951 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/IoTDeviceValue.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.server.receiver.handler.zabbix; + +import lombok.Getter; +import lombok.Setter; + +import java.util.Map; + +/** + * @author nantian created at 2021/8/23 18:01 + *

+ * 方便大家理解,转换一下 命名 + */ + +@Getter +@Setter +public class IoTDeviceValue { + + private String deviceId; // 设备ID + + private Map attributes; // key : value + + private Long clock; // 毫秒,70年到现在时间戳 +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderComponent.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderComponent.java similarity index 80% rename from iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderComponent.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderComponent.java index 667cf445..dd00c429 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderComponent.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderComponent.java @@ -1,8 +1,8 @@ -package com.zmops.zeus.iot.server.core.camel; +package com.zmops.zeus.iot.server.receiver.handler.zabbix; -import com.zmops.zeus.iot.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.module.ModuleManager; import org.apache.camel.Endpoint; -import org.apache.camel.impl.DefaultComponent; +import org.apache.camel.support.DefaultComponent; import java.util.Map; diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderConsumer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderConsumer.java similarity index 73% rename from iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderConsumer.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderConsumer.java index 9886d1d1..0b81da8a 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderConsumer.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderConsumer.java @@ -1,8 +1,8 @@ -package com.zmops.zeus.iot.server.core.camel; +package com.zmops.zeus.iot.server.receiver.handler.zabbix; import org.apache.camel.Endpoint; import org.apache.camel.Processor; -import org.apache.camel.impl.DefaultConsumer; +import org.apache.camel.support.DefaultConsumer; /** * @author nantian created at 2021/8/16 22:47 diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderEndpoint.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderEndpoint.java similarity index 63% rename from iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderEndpoint.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderEndpoint.java index 8457da64..0704329e 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixSenderEndpoint.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixSenderEndpoint.java @@ -1,11 +1,11 @@ -package com.zmops.zeus.iot.server.core.camel; +package com.zmops.zeus.iot.server.receiver.handler.zabbix; -import com.zmops.zeus.iot.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.module.ModuleManager; import org.apache.camel.Component; import org.apache.camel.Consumer; import org.apache.camel.Processor; import org.apache.camel.Producer; -import org.apache.camel.impl.DefaultEndpoint; +import org.apache.camel.support.DefaultEndpoint; /** * @author nantian created at 2021/8/16 22:45 @@ -13,20 +13,22 @@ public class ZabbixSenderEndpoint extends DefaultEndpoint { private final ModuleManager moduleManager; + private final ZabbixTrapperProducer producer; public ZabbixSenderEndpoint(String endpointUri, Component component, ModuleManager moduleManager) { super(endpointUri, component); this.moduleManager = moduleManager; + this.producer = new ZabbixTrapperProducer(this, moduleManager); } @Override public Producer createProducer() throws Exception { - return new ZabbixTrapperProducer(this, moduleManager); + return producer; // 每次 process 都会创建一个对象, 单例返回 } @Override public Consumer createConsumer(Processor processor) throws Exception { - return new ZabbixSenderConsumer(this, processor); + return new ZabbixSenderConsumer(this, processor); //TODO } @Override diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapper.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapper.java new file mode 100644 index 00000000..ad45c766 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapper.java @@ -0,0 +1,27 @@ +package com.zmops.zeus.iot.server.receiver.handler.zabbix; + +import com.zmops.zeus.dto.ItemValue; +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author nantian created at 2021/8/23 16:49 + */ +public class ZabbixTrapper { + + + @Getter + private final String request = "sender data"; + + @Setter + @Getter + private List data; + + public ZabbixTrapper(List itemValues) { + data = new ArrayList<>(); + data.addAll(itemValues); + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapperProducer.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapperProducer.java new file mode 100644 index 00000000..a50cf01f --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/ZabbixTrapperProducer.java @@ -0,0 +1,67 @@ +package com.zmops.zeus.iot.server.receiver.handler.zabbix; + +import com.google.gson.Gson; +import com.zmops.zeus.dto.ItemValue; +import com.zmops.zeus.iot.server.receiver.handler.zabbix.worker.ItemDataTransferWorker; +import com.zmops.zeus.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.util.StringUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.camel.Endpoint; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.support.DefaultProducer; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @author nantian created at 2021/8/16 22:48 + *

+ * to("Zabbix") + */ +@Slf4j +public class ZabbixTrapperProducer extends DefaultProducer { + + private final ModuleManager moduleManager; + private final ItemDataTransferWorker itemDataTransferWorker; + private final ExecutorService itemValueThread = Executors.newFixedThreadPool(20); + + + public ZabbixTrapperProducer(Endpoint endpoint, ModuleManager moduleManager) { + super(endpoint); + this.moduleManager = moduleManager; + this.itemDataTransferWorker = new ItemDataTransferWorker(moduleManager); + } + + /** + * Body 必须是 ItemValue + * + * @param exchange Exchange + */ + @Override + public void process(Exchange exchange) { + Message message = exchange.getIn(); + + if (message.getBody() == null && !(message.getBody() instanceof List)) { + return; + } + + List values = (List) message.getBody(); + + for (ItemValue itemValue : values) { + if (StringUtil.isEmpty(itemValue.getHost()) + || StringUtil.isEmpty(itemValue.getKey()) + || StringUtil.isEmpty(itemValue.getValue())) { + log.error(" process item data error,{}", new Gson().toJson(itemValue)); + continue; + } + + itemValueThread.submit(() -> { + itemDataTransferWorker.in(itemValue); + }); + } + + exchange.getMessage().setBody("{\"success\":\"true\"}"); + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/process/JsonToItemValueProcess.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/process/JsonToItemValueProcess.java new file mode 100644 index 00000000..74721dcd --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/process/JsonToItemValueProcess.java @@ -0,0 +1,63 @@ +package com.zmops.zeus.iot.server.receiver.handler.zabbix.process; + +import com.google.gson.Gson; +import com.zmops.zeus.dto.ItemValue; +import com.zmops.zeus.iot.server.receiver.handler.zabbix.IoTDeviceValue; +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.camel.Processor; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +/** + * @author nantian created at 2021/8/23 17:16 + *

+ * Json 转 对象,进队列,一定要转成 ItemValue 对象,{@link ItemValue} + */ +public class JsonToItemValueProcess implements Processor { + + private final Gson gson = new Gson(); + + @Override + public void process(Exchange exchange) throws Exception { + Message message = exchange.getIn(); + InputStream bodyStream = (InputStream) message.getBody(); + String inputContext = this.analysisMessage(bodyStream); + + + IoTDeviceValue iotValue = gson.fromJson(inputContext, IoTDeviceValue.class); + + List itemValueList = new ArrayList<>(); + + iotValue.getAttributes().forEach((key, value) -> { + ItemValue item = new ItemValue(iotValue.getDeviceId(), iotValue.getClock()); + item.setKey(key); + item.setValue(value); + + itemValueList.add(item); + }); + + exchange.getMessage().setBody(itemValueList); + } + + + private String analysisMessage(InputStream bodyStream) throws IOException { + ByteArrayOutputStream outStream = new ByteArrayOutputStream(); + byte[] contextBytes = new byte[4096]; + int realLen; + while ((realLen = bodyStream.read(contextBytes, 0, 4096)) != -1) { + outStream.write(contextBytes, 0, realLen); + } + + // 返回从Stream中读取的字串 + try { + return outStream.toString("UTF-8"); + } finally { + outStream.close(); + } + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/AbstractWorker.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/AbstractWorker.java new file mode 100644 index 00000000..885d831f --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/AbstractWorker.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.zmops.zeus.iot.server.receiver.handler.zabbix.worker; + +import com.zmops.zeus.server.library.module.ModuleDefineHolder; +import lombok.Getter; + + +/** + * Abstract worker definition. Provide the {@link ModuleDefineHolder} to make sure the worker could find and access + * services in different modules. Also, {@link #in(Object)} is provided as the primary entrance of every worker. + *

+ * + * @param the datatype this worker implementation processes. + * @editor nantian + * 数据从协议入口 发送到 zabbix 过程中的队列,to("zabbix") + */ +public abstract class AbstractWorker { + + @Getter + private final ModuleDefineHolder moduleDefineHolder; + + public AbstractWorker(ModuleDefineHolder moduleDefineHolder) { + this.moduleDefineHolder = moduleDefineHolder; + } + + /** + * Main entrance of this worker. + */ + public abstract void in(INPUT input); +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/ItemDataTransferWorker.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/ItemDataTransferWorker.java new file mode 100644 index 00000000..4f7f1a35 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/ItemDataTransferWorker.java @@ -0,0 +1,141 @@ +package com.zmops.zeus.iot.server.receiver.handler.zabbix.worker; + +import com.google.gson.Gson; +import com.zmops.zeus.dto.ItemValue; +import com.zmops.zeus.iot.server.receiver.handler.zabbix.ZabbixTrapper; +import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; +import com.zmops.zeus.iot.server.sender.service.ZabbixSenderService; +import com.zmops.zeus.iot.server.telemetry.TelemetryModule; +import com.zmops.zeus.iot.server.telemetry.api.CounterMetrics; +import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; +import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import com.zmops.zeus.server.datacarrier.DataCarrier; +import com.zmops.zeus.server.datacarrier.consumer.BulkConsumePool; +import com.zmops.zeus.server.datacarrier.consumer.ConsumerPoolFactory; +import com.zmops.zeus.server.datacarrier.consumer.IConsumer; +import com.zmops.zeus.server.library.module.ModuleManager; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author nantian created at 2021/8/23 15:11 + *

+ * 数据发送队列 + */ +@Slf4j +public class ItemDataTransferWorker extends TransferWorker { + + + private final DataCarrier dataCarrier; + private final CounterMetrics iotDataTransferCounter; + private final Gson gson = new Gson(); + + public ItemDataTransferWorker(ModuleManager moduleManager) { + super(moduleManager); + + String name = "ITEMVALUE_TRANSFER_TUNNEL"; + + int size = BulkConsumePool.Creator.recommendMaxSize() / 8; + if (size == 0) { + size = 1; + } + BulkConsumePool.Creator creator = new BulkConsumePool.Creator(name, size, 20); + try { + ConsumerPoolFactory.INSTANCE.createIfAbsent(name, creator); + } catch (Exception e) { + e.printStackTrace(); + } + + this.dataCarrier = new DataCarrier<>("ZABBIX_SENDER", name, 4, 2000); + this.dataCarrier.consume(ConsumerPoolFactory.INSTANCE.get(name), new SenderConsumer()); + + // #### 发送数量 指标采集 + MetricsCreator metricsCreator = moduleManager.find(TelemetryModule.NAME) + .provider() + .getService(MetricsCreator.class); + + iotDataTransferCounter = metricsCreator.createCounter( + "transfer_data_count", "The count number of iot device data in transfer", + new MetricsTag.Keys("name"), + new MetricsTag.Values("transfer_data_count") + ); + } + + + @Override + public void in(ItemValue itemValue) { + iotDataTransferCounter.inc(); + dataCarrier.produce(itemValue); + } + + @Override + public void prepareBatch(Collection lastCollection) { + long start = System.currentTimeMillis(); + if (lastCollection.size() == 0) { + return; + } + + int maxBatchGetSize = 500; + final int batchSize = Math.min(maxBatchGetSize, lastCollection.size()); + List valueList = new ArrayList<>(); + + for (ItemValue data : lastCollection) { + valueList.add(data); + if (valueList.size() == batchSize) { + batchSenderDataToZabbix(valueList); + } + } + + if (valueList.size() > 0) { + batchSenderDataToZabbix(valueList); + } + + log.debug("batch sender data size:{}, took time: {}", lastCollection.size(), System.currentTimeMillis() - start); + } + + + private void batchSenderDataToZabbix(List valueList) { + ZabbixTrapper zabbixTrapper = new ZabbixTrapper(valueList); + + ZabbixSenderService senderService = getModuleDefineHolder() + .find(ZabbixSenderModule.NAME).provider().getService(ZabbixSenderService.class); + + try { + String sendResult = senderService.sendData(gson.toJson(zabbixTrapper)); + log.debug(sendResult); + } catch (IOException e) { + log.error(" itemvalue data sender error,msg :{}", e.getMessage()); + e.printStackTrace(); + } finally { + valueList.clear(); + } + } + + + private class SenderConsumer implements IConsumer { + @Override + public void init() { + + } + + @Override + public void consume(List data) { + ItemDataTransferWorker.this.onWork(data); + } + + @Override + public void onError(List data, Throwable t) { + log.error(t.getMessage(), t); + } + + @Override + public void onExit() { + } + } + + +} diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixProtocolType.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/TransferWorker.java similarity index 55% rename from iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixProtocolType.java rename to iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/TransferWorker.java index e16e2aca..ba7e2cd2 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixProtocolType.java +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/handler/zabbix/worker/TransferWorker.java @@ -16,36 +16,32 @@ * */ -package com.zmops.zeus.iot.server.sender.provider.protocol.bean; +package com.zmops.zeus.iot.server.receiver.handler.zabbix.worker; -import lombok.Getter; -import java.util.Objects; +import com.zmops.zeus.dto.Item; +import com.zmops.zeus.server.library.module.ModuleDefineHolder; +import lombok.extern.slf4j.Slf4j; + +import java.util.Collection; +import java.util.List; /** - * Zabbix protocol type + * 1. 协议入口 -> zabbix trapper item + * + * @param The type of worker input. */ -@Getter -public enum ZabbixProtocolType { - ACTIVE_CHECKS("active checks"), - AGENT_DATA("agent data"), - SENDER_DATA("sender data"); - - private final String name; +@Slf4j +public abstract class TransferWorker extends AbstractWorker { - ZabbixProtocolType(String name) { - this.name = name; + TransferWorker(ModuleDefineHolder moduleDefineHolder) { + super(moduleDefineHolder); } - /** - * Parse type by name - */ - public static ZabbixProtocolType parse(String name) { - for (ZabbixProtocolType type : ZabbixProtocolType.values()) { - if (Objects.equals(type.name, name)) { - return type; - } - } - return null; + void onWork(List input) { + prepareBatch(input); } -} \ No newline at end of file + + public abstract void prepareBatch(Collection lastCollection); + +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/module/CamelReceiverModule.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/module/CamelReceiverModule.java new file mode 100644 index 00000000..d13d0359 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/module/CamelReceiverModule.java @@ -0,0 +1,30 @@ +package com.zmops.zeus.iot.server.receiver.module; + +import com.zmops.zeus.iot.server.receiver.service.CamelContextHolderService; +import com.zmops.zeus.iot.server.receiver.service.ReferenceClientService; +import com.zmops.zeus.server.library.module.ModuleDefine; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author nantian created at 2021/10/23 20:59 + *

+ * 通信服务模块,Apache Camel 统一接入 + */ +public class CamelReceiverModule extends ModuleDefine { + + public static final String NAME = "camel-receiver"; + + public CamelReceiverModule() { + super(NAME); + } + + @Override + public Class[] services() { + List> classes = new ArrayList<>(); + classes.add(CamelContextHolderService.class); + classes.add(ReferenceClientService.class); + return classes.toArray(new Class[]{}); + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverConfig.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverConfig.java new file mode 100644 index 00000000..29616403 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverConfig.java @@ -0,0 +1,16 @@ +package com.zmops.zeus.iot.server.receiver.provider; + +import com.zmops.zeus.server.library.module.ModuleConfig; +import lombok.Getter; +import lombok.Setter; + +/** + * @author nantian created at 2021/10/23 21:25 + */ + +@Getter +@Setter +public class CamelReceiverConfig extends ModuleConfig { + + private String version; +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java new file mode 100644 index 00000000..97dbd58f --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/provider/CamelReceiverProvider.java @@ -0,0 +1,84 @@ +package com.zmops.zeus.iot.server.receiver.provider; + +import com.zmops.zeus.iot.server.receiver.Const; +import com.zmops.zeus.iot.server.receiver.handler.ark.ArkBizComponent; +import com.zmops.zeus.iot.server.receiver.handler.zabbix.ZabbixSenderComponent; +import com.zmops.zeus.iot.server.receiver.module.CamelReceiverModule; +import com.zmops.zeus.iot.server.receiver.service.CamelContextHolderService; +import com.zmops.zeus.iot.server.receiver.service.ReferenceClientService; +import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; +import com.zmops.zeus.server.library.module.*; +import com.zmops.zeus.server.runtime.SofaStarter; +import com.zmops.zeus.server.runtime.api.client.ReferenceClient; +import org.apache.camel.ExtendedCamelContext; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.impl.engine.PooledExchangeFactory; +import org.apache.camel.model.ModelCamelContext; + +/** + * @author nantian created at 2021/10/23 21:24 + */ +public class CamelReceiverProvider extends ModuleProvider { + + private final CamelReceiverConfig camelReceiverConfig; + + private ModelCamelContext camelContext; + + private ReferenceClient referenceClient; + + public CamelReceiverProvider() { + this.camelReceiverConfig = new CamelReceiverConfig(); + } + + @Override + public String name() { + return "default"; + } + + @Override + public Class module() { + return CamelReceiverModule.class; + } + + @Override + public ModuleConfig createConfigBeanIfAbsent() { + return camelReceiverConfig; + } + + @Override + public void prepare() throws ServiceNotProvidedException, ModuleStartException { + camelContext = new DefaultCamelContext(); // master 只有一个 CamelContext + camelContext.disableJMX(); + camelContext.setTracing(true); + camelContext.adapt(ExtendedCamelContext.class).setExchangeFactory(new PooledExchangeFactory()); + + // biz-ark JVM 通信客户端 + SofaStarter sofaStarter = new SofaStarter(); + this.referenceClient = sofaStarter.getSofaRuntimeContext().getClientFactory().getClient(ReferenceClient.class); + + this.registerServiceImplementation(CamelContextHolderService.class, new CamelContextHolderService(camelContext, getManager())); + this.registerServiceImplementation(ReferenceClientService.class, new ReferenceClientService(referenceClient, getManager())); + } + + @Override + public void start() throws ServiceNotProvidedException, ModuleStartException { + camelContext.addComponent(Const.CAMEL_ZABBIX_COMPONENT_NAME, new ZabbixSenderComponent(getManager())); + camelContext.addComponent(Const.CAMEL_ARK_COMPONENT_NAME, new ArkBizComponent(getManager())); + } + + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { + try { + camelContext.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public String[] requiredModules() { + return new String[]{ + ZabbixSenderModule.NAME + }; + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/CoapServerRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/CoapServerRouteBuilder.java new file mode 100644 index 00000000..48122864 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/CoapServerRouteBuilder.java @@ -0,0 +1,20 @@ +package com.zmops.zeus.iot.server.receiver.routes; + +import com.zmops.zeus.iot.server.receiver.ReceiverServerRoute; + +import java.util.Map; + +/** + * @author nantian created at 2021/10/24 14:23 + */ +public class CoapServerRouteBuilder extends ReceiverServerRoute { + + public CoapServerRouteBuilder(String routeId, Map options) { + super(routeId, options); + } + + @Override + public void configure() throws Exception { + + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/HttpRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/HttpRouteBuilder.java new file mode 100644 index 00000000..05e8168a --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/HttpRouteBuilder.java @@ -0,0 +1,29 @@ +package com.zmops.zeus.iot.server.receiver.routes; + +import com.zmops.zeus.iot.server.receiver.ReceiverServerRoute; +import lombok.extern.slf4j.Slf4j; +import org.apache.camel.LoggingLevel; + +import java.util.Map; + +/** + * @author nantian created at 2021/10/23 23:25 + */ + +@Slf4j +public class HttpRouteBuilder extends ReceiverServerRoute { + + public HttpRouteBuilder(String routeId, Map option) { + super(routeId, option); + log.info("Http Route Created ====> ip : {},port : {}", option.get("hostIp"), option.get("port")); + } + + @Override + public void configure() throws Exception { + fromF("netty4-http:http://0.0.0.0:%s/data?sync=true", options.get("port")) + .routeId(routeId) + .log(LoggingLevel.DEBUG, log, ">>> Message received from Netty4 Http Server : ${body}"); + } + + +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttBrokerRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttBrokerRouteBuilder.java new file mode 100644 index 00000000..c91d72cd --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttBrokerRouteBuilder.java @@ -0,0 +1,20 @@ +package com.zmops.zeus.iot.server.receiver.routes; + +import com.zmops.zeus.iot.server.receiver.ReceiverServerRoute; + +import java.util.Map; + +/** + * @author nantian created at 2021/11/26 13:54 + */ +public class MqttBrokerRouteBuilder extends ReceiverServerRoute { + + public MqttBrokerRouteBuilder(String routeId, Map options) { + super(routeId, options); + } + + @Override + public void configure() throws Exception { + + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java new file mode 100644 index 00000000..db9a3929 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/MqttClientRouteBuilder.java @@ -0,0 +1,79 @@ +package com.zmops.zeus.iot.server.receiver.routes; + +import com.zmops.zeus.iot.server.h2.module.LocalH2Module; +import com.zmops.zeus.iot.server.h2.service.InsertDAO; +import com.zmops.zeus.iot.server.receiver.ReceiverServerRoute; +import com.zmops.zeus.server.library.module.ModuleManager; +import org.apache.camel.Exchange; +import org.apache.camel.LoggingLevel; +import org.apache.camel.Message; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/10/24 0:11 + *

+ * mqtt client + */ +public class MqttClientRouteBuilder extends ReceiverServerRoute { + + public MqttClientRouteBuilder(String routeId, Map options) { + super(routeId, options); + } + + @Override + public void configure() throws Exception { + fromF("paho-mqtt5:%s?brokerUrl=tcp://%s:%s", options.get("topicNames"), options.get("hostIp"), options.get("port")) + .routeId(routeId) + .log(LoggingLevel.DEBUG, log, ">>> Message received from Mqtt Client : \n${body}") + .dynamicRouter(method(RouteJudge.class, "slip")).to("Zabbix:mqtt"); + } + + + static class RouteJudge { + public static String slip(Exchange exchange) { + Message message = exchange.getMessage(); + + if (message.getBody() instanceof List) { + return null; + } + + String topicName = exchange.getIn().getHeader("CamelMqttTopic").toString(); + InsertDAO localH2InsertDAO = ModuleManager.getInstance() + .find(LocalH2Module.NAME).provider().getService(InsertDAO.class); + //TODO 这里需要动态加载规则 + ResultSet rs = localH2InsertDAO.queryRes("select pm.topic,pc.unique_id from protocol_gateway_mqtt pm left join protocol_component pc on pc.id=pm.protocol_component_id"); + Map map = new HashMap<>(); + while (true) { + try { + if (!rs.next()) { + break; + } + + map.put(rs.getString(1), rs.getString(2)); + + } catch (SQLException e) { + e.printStackTrace(); + } + } + if (map.containsKey(topicName)) { + return "ArkBiz:mqtt?uniqueId=" + map.get(topicName); + } + +// if ("zeus11".equals(topicName)) { +// return "ArkBiz:mqtt?uniqueId=19890918"; +// } +// +// if ("zeus22".equals(topicName)) { +// return "ArkBiz:mqtt?uniqueId=20211225"; +// } + + return null; + } + + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/TcpServerRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/TcpServerRouteBuilder.java new file mode 100644 index 00000000..3cf48a6f --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/TcpServerRouteBuilder.java @@ -0,0 +1,20 @@ +package com.zmops.zeus.iot.server.receiver.routes; + +import com.zmops.zeus.iot.server.receiver.ReceiverServerRoute; + +import java.util.Map; + +/** + * @author nantian created at 2021/10/24 0:11 + */ +public class TcpServerRouteBuilder extends ReceiverServerRoute { + + public TcpServerRouteBuilder(String routeId, Map options) { + super(routeId, options); + } + + @Override + public void configure() throws Exception { + + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/UdpServerRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/UdpServerRouteBuilder.java new file mode 100644 index 00000000..528e8eb2 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/UdpServerRouteBuilder.java @@ -0,0 +1,20 @@ +package com.zmops.zeus.iot.server.receiver.routes; + +import com.zmops.zeus.iot.server.receiver.ReceiverServerRoute; + +import java.util.Map; + +/** + * @author nantian created at 2021/10/24 0:12 + */ +public class UdpServerRouteBuilder extends ReceiverServerRoute { + + public UdpServerRouteBuilder(String routeId, Map options) { + super(routeId, options); + } + + @Override + public void configure() throws Exception { + + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/WebSocketServerRouteBuilder.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/WebSocketServerRouteBuilder.java new file mode 100644 index 00000000..ca08d357 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/routes/WebSocketServerRouteBuilder.java @@ -0,0 +1,20 @@ +package com.zmops.zeus.iot.server.receiver.routes; + +import com.zmops.zeus.iot.server.receiver.ReceiverServerRoute; + +import java.util.Map; + +/** + * @author nantian created at 2021/10/24 14:23 + */ +public class WebSocketServerRouteBuilder extends ReceiverServerRoute { + + public WebSocketServerRouteBuilder(String routeId, Map options) { + super(routeId, options); + } + + @Override + public void configure() throws Exception { + + } +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java new file mode 100644 index 00000000..49a86081 --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/CamelContextHolderService.java @@ -0,0 +1,77 @@ +package com.zmops.zeus.iot.server.receiver.service; + +import com.zmops.zeus.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.module.Service; +import lombok.extern.slf4j.Slf4j; +import org.apache.camel.CamelContext; +import org.apache.camel.Route; +import org.apache.camel.RoutesBuilder; + +/** + * @author nantian created at 2021/8/17 0:24 + *

+ * CamelContextHolderService ,便于模块服务调用,全局只有一个 Camel 上下文 + */ +@Slf4j +public class CamelContextHolderService implements Service { + + private final CamelContext camelContext; + private final ModuleManager moduleManager; + + public CamelContextHolderService(CamelContext camelContext, ModuleManager moduleManager) { + this.camelContext = camelContext; + this.moduleManager = moduleManager; + } + + /** + * 配置路由 + * + * @param builder 路由 + */ + public void addRoutes(RoutesBuilder builder) { + try { + camelContext.addRoutes(builder); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * 关闭路由 + * + * @param routeId 路由ID + */ + public void routeShutDown(String routeId) { + + Route route = camelContext.getRoute(routeId); + if (route == null) { + return; + } + + try { + camelContext.getRouteController().stopRoute(routeId); + camelContext.removeRoute(routeId); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * 启动路由 + * + * @param routeId 路由ID + */ + public void routeStartUp(String routeId) { + Route route = camelContext.getRoute(routeId); + try { + route.getEndpoint().start(); + route.getConsumer().start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + +} diff --git a/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/ReferenceClientService.java b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/ReferenceClientService.java new file mode 100644 index 00000000..325f51bc --- /dev/null +++ b/iot-server/server-camel-receiver/src/main/java/com/zmops/zeus/iot/server/receiver/service/ReferenceClientService.java @@ -0,0 +1,57 @@ +package com.zmops.zeus.iot.server.receiver.service; + +import com.zmops.zeus.facade.DynamicProcotol; +import com.zmops.zeus.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.module.Service; +import com.zmops.zeus.server.runtime.api.client.ReferenceClient; +import com.zmops.zeus.server.runtime.api.client.param.ReferenceParam; + +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author nantian created at 2021/12/21 15:20 + *

+ * 动态协议代理 + */ +public class ReferenceClientService implements Service { + + private final ReferenceClient referenceClient; + private final ModuleManager moduleManager; + + // 缓存调用 客户端 + private static final ConcurrentHashMap dynamicProtoMap = new ConcurrentHashMap<>(); + + public ReferenceClientService(ReferenceClient client, ModuleManager moduleManager) { + this.referenceClient = client; + this.moduleManager = moduleManager; + } + + + public ReferenceClient getReferenceClient() { + return referenceClient; + } + + + /** + * 根据服务ID,动态获取代理客户端 + * + * @param serviceId - + * @return DynamicProcotol + */ + public DynamicProcotol getDynamicProtocolClient(String serviceId) { + + DynamicProcotol client = dynamicProtoMap.get(serviceId); + if (client != null) { + return client; + } + + ReferenceParam referenceParam = new ReferenceParam<>(); + referenceParam.setInterfaceType(DynamicProcotol.class); + referenceParam.setUniqueId(serviceId); + + DynamicProcotol client2 = referenceClient.reference(referenceParam); + dynamicProtoMap.put(serviceId, client2); + + return client2; + } +} diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine similarity index 92% rename from iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine index a0628d9a..cd693e09 100644 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine +++ b/iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine @@ -16,4 +16,4 @@ # # -com.zmops.zeus.iot.server.receiver.tcp.module.TcpReceiverModule +com.zmops.zeus.iot.server.receiver.module.CamelReceiverModule diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 92% rename from iot-server/server-receiver-plugin/http-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider index 3bf15d97..76011bd9 100644 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine +++ b/iot-server/server-camel-receiver/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider @@ -16,4 +16,4 @@ # # -com.zmops.zeus.iot.server.receiver.http.module.HttpReceiverModule +com.zmops.zeus.iot.server.receiver.provider.CamelReceiverProvider diff --git a/iot-server/server-library/library-module/pom.xml b/iot-server/server-client/pom.xml similarity index 71% rename from iot-server/server-library/library-module/pom.xml rename to iot-server/server-client/pom.xml index 04d87d24..dfd4401d 100644 --- a/iot-server/server-library/library-module/pom.xml +++ b/iot-server/server-client/pom.xml @@ -3,27 +3,30 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - server-library + iot-server com.zmops 1.0-beta 4.0.0 - jar + server-client + + + 8 + 8 + - library-module com.zmops library-util - ${project.version} - compile + 1.0.3-RELEASE + + + com.zaxxer + HikariCP + 3.1.0 - - 8 - 8 - - \ No newline at end of file diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/BufferStrategy.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/Client.java similarity index 82% rename from iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/BufferStrategy.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/Client.java index 37b775f4..60d0f920 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/BufferStrategy.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/Client.java @@ -16,8 +16,13 @@ * */ -package com.zmops.zeus.iot.server.datacarrier.buffer; +package com.zmops.zeus.iot.server.client; -public enum BufferStrategy { - BLOCKING, IF_POSSIBLE +import java.io.IOException; + +public interface Client { + + void connect() throws Exception; + + void shutdown() throws IOException; } diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleStartException.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/ClientException.java similarity index 79% rename from iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleStartException.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/ClientException.java index 7d068a0c..f9a93279 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleStartException.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/ClientException.java @@ -16,14 +16,14 @@ * */ -package com.zmops.zeus.iot.server.library.module; +package com.zmops.zeus.iot.server.client; -public class ModuleStartException extends Exception { - public ModuleStartException(String message) { +public abstract class ClientException extends Exception { + public ClientException(String message) { super(message); } - public ModuleStartException(String message, Throwable cause) { + public ClientException(String message, Throwable cause) { super(message, cause); } } diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyDefaultHandler.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/healthcheck/DelegatedHealthChecker.java similarity index 51% rename from iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyDefaultHandler.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/healthcheck/DelegatedHealthChecker.java index ae9a3d3d..7f889116 100644 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyDefaultHandler.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/healthcheck/DelegatedHealthChecker.java @@ -16,20 +16,34 @@ * */ -package com.zmops.zeus.iot.server.library.server.jetty; +package com.zmops.zeus.iot.server.client.healthcheck; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -public class JettyDefaultHandler extends JettyHandler { +import com.zmops.zeus.server.library.util.HealthChecker; + +import java.util.Optional; +import java.util.concurrent.atomic.AtomicReference; + +public class DelegatedHealthChecker implements HealthChecker { + + private final AtomicReference delegated = new AtomicReference<>(); + @Override - public String pathSpec() { - return "/"; + public void health() { + Optional.ofNullable(delegated.get()).ifPresent(HealthChecker::health); } @Override - protected final void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { - resp.sendError(HttpServletResponse.SC_NOT_FOUND); + public void unHealth(Throwable t) { + Optional.ofNullable(delegated.get()).ifPresent(d -> d.unHealth(t)); + } + + @Override + public void unHealth(String reason) { + Optional.ofNullable(delegated.get()).ifPresent(d -> d.unHealth(reason)); + } + + public void register(HealthChecker healthChecker) { + delegated.set(healthChecker); } } diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/IDataPartitioner.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/healthcheck/HealthCheckable.java similarity index 66% rename from iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/IDataPartitioner.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/healthcheck/HealthCheckable.java index 1dfe31c5..651a5134 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/IDataPartitioner.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/healthcheck/HealthCheckable.java @@ -16,19 +16,19 @@ * */ -package com.zmops.zeus.iot.server.datacarrier.partition; +package com.zmops.zeus.iot.server.client.healthcheck; +import com.zmops.zeus.server.library.util.HealthChecker; -import com.zmops.zeus.iot.server.datacarrier.buffer.BufferStrategy; - -public interface IDataPartitioner { - - int partition(int total, T data); +/** + * HealthCheckable indicate the client has the capacity of health check and need to register healthChecker. + */ +public interface HealthCheckable { /** - * @return an integer represents how many times should retry when {@link BufferStrategy#IF_POSSIBLE}. - *

- * Less or equal 1, means not support retry. + * Register health checker. + * + * @param healthChecker HealthChecker to be registered. */ - int maxRetryCount(); + void registerChecker(HealthChecker healthChecker); } diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/ArgumentsParseException.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/jdbc/JDBCClientException.java similarity index 78% rename from iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/ArgumentsParseException.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/jdbc/JDBCClientException.java index dbdb5d92..d85b2382 100644 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/ArgumentsParseException.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/jdbc/JDBCClientException.java @@ -16,15 +16,18 @@ * */ -package com.zmops.zeus.iot.server.library.server.jetty; +package com.zmops.zeus.iot.server.client.jdbc; -public class ArgumentsParseException extends Exception { +import java.io.IOException; - public ArgumentsParseException(String message) { +public class JDBCClientException extends IOException { + + public JDBCClientException(String message) { super(message); } - public ArgumentsParseException(String message, Throwable cause) { + public JDBCClientException(String message, Throwable cause) { super(message, cause); } } + diff --git a/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/jdbc/hikaricp/JDBCHikariCPClient.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/jdbc/hikaricp/JDBCHikariCPClient.java new file mode 100644 index 00000000..7bca76e7 --- /dev/null +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/jdbc/hikaricp/JDBCHikariCPClient.java @@ -0,0 +1,168 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.zmops.zeus.iot.server.client.jdbc.hikaricp; + + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import com.zmops.zeus.iot.server.client.Client; +import com.zmops.zeus.iot.server.client.healthcheck.DelegatedHealthChecker; +import com.zmops.zeus.iot.server.client.healthcheck.HealthCheckable; +import com.zmops.zeus.iot.server.client.jdbc.JDBCClientException; +import com.zmops.zeus.server.library.util.HealthChecker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.*; +import java.util.Properties; + +/** + * JDBC Client uses HikariCP connection management lib to execute SQL. + */ +public class JDBCHikariCPClient implements Client, HealthCheckable { + private static final Logger LOGGER = LoggerFactory.getLogger(JDBCHikariCPClient.class); + + private final HikariConfig hikariConfig; + private final DelegatedHealthChecker healthChecker; + private HikariDataSource dataSource; + + public JDBCHikariCPClient(Properties properties) { + hikariConfig = new HikariConfig(properties); + this.healthChecker = new DelegatedHealthChecker(); + } + + @Override + public void connect() { + dataSource = new HikariDataSource(hikariConfig); + } + + @Override + public void shutdown() { + } + + /** + * Default getConnection is set in auto-commit. + */ + public Connection getConnection() throws JDBCClientException { + return getConnection(true); + } + + public Connection getTransactionConnection() throws JDBCClientException { + return getConnection(false); + } + + public Connection getConnection(boolean autoCommit) throws JDBCClientException { + try { + Connection connection = dataSource.getConnection(); + connection.setAutoCommit(autoCommit); + return connection; + } catch (SQLException e) { + throw new JDBCClientException(e.getMessage(), e); + } + } + + public void execute(Connection connection, String sql) throws JDBCClientException { + LOGGER.debug("execute sql: {}", sql); + try (Statement statement = connection.createStatement()) { + statement.execute(sql); + healthChecker.health(); + } catch (SQLException e) { + healthChecker.unHealth(e); + throw new JDBCClientException(e.getMessage(), e); + } + } + + public int executeUpdate(Connection connection, String sql, Object... params) throws JDBCClientException { + LOGGER.debug("execute query with result: {}", sql); + int result; + PreparedStatement statement = null; + try { + statement = connection.prepareStatement(sql); + setStatementParam(statement, params); + result = statement.executeUpdate(); + statement.closeOnCompletion(); + healthChecker.health(); + } catch (SQLException e) { + if (statement != null) { + try { + statement.close(); + } catch (SQLException e1) { + } + } + healthChecker.unHealth(e); + throw new JDBCClientException(e.getMessage(), e); + } + + return result; + } + + public ResultSet executeQuery(Connection connection, String sql, Object... params) throws JDBCClientException { + LOGGER.debug("execute query with result: {}", sql); + ResultSet rs; + PreparedStatement statement = null; + try { + statement = connection.prepareStatement(sql); + setStatementParam(statement, params); + rs = statement.executeQuery(); + statement.closeOnCompletion(); + healthChecker.health(); + } catch (SQLException e) { + if (statement != null) { + try { + statement.close(); + } catch (SQLException e1) { + } + } + healthChecker.unHealth(e); + throw new JDBCClientException(e.getMessage(), e); + } + + return rs; + } + + private void setStatementParam(PreparedStatement statement, + Object[] params) throws SQLException, JDBCClientException { + if (params != null) { + int p = 0; + for (int i = 0; i < params.length; i++) { + Object param = params[i]; + if (param == null) { + continue; + } + ++p; + if (param instanceof String) { + statement.setString(p, (String) param); + } else if (param instanceof Integer) { + statement.setInt(p, (int) param); + } else if (param instanceof Double) { + statement.setDouble(p, (double) param); + } else if (param instanceof Long) { + statement.setLong(p, (long) param); + } else { + throw new JDBCClientException("Unsupported data type, type=" + param.getClass().getName()); + } + } + } + } + + @Override + public void registerChecker(HealthChecker healthChecker) { + this.healthChecker.register(healthChecker); + } +} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfig.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/request/InsertRequest.java similarity index 88% rename from iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfig.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/request/InsertRequest.java index bd5f8bec..4d48f0c7 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfig.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/request/InsertRequest.java @@ -13,10 +13,9 @@ * 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.zmops.zeus.iot.server.library.module; +package com.zmops.zeus.iot.server.client.request; -public abstract class ModuleConfig { +public interface InsertRequest extends PrepareRequest { } diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerHandler.java b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/request/PrepareRequest.java similarity index 90% rename from iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerHandler.java rename to iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/request/PrepareRequest.java index 0547f581..d608d264 100644 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerHandler.java +++ b/iot-server/server-client/src/main/java/com/zmops/zeus/iot/server/client/request/PrepareRequest.java @@ -13,10 +13,9 @@ * 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.zmops.zeus.iot.server.library.server; +package com.zmops.zeus.iot.server.client.request; -public interface ServerHandler { +public interface PrepareRequest { } diff --git a/iot-server/server-core/pom.xml b/iot-server/server-core/pom.xml index 5bf5c694..a8762a49 100644 --- a/iot-server/server-core/pom.xml +++ b/iot-server/server-core/pom.xml @@ -14,7 +14,7 @@ com.zmops library-module - 1.0-beta + 1.0.3-RELEASE com.zmops @@ -28,7 +28,24 @@ com.zmops - library-server + zeus-server-jetty + 1.0.3-RELEASE + + + + com.zmops + toolkit-datacarrier + 1.0.3-RELEASE + + + + com.zmops + server-camel-receiver + 1.0-beta + + + com.zmops + server-localdb 1.0-beta diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/Const.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/Const.java deleted file mode 100644 index 28f2452a..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/Const.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.zmops.zeus.iot.server.core; - -public class Const { - - public static final String CAMEL_ZABBIX_COMPONENT_NAME = "Zabbix"; -} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreConst.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreConst.java new file mode 100644 index 00000000..3355a16f --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreConst.java @@ -0,0 +1,9 @@ +package com.zmops.zeus.iot.server.core; + +/** + * 核心模块 参数 + */ +public class CoreConst { + + public static final String CORE_MODULE_VERSION = "1.0.1"; +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java index 245bce7f..cc396cd4 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModule.java @@ -1,9 +1,6 @@ package com.zmops.zeus.iot.server.core; -import com.zmops.zeus.iot.server.core.camel.CamelContextHolderService; -import com.zmops.zeus.iot.server.core.server.JettyHandlerRegister; -import com.zmops.zeus.iot.server.core.servlet.HttpItemTrapperHandler; -import com.zmops.zeus.iot.server.library.module.ModuleDefine; +import com.zmops.zeus.server.library.module.ModuleDefine; import java.util.ArrayList; import java.util.List; @@ -22,10 +19,6 @@ public CoreModule() { @Override public Class[] services() { List> classes = new ArrayList<>(); - - classes.add(JettyHandlerRegister.class); - classes.add(CamelContextHolderService.class); - return classes.toArray(new Class[]{}); } } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java index 2a7255dc..24da2f6b 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleConfig.java @@ -1,12 +1,9 @@ package com.zmops.zeus.iot.server.core; -import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import com.zmops.zeus.server.library.module.ModuleConfig; import lombok.Getter; import lombok.Setter; -import java.util.ArrayList; -import java.util.List; - /** * @author nantian created at 2021/8/16 22:29 */ @@ -19,13 +16,13 @@ public class CoreModuleConfig extends ModuleConfig { private String nameSpace; private String restHost; - private int restPort; + private int restPort; private String restContextPath; - private int restMinThreads = 1; - private int restMaxThreads = 200; - private long restIdleTimeOut = 30000; - private int restAcceptorPriorityDelta = 0; - private int restAcceptQueueSize = 0; + private int restMinThreads = 1; + private int restMaxThreads = 200; + private long restIdleTimeOut = 30000; + private int restAcceptorPriorityDelta = 0; + private int restAcceptQueueSize = 0; /** diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java index 30daea79..d74eacc5 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/CoreModuleProvider.java @@ -1,32 +1,32 @@ package com.zmops.zeus.iot.server.core; -import com.zmops.zeus.iot.server.core.camel.CamelContextHolderService; -import com.zmops.zeus.iot.server.core.camel.ZabbixSenderComponent; -import com.zmops.zeus.iot.server.core.server.JettyHandlerRegister; -import com.zmops.zeus.iot.server.core.server.JettyHandlerRegisterImpl; -import com.zmops.zeus.iot.server.core.servlet.HttpItemTrapperHandler; -import com.zmops.zeus.iot.server.library.module.*; -import com.zmops.zeus.iot.server.library.server.jetty.JettyServer; -import com.zmops.zeus.iot.server.library.server.jetty.JettyServerConfig; -import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; +import com.zmops.zeus.iot.server.core.analysis.StreamAnnotationListener; +import com.zmops.zeus.iot.server.core.annotation.AnnotationScan; +import com.zmops.zeus.iot.server.core.storage.StorageException; +import com.zmops.zeus.iot.server.receiver.module.CamelReceiverModule; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; -import org.apache.camel.impl.DefaultCamelContext; -import org.apache.camel.model.ModelCamelContext; +import com.zmops.zeus.server.jetty.JettyServer; +import com.zmops.zeus.server.jetty.JettyServerConfig; +import com.zmops.zeus.server.library.module.*; + +import java.io.IOException; /** * @author nantian created at 2021/8/16 22:26 */ public class CoreModuleProvider extends ModuleProvider { - private final CoreModuleConfig moduleConfig; - private ModelCamelContext camelContext; + private final CoreModuleConfig moduleConfig; private JettyServer jettyServer; + private final AnnotationScan annotationScan; + public CoreModuleProvider() { super(); this.moduleConfig = new CoreModuleConfig(); + this.annotationScan = new AnnotationScan(); } @@ -48,6 +48,8 @@ public ModuleConfig createConfigBeanIfAbsent() { @Override public void prepare() throws ServiceNotProvidedException, ModuleStartException { + annotationScan.registerListener(new StreamAnnotationListener(getManager())); + JettyServerConfig jettyServerConfig = JettyServerConfig.builder() .host(moduleConfig.getRestHost()) .port(moduleConfig.getRestPort()) @@ -60,42 +62,40 @@ public void prepare() throws ServiceNotProvidedException, ModuleStartException { .jettyHttpMaxRequestHeaderSize(moduleConfig.getHttpMaxRequestHeaderSize()) .build(); - jettyServer = new JettyServer(jettyServerConfig); jettyServer.initialize(); - - this.registerServiceImplementation(JettyHandlerRegister.class, new JettyHandlerRegisterImpl(jettyServer)); - - - camelContext = new DefaultCamelContext(); - camelContext.addComponent(Const.CAMEL_ZABBIX_COMPONENT_NAME, new ZabbixSenderComponent(getManager())); - - this.registerServiceImplementation(CamelContextHolderService.class, new CamelContextHolderService(camelContext, getManager())); + jettyServer.setFilterInitParameter("configClass", "com.zmops.zeus.iot.web.config.IoTConfig"); } @Override public void start() throws ServiceNotProvidedException, ModuleStartException { try { + annotationScan.scan(); + } catch (IOException | StorageException e) { + throw new ModuleStartException(e.getMessage(), e); + } + } - jettyServer.start(); - camelContext.start(); + public void shutdown() { - } catch (Exception e) { - e.printStackTrace(); - } } @Override public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { - JettyHandlerRegister service = getManager().find(CoreModule.NAME).provider().getService(JettyHandlerRegister.class); - service.addHandler(new HttpItemTrapperHandler()); + + try { + jettyServer.start(); + } catch (Exception e) { + throw new ModuleStartException(e.getMessage(), e); + } + } @Override public String[] requiredModules() { return new String[]{ TelemetryModule.NAME, - ZabbixSenderModule.NAME + CamelReceiverModule.NAME }; } } diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfigException.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/UnexpectedException.java similarity index 79% rename from iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfigException.java rename to iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/UnexpectedException.java index 7c03bba6..bb6d504d 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleConfigException.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/UnexpectedException.java @@ -16,15 +16,14 @@ * */ -package com.zmops.zeus.iot.server.library.module; +package com.zmops.zeus.iot.server.core; -public class ModuleConfigException extends Exception { - - public ModuleConfigException(String message) { +public class UnexpectedException extends RuntimeException { + public UnexpectedException(String message) { super(message); } - public ModuleConfigException(String message, Throwable cause) { + public UnexpectedException(String message, Exception cause) { super(message, cause); } } diff --git a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/HealthChecker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/Stream.java similarity index 55% rename from iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/HealthChecker.java rename to iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/Stream.java index 45c80f92..ab7754fc 100644 --- a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/HealthChecker.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/Stream.java @@ -16,29 +16,30 @@ * */ -package com.zmops.zeus.iot.server.library.util; +package com.zmops.zeus.iot.server.core.analysis; -/** - * Health checker provides methods to register the health status. - */ -public interface HealthChecker { - /** - * It's health. - */ - void health(); +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Stream annotation represents a metadata definition. + * See {@link RecordStreamProcessor} + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface Stream { /** - * It's unHealth. - * - * @param t details of unhealthy status + * @return name of this stream definition. */ - void unHealth(Throwable t); + String name(); /** - * It's unHealth. - * - * @param reason details reason of unhealthy status + * @return the stream processor type, {@link RecordStreamProcessor} for more details. */ - void unHealth(String reason); + Class processor(); } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamAnnotationListener.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamAnnotationListener.java new file mode 100644 index 00000000..0570e515 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamAnnotationListener.java @@ -0,0 +1,42 @@ +package com.zmops.zeus.iot.server.core.analysis; + +import com.zmops.zeus.iot.server.core.UnexpectedException; +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import com.zmops.zeus.iot.server.core.annotation.AnnotationListener; +import com.zmops.zeus.iot.server.core.storage.StorageException; +import com.zmops.zeus.server.library.module.ModuleDefineHolder; + +import java.lang.annotation.Annotation; + +/** + * @author nantian created at 2021/9/6 17:37 + */ +public class StreamAnnotationListener implements AnnotationListener { + + private final ModuleDefineHolder moduleDefineHolder; + + public StreamAnnotationListener(ModuleDefineHolder moduleDefineHolder) { + this.moduleDefineHolder = moduleDefineHolder; + } + + @Override + public Class annotation() { + return Stream.class; + } + + @Override + @SuppressWarnings("unchecked") + public void notify(Class aClass) throws StorageException { + if (aClass.isAnnotationPresent(Stream.class)) { + Stream stream = (Stream) aClass.getAnnotation(Stream.class); + + if (stream.processor().equals(RecordStreamProcessor.class)) { + RecordStreamProcessor.getInstance().create(moduleDefineHolder, stream, aClass); + } else { + throw new UnexpectedException("Unknown stream processor."); + } + } else { + throw new UnexpectedException("Stream annotation listener could only parse the class present stream annotation."); + } + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamProcessor.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamProcessor.java new file mode 100644 index 00000000..698a1079 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/StreamProcessor.java @@ -0,0 +1,14 @@ +package com.zmops.zeus.iot.server.core.analysis; + +/** + * @author nantian created at 2021/9/6 16:49 + */ +public interface StreamProcessor { + + /** + * 写入数据 + * + * @param stream record + */ + void in(STREAM stream); +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java new file mode 100644 index 00000000..7dc547f8 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/History.java @@ -0,0 +1,43 @@ +package com.zmops.zeus.iot.server.core.analysis.manual.history; + +import com.zmops.zeus.iot.server.core.analysis.Stream; +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/9/6 17:07 + */ +@Getter +@Setter +@Stream(name = "history", processor = RecordStreamProcessor.class) +public class History extends Record { + + private Long clock; + + private Long ns; + + private String value; // 浮点数 + + private String deviceId; // host + + private Map itemTags; + + private List hostGroups; + + @Override + public Integer itemid() { + return getItemid(); + } + + @Override + public void setValue(String deviceId, String value, Long clock) { + this.deviceId = deviceId; + this.value = value; + this.clock = clock; + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/StrHistory.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/StrHistory.java new file mode 100644 index 00000000..3a6d6498 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/StrHistory.java @@ -0,0 +1,43 @@ +package com.zmops.zeus.iot.server.core.analysis.manual.history; + +import com.zmops.zeus.iot.server.core.analysis.Stream; +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/9/6 17:07 + */ +@Getter +@Setter +@Stream(name = "history_str", processor = RecordStreamProcessor.class) +public class StrHistory extends Record { + + private Long clock; + + private Long ns; + + private String value; // 浮点数 + + private String deviceId; // host + + private Map itemTags; + + private List hostGroups; + + @Override + public Integer itemid() { + return getItemid(); + } + + @Override + public void setValue(String deviceId, String value, Long clock) { + this.deviceId = deviceId; + this.value = value; + this.clock = clock; + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/TextHistory.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/TextHistory.java new file mode 100644 index 00000000..06d6e1c9 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/TextHistory.java @@ -0,0 +1,43 @@ +package com.zmops.zeus.iot.server.core.analysis.manual.history; + +import com.zmops.zeus.iot.server.core.analysis.Stream; +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/9/6 17:07 + */ +@Getter +@Setter +@Stream(name = "history_text", processor = RecordStreamProcessor.class) +public class TextHistory extends Record { + + private Long clock; + + private Long ns; + + private String value; // 浮点数 + + private String deviceId; // host + + private Map itemTags; + + private List hostGroups; + + @Override + public Integer itemid() { + return getItemid(); + } + + @Override + public void setValue(String deviceId, String value, Long clock) { + this.deviceId = deviceId; + this.value = value; + this.clock = clock; + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java new file mode 100644 index 00000000..e8978868 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/history/UIntHistory.java @@ -0,0 +1,43 @@ +package com.zmops.zeus.iot.server.core.analysis.manual.history; + +import com.zmops.zeus.iot.server.core.analysis.Stream; +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/9/6 17:07 + */ +@Getter +@Setter +@Stream(name = "history_uint", processor = RecordStreamProcessor.class) +public class UIntHistory extends Record { + + private Long clock; + + private Long ns; + + private String value; // 浮点数 + + private String deviceId; + + private Map itemTags; + + private List hostGroups; + + @Override + public Integer itemid() { + return getItemid(); + } + + @Override + public void setValue(String deviceId, String value, Long clock) { + this.deviceId = deviceId; + this.value = value; + this.clock = clock; + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/Trends.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/Trends.java new file mode 100644 index 00000000..c8fe7d04 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/Trends.java @@ -0,0 +1,7 @@ +package com.zmops.zeus.iot.server.core.analysis.manual.trends; + +/** + * @author nantian created at 2021/9/6 17:32 + */ +public class Trends { +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/UIntTrends.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/UIntTrends.java new file mode 100644 index 00000000..446ae22d --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/manual/trends/UIntTrends.java @@ -0,0 +1,7 @@ +package com.zmops.zeus.iot.server.core.analysis.manual.trends; + +/** + * @author nantian created at 2021/9/6 17:32 + */ +public class UIntTrends { +} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IConsumer.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java similarity index 70% rename from iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IConsumer.java rename to iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java index 964edbf8..5dcdcf73 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IConsumer.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/record/Record.java @@ -16,16 +16,18 @@ * */ -package com.zmops.zeus.iot.server.datacarrier.consumer; +package com.zmops.zeus.iot.server.core.analysis.record; -import java.util.List; +import com.zmops.zeus.iot.server.core.storage.StorageData; +import lombok.Getter; +import lombok.Setter; -public interface IConsumer { - void init(); +public abstract class Record implements StorageData { - void consume(List data); + @Getter + @Setter + private Integer itemid; - void onError(List data, Throwable t); - void onExit(); + public abstract void setValue(String deviceId, String value, Long clock); } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordPersistentWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordPersistentWorker.java new file mode 100644 index 00000000..81c5a93f --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordPersistentWorker.java @@ -0,0 +1,38 @@ +package com.zmops.zeus.iot.server.core.analysis.worker; + +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.storage.IBatchDAO; +import com.zmops.zeus.iot.server.core.storage.IRecordDAO; +import com.zmops.zeus.iot.server.core.storage.StorageModule; +import com.zmops.zeus.iot.server.core.storage.model.Model; +import com.zmops.zeus.iot.server.core.worker.AbstractWorker; +import com.zmops.zeus.iot.server.client.request.InsertRequest; +import com.zmops.zeus.server.library.module.ModuleDefineHolder; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; + +@Slf4j +public class RecordPersistentWorker extends AbstractWorker { + + private final Model model; + private final IRecordDAO recordDAO; + private final IBatchDAO batchDAO; + + public RecordPersistentWorker(ModuleDefineHolder moduleDefineHolder, Model model, IRecordDAO recordDAO) { + super(moduleDefineHolder); + this.model = model; + this.recordDAO = recordDAO; + this.batchDAO = moduleDefineHolder.find(StorageModule.NAME).provider().getService(IBatchDAO.class); + } + + @Override + public void in(Record record) { + try { + InsertRequest insertRequest = recordDAO.prepareBatchInsert(model, record); + batchDAO.insert(insertRequest); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java new file mode 100644 index 00000000..5708191d --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/analysis/worker/RecordStreamProcessor.java @@ -0,0 +1,47 @@ +package com.zmops.zeus.iot.server.core.analysis.worker; + +import com.zmops.zeus.iot.server.core.analysis.Stream; +import com.zmops.zeus.iot.server.core.analysis.StreamProcessor; +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.storage.IRecordDAO; +import com.zmops.zeus.iot.server.core.storage.StorageDAO; +import com.zmops.zeus.iot.server.core.storage.StorageModule; +import com.zmops.zeus.iot.server.core.storage.model.Model; +import com.zmops.zeus.server.library.module.ModuleDefineHolder; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author nantian created at 2021/9/6 16:47 + */ +public class RecordStreamProcessor implements StreamProcessor { + + private final Map, RecordPersistentWorker> workers = new HashMap<>(); + + private final static RecordStreamProcessor PROCESSOR = new RecordStreamProcessor(); + + public static RecordStreamProcessor getInstance() { + return PROCESSOR; + } + + @Override + public void in(Record record) { + RecordPersistentWorker worker = workers.get(record.getClass()); + if (worker != null) { + worker.in(record); + } + } + + public void create(ModuleDefineHolder moduleDefineHolder, Stream stream, Class recordClass) { + + StorageDAO storageDAO = moduleDefineHolder.find(StorageModule.NAME).provider().getService(StorageDAO.class); + IRecordDAO recordDAO = storageDAO.newRecordDao(); + + Model model = new Model(stream.name()); + + RecordPersistentWorker persistentWorker = new RecordPersistentWorker(moduleDefineHolder, model, recordDAO); + + workers.put(recordClass, persistentWorker); + } +} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IDriver.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationListener.java similarity index 73% rename from iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IDriver.java rename to iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationListener.java index ced1c6e0..155fcdbf 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/IDriver.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationListener.java @@ -16,18 +16,15 @@ * */ -package com.zmops.zeus.iot.server.datacarrier.consumer; +package com.zmops.zeus.iot.server.core.annotation; +import com.zmops.zeus.iot.server.core.storage.StorageException; -import com.zmops.zeus.iot.server.datacarrier.buffer.Channels; +import java.lang.annotation.Annotation; -/** - * The driver of consumer. - */ -public interface IDriver { - boolean isRunning(Channels channels); +public interface AnnotationListener { - void close(Channels channels); + Class annotation(); - void begin(Channels channels); + void notify(Class aClass) throws StorageException; } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java new file mode 100644 index 00000000..c979bbb8 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/annotation/AnnotationScan.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.zmops.zeus.iot.server.core.annotation; + +import com.google.common.collect.ImmutableSet; +import com.google.common.reflect.ClassPath; +import com.zmops.zeus.iot.server.core.storage.StorageException; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; + +/** + * Scan the annotation, and notify the listener(s) + */ +public class AnnotationScan { + + private final List listeners; + + public AnnotationScan() { + this.listeners = new LinkedList<>(); + } + + /** + * Register the callback listener + * + * @param listener to be called after class found w/ annotation + */ + public void registerListener(AnnotationListener listener) { + listeners.add(new AnnotationListenerCache(listener)); + } + + /** + * Begin to scan classes. + */ + public void scan() throws IOException, StorageException { + ClassPath classpath = ClassPath.from(this.getClass().getClassLoader()); + ImmutableSet classes = classpath.getTopLevelClassesRecursive("com.zmops.zeus.iot"); + for (ClassPath.ClassInfo classInfo : classes) { + Class aClass = classInfo.load(); + + for (AnnotationListenerCache listener : listeners) { + if (aClass.isAnnotationPresent(listener.annotation())) { + listener.addMatch(aClass); + } + } + } + + for (AnnotationListenerCache listener : listeners) { + listener.complete(); + } + } + + private static class AnnotationListenerCache { + + private final AnnotationListener listener; + private final List> matchedClass; + + private AnnotationListenerCache(AnnotationListener listener) { + this.listener = listener; + matchedClass = new LinkedList<>(); + } + + private Class annotation() { + return this.listener.annotation(); + } + + private void addMatch(Class aClass) { + matchedClass.add(aClass); + } + + private void complete() throws StorageException { + matchedClass.sort(Comparator.comparing(Class::getName)); + for (Class aClass : matchedClass) { + listener.notify(aClass); + } + } + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/CamelContextHolderService.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/CamelContextHolderService.java deleted file mode 100644 index c9d19164..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/CamelContextHolderService.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.zmops.zeus.iot.server.core.camel; - -import com.zmops.zeus.iot.server.library.module.ModuleManager; -import com.zmops.zeus.iot.server.library.module.Service; -import org.apache.camel.CamelContext; -import org.apache.camel.RoutesBuilder; - -/** - * @author nantian created at 2021/8/17 0:24 - *

- * CamelContextHolderService ,便于模块服务调用,全局只有一个 Camel 上下文 - */ -public class CamelContextHolderService implements Service { - - private final CamelContext camelContext; - private final ModuleManager moduleManager; - - public CamelContextHolderService(CamelContext camelContext, ModuleManager moduleManager) { - this.camelContext = camelContext; - this.moduleManager = moduleManager; - } - - - /** - * 配置路由 - * - * @param builder 路由 - */ - public void addRoutes(RoutesBuilder builder) { - try { - camelContext.addRoutes(builder); - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java deleted file mode 100644 index 4f8dbac1..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/camel/ZabbixTrapperProducer.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.zmops.zeus.iot.server.core.camel; - -import com.zmops.zeus.iot.server.library.module.ModuleManager; -import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; -import com.zmops.zeus.iot.server.sender.provider.service.ZabbixSenderService; -import org.apache.camel.Endpoint; -import org.apache.camel.Exchange; -import org.apache.camel.Message; -import org.apache.camel.impl.DefaultProducer; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * @author nantian created at 2021/8/16 22:48 - *

- * to("Zabbix") - */ -public class ZabbixTrapperProducer extends DefaultProducer { - - private final ModuleManager moduleManager; - - - public ZabbixTrapperProducer(Endpoint endpoint, ModuleManager moduleManager) { - super(endpoint); - this.moduleManager = moduleManager; - } - - /** - * TODO 数据写入 队列,进来之前 是 JSON 格式 - * - * @param exchange Exchange - */ - @Override - public void process(Exchange exchange) throws Exception { - Message message = exchange.getIn(); - InputStream bodyStream = (InputStream) message.getBody(); - String inputContext = this.analysisMessage(bodyStream); - - ZabbixSenderService senderService = moduleManager.find(ZabbixSenderModule.NAME).provider().getService(ZabbixSenderService.class); - - String resp = senderService.sendData(inputContext); - - // 把Zabbix 响应结果放入 Message 返回 - message.setBody(resp); - } - - - private String analysisMessage(InputStream bodyStream) throws IOException { - ByteArrayOutputStream outStream = new ByteArrayOutputStream(); - byte[] contextBytes = new byte[4096]; - int realLen; - while ((realLen = bodyStream.read(contextBytes, 0, 4096)) != -1) { - outStream.write(contextBytes, 0, realLen); - } - - // 返回从Stream中读取的字串 - try { - return outStream.toString("UTF-8"); - } finally { - outStream.close(); - } - } -} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegister.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegister.java deleted file mode 100644 index 07ca38aa..00000000 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegister.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.core.server; - - -import com.zmops.zeus.iot.server.library.module.Service; -import com.zmops.zeus.iot.server.library.server.jetty.JettyHandler; - -public interface JettyHandlerRegister extends Service { - - void addHandler(JettyHandler serverHandler); -} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java index 77dadab9..85671250 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/DeviceTriggerActionHandler.java @@ -1,10 +1,14 @@ package com.zmops.zeus.iot.server.core.servlet; +import com.google.gson.Gson; import com.google.gson.JsonElement; -import com.zmops.zeus.iot.server.library.server.jetty.ArgumentsParseException; -import com.zmops.zeus.iot.server.library.server.jetty.JettyJsonHandler; +import com.zmops.zeus.server.jetty.ArgumentsParseException; +import com.zmops.zeus.server.jetty.JettyJsonHandler; +import com.zmops.zeus.server.library.module.ModuleManager; +import lombok.extern.slf4j.Slf4j; import javax.servlet.http.HttpServletRequest; +import java.io.BufferedReader; import java.io.IOException; /** @@ -12,8 +16,15 @@ *

* 设备 告警规则 触发动作,Http 统一入口 */ +@Slf4j public class DeviceTriggerActionHandler extends JettyJsonHandler { + private final ModuleManager moduleManager; + private final Gson gson = new Gson(); + + public DeviceTriggerActionHandler(ModuleManager moduleManager) { + this.moduleManager = moduleManager; + } @Override public String pathSpec() { @@ -21,16 +32,40 @@ public String pathSpec() { } + /** + * 动作触发Http入口,可在设备 上面设置 宏 定义,动态传入 identifier + * + * @param req + * @return JsonElement + */ @Override - protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { + public JsonElement doPost(HttpServletRequest req) throws IOException { + + String request = getJsonBody(req); + log.info("action command : {}", request); + +// EventBusService eventBusService = moduleManager.find(CoreModule.NAME).provider().getService(EventBusService.class); +// +// +// ActionParam actionParam = new ActionParam(); +// actionParam.setActionParamContent(request); +// +// eventBusService.postExecuteActionMsg(ActionRouteIdentifier.helloworld, actionParam); + return null; } - /** - * 执行 Action,进 EventBus,方便订阅处理 - */ - private void execute() { - + @Override + public String getJsonBody(HttpServletRequest req) throws IOException { + StringBuffer stringBuffer = new StringBuffer(); + String line = null; + BufferedReader reader = req.getReader(); + while ((line = reader.readLine()) != null) { + stringBuffer.append(line); + } + return stringBuffer.toString(); } + + } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java index 48c28549..48c16a18 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/servlet/HttpItemTrapperHandler.java @@ -3,13 +3,21 @@ import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import com.zmops.zeus.iot.server.library.server.jetty.ArgumentsParseException; -import com.zmops.zeus.iot.server.library.server.jetty.JettyJsonHandler; +import com.google.gson.reflect.TypeToken; +import com.zmops.zeus.iot.server.core.worker.data.ItemValue; +import com.zmops.zeus.iot.server.core.worker.data.ZabbixTrapper; +import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; +import com.zmops.zeus.iot.server.sender.service.ZabbixSenderService; +import com.zmops.zeus.server.jetty.ArgumentsParseException; +import com.zmops.zeus.server.jetty.JettyJsonHandler; +import com.zmops.zeus.server.library.module.ModuleManager; import javax.servlet.http.HttpServletRequest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.lang.reflect.Type; +import java.util.List; /** * @author nantian created at 2021/8/20 0:51 @@ -20,16 +28,22 @@ public class HttpItemTrapperHandler extends JettyJsonHandler { private final Gson gson = new Gson(); + private final ModuleManager moduleManager; + + public HttpItemTrapperHandler(ModuleManager moduleManager) { + this.moduleManager = moduleManager; + } + @Override public String pathSpec() { return "/device/attr/send"; } @Override - protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException { + public JsonElement doPost(HttpServletRequest req) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(req.getInputStream())); - String line; + String line; StringBuilder request = new StringBuilder(); while ((line = reader.readLine()) != null) { request.append(line); @@ -37,6 +51,19 @@ protected JsonElement doPost(HttpServletRequest req) throws ArgumentsParseExcept JsonObject requestJson = gson.fromJson(request.toString(), JsonObject.class); + Type listType = new TypeToken>() {}.getType(); + + List valueList = gson.fromJson(requestJson.getAsJsonArray("params").toString(), listType); + + + ZabbixSenderService zabbixSenderService = moduleManager.find(ZabbixSenderModule.NAME).provider().getService(ZabbixSenderService.class); + ZabbixTrapper zabbixTrapper = new ZabbixTrapper(valueList); + zabbixSenderService.sendData(gson.toJson(zabbixTrapper)); return requestJson; } + + @Override + public String getJsonBody(HttpServletRequest req) throws IOException { + return null; + } } diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/CycleDependencyException.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/DAO.java similarity index 80% rename from iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/CycleDependencyException.java rename to iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/DAO.java index 8f7e2aa9..da60f993 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/CycleDependencyException.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/DAO.java @@ -16,10 +16,13 @@ * */ -package com.zmops.zeus.iot.server.library.module; +package com.zmops.zeus.iot.server.core.storage; -public class CycleDependencyException extends RuntimeException { - public CycleDependencyException(String message) { - super(message); - } + +import com.zmops.zeus.server.library.module.Service; + +/** + * A specific interface for storage layer services. + */ +public interface DAO extends Service { } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IBatchDAO.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IBatchDAO.java new file mode 100644 index 00000000..a7d63e27 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IBatchDAO.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.zmops.zeus.iot.server.core.storage; + + +import com.zmops.zeus.iot.server.client.request.InsertRequest; +import com.zmops.zeus.iot.server.client.request.PrepareRequest; + +import java.util.List; + +/** + * IBatchDAO provides two modes of data persistence supported by most databases, including pure insert and batch hybrid + * insert/update. + */ +public interface IBatchDAO extends DAO { + /** + * Push data into the database in async mode. This method is driven by streaming process. This method doesn't + * request the data queryable immediately after the method finished. + * + * @param insertRequest data to insert. + */ + void insert(InsertRequest insertRequest); + + /** + * Push data collection into the database in async mode. This method is driven by streaming process. This method + * doesn't request the data queryable immediately after the method finished. + *

+ * The method requires thread safe. The OAP core would call this concurrently. + * + * @param prepareRequests data to insert or update. No delete happens in streaming mode. + */ + void flush(List prepareRequests); +} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPool.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IRecordDAO.java similarity index 64% rename from iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPool.java rename to iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IRecordDAO.java index bbeb4b08..02850810 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/consumer/ConsumerPool.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/IRecordDAO.java @@ -16,16 +16,19 @@ * */ -package com.zmops.zeus.iot.server.datacarrier.consumer; +package com.zmops.zeus.iot.server.core.storage; -import com.zmops.zeus.iot.server.datacarrier.DataCarrier; -import com.zmops.zeus.iot.server.datacarrier.buffer.Channels; +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.storage.model.Model; +import com.zmops.zeus.iot.server.client.request.InsertRequest; + +import java.io.IOException; /** - * The Consumer pool could support data consumer from multiple {@link DataCarrier}s, by using different consume thread - * management models. + * DAO specifically for {@link Record} implementations. */ -public interface ConsumerPool extends IDriver { - void add(String name, Channels channels, IConsumer consumer); +public interface IRecordDAO extends DAO { + + InsertRequest prepareBatchInsert(Model model, Record record) throws IOException; } diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/Service.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageDAO.java similarity index 69% rename from iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/Service.java rename to iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageDAO.java index 4315fe5c..5307a0fe 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/Service.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageDAO.java @@ -16,12 +16,17 @@ * */ -package com.zmops.zeus.iot.server.library.module; +package com.zmops.zeus.iot.server.core.storage; + + +import com.zmops.zeus.server.library.module.Service; /** - * The Service implementation is a service provided by its own modules. - *

- * And every {@link ModuleProvider} must provide all the given services of the {@link ModuleDefine}. + * StorageDAO is a DAO factory for storage layer. Provide the implementations of typical DAO interfaces. */ -public interface Service { +public interface StorageDAO extends Service { + +// IMetricsDAO newMetricsDao(StorageBuilder storageBuilder); + + IRecordDAO newRecordDao(); } diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/DuplicateProviderException.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageData.java similarity index 76% rename from iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/DuplicateProviderException.java rename to iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageData.java index 221f5a65..9c4ab518 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/DuplicateProviderException.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageData.java @@ -16,15 +16,14 @@ * */ -package com.zmops.zeus.iot.server.library.module; - +package com.zmops.zeus.iot.server.core.storage; /** - * @author nantian 重复的 Provider + * Any persistent entity should be an implementation of this interface. */ -public class DuplicateProviderException extends RuntimeException { - - public DuplicateProviderException(String message) { - super(message); - } +public interface StorageData { + /** + * @return the unique id used in any storage option. + */ + Integer itemid(); } diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerException.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageException.java similarity index 80% rename from iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerException.java rename to iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageException.java index 1f7e15ec..4cd73613 100644 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ServerException.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageException.java @@ -16,15 +16,15 @@ * */ -package com.zmops.zeus.iot.server.library.server; +package com.zmops.zeus.iot.server.core.storage; -public abstract class ServerException extends Exception { +public class StorageException extends Exception { - public ServerException(String message) { + public StorageException(String message) { super(message); } - public ServerException(String message, Throwable cause) { + public StorageException(String message, Throwable cause) { super(message, cause); } } diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/SimpleRollingPartitioner.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageModule.java similarity index 58% rename from iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/SimpleRollingPartitioner.java rename to iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageModule.java index c69041e8..6a7727ce 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/SimpleRollingPartitioner.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/StorageModule.java @@ -16,22 +16,28 @@ * */ -package com.zmops.zeus.iot.server.datacarrier.partition; +package com.zmops.zeus.iot.server.core.storage; + + +import com.zmops.zeus.server.library.module.ModuleDefine; /** - * use normal int to rolling. + * StorageModule provides the capabilities(services) to interact with the database. With different databases, this + * module could have different providers, such as currently, H2, MySQL, ES, TiDB. */ -public class SimpleRollingPartitioner implements IDataPartitioner { - @SuppressWarnings("NonAtomicVolatileUpdate") - private volatile int i = 0; +public class StorageModule extends ModuleDefine { - @Override - public int partition(int total, T data) { - return Math.abs(i++ % total); + public static final String NAME = "storage"; + + public StorageModule() { + super(NAME); } @Override - public int maxRetryCount() { - return 3; + public Class[] services() { + return new Class[]{ + IBatchDAO.class, + StorageDAO.class + }; } } diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundException.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/model/Model.java similarity index 72% rename from iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundException.java rename to iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/model/Model.java index bf06561b..eefe9a9a 100644 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundException.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/storage/model/Model.java @@ -16,15 +16,21 @@ * */ -package com.zmops.zeus.iot.server.library.module; +package com.zmops.zeus.iot.server.core.storage.model; -public class ModuleNotFoundException extends Exception { +import lombok.EqualsAndHashCode; +import lombok.Getter; - public ModuleNotFoundException(Throwable cause) { - super(cause); - } +/** + * The model definition of a logic entity. + */ +@Getter +@EqualsAndHashCode +public class Model { + + private final String name; - public ModuleNotFoundException(String message) { - super(message); + public Model(final String name) { + this.name = name; } } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/AbstractWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/AbstractWorker.java new file mode 100644 index 00000000..3b25872b --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/AbstractWorker.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.zmops.zeus.iot.server.core.worker; + +import com.zmops.zeus.server.library.module.ModuleDefineHolder; +import lombok.Getter; + + +/** + * Abstract worker definition. Provide the {@link ModuleDefineHolder} to make sure the worker could find and access + * services in different modules. Also, {@link #in(Object)} is provided as the primary entrance of every worker. + *

+ * + * @param the datatype this worker implementation processes. + * @editor nantian + * 数据从协议入口 发送到 zabbix 过程中的队列,to("zabbix") + */ +public abstract class AbstractWorker { + + @Getter + private final ModuleDefineHolder moduleDefineHolder; + + public AbstractWorker(ModuleDefineHolder moduleDefineHolder) { + this.moduleDefineHolder = moduleDefineHolder; + } + + /** + * Main entrance of this worker. + */ + public abstract void in(INPUT input); +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java new file mode 100644 index 00000000..9024fd78 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/ItemDataTransferWorker.java @@ -0,0 +1,142 @@ +package com.zmops.zeus.iot.server.core.worker; + +import com.google.gson.Gson; +import com.zmops.zeus.iot.server.core.UnexpectedException; +import com.zmops.zeus.iot.server.core.worker.data.ItemValue; +import com.zmops.zeus.iot.server.core.worker.data.ZabbixTrapper; +import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; +import com.zmops.zeus.iot.server.sender.service.ZabbixSenderService; +import com.zmops.zeus.iot.server.telemetry.TelemetryModule; +import com.zmops.zeus.iot.server.telemetry.api.CounterMetrics; +import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; +import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import com.zmops.zeus.server.datacarrier.DataCarrier; +import com.zmops.zeus.server.datacarrier.consumer.BulkConsumePool; +import com.zmops.zeus.server.datacarrier.consumer.ConsumerPoolFactory; +import com.zmops.zeus.server.datacarrier.consumer.IConsumer; +import com.zmops.zeus.server.library.module.ModuleManager; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author nantian created at 2021/8/23 15:11 + *

+ * 数据发送队列 + */ +@Slf4j +public class ItemDataTransferWorker extends TransferWorker { + + + private final DataCarrier dataCarrier; + private final CounterMetrics iotDataTransferCounter; + private final Gson gson = new Gson(); + + public ItemDataTransferWorker(ModuleManager moduleManager) { + super(moduleManager); + + String name = "ITEMVALUE_TRANSFER_TUNNEL"; + + int size = BulkConsumePool.Creator.recommendMaxSize() / 8; + if (size == 0) { + size = 1; + } + BulkConsumePool.Creator creator = new BulkConsumePool.Creator(name, size, 20); + try { + ConsumerPoolFactory.INSTANCE.createIfAbsent(name, creator); + } catch (Exception e) { + throw new UnexpectedException(e.getMessage(), e); + } + + this.dataCarrier = new DataCarrier<>("ZABBIX_SENDER", name, 4, 2000); + this.dataCarrier.consume(ConsumerPoolFactory.INSTANCE.get(name), new SenderConsumer()); + + // #### 发送数量 指标采集 + MetricsCreator metricsCreator = moduleManager.find(TelemetryModule.NAME) + .provider() + .getService(MetricsCreator.class); + + iotDataTransferCounter = metricsCreator.createCounter( + "transfer_data_count", "The count number of iot device data in transfer", + new MetricsTag.Keys("name"), + new MetricsTag.Values("transfer_data_count") + ); + } + + + @Override + public void in(ItemValue itemValue) { + iotDataTransferCounter.inc(); + dataCarrier.produce(itemValue); + } + + @Override + public void prepareBatch(Collection lastCollection) { + long start = System.currentTimeMillis(); + if (lastCollection.size() == 0) { + return; + } + + int maxBatchGetSize = 500; + final int batchSize = Math.min(maxBatchGetSize, lastCollection.size()); + List valueList = new ArrayList<>(); + + for (ItemValue data : lastCollection) { + valueList.add(data); + if (valueList.size() == batchSize) { + batchSenderDataToZabbix(valueList); + } + } + + if (valueList.size() > 0) { + batchSenderDataToZabbix(valueList); + } + + log.debug("batch sender data size:{}, took time: {}", lastCollection.size(), System.currentTimeMillis() - start); + } + + + private void batchSenderDataToZabbix(List valueList) { + ZabbixTrapper zabbixTrapper = new ZabbixTrapper(valueList); + + ZabbixSenderService senderService = getModuleDefineHolder() + .find(ZabbixSenderModule.NAME).provider().getService(ZabbixSenderService.class); + + try { + String sendResult = senderService.sendData(gson.toJson(zabbixTrapper)); + log.debug(sendResult); + } catch (IOException e) { + log.error(" itemvalue data sender error,msg :{}", e.getMessage()); + e.printStackTrace(); + } finally { + valueList.clear(); + } + } + + + private class SenderConsumer implements IConsumer { + @Override + public void init() { + + } + + @Override + public void consume(List data) { + ItemDataTransferWorker.this.onWork(data); + } + + @Override + public void onError(List data, Throwable t) { + log.error(t.getMessage(), t); + } + + @Override + public void onExit() { + } + } + + +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/TransferWorker.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/TransferWorker.java new file mode 100644 index 00000000..4fbba12d --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/TransferWorker.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.zmops.zeus.iot.server.core.worker; + +import com.zmops.zeus.iot.server.core.worker.data.Item; +import com.zmops.zeus.server.library.module.ModuleDefineHolder; +import lombok.extern.slf4j.Slf4j; + +import java.util.Collection; +import java.util.List; + +/** + * 1. 协议入口 -> zabbix trapper item + * + * @param The type of worker input. + */ +@Slf4j +public abstract class TransferWorker extends AbstractWorker { + + TransferWorker(ModuleDefineHolder moduleDefineHolder) { + super(moduleDefineHolder); + } + + void onWork(List input) { + prepareBatch(input); + } + + public abstract void prepareBatch(Collection lastCollection); + +} diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/QueueBuffer.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/BufferedData.java similarity index 60% rename from iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/QueueBuffer.java rename to iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/BufferedData.java index 25d944a8..ba5a7346 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/buffer/QueueBuffer.java +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/BufferedData.java @@ -16,31 +16,26 @@ * */ -package com.zmops.zeus.iot.server.datacarrier.buffer; +package com.zmops.zeus.iot.server.core.worker.data; import java.util.List; /** - * Queue buffer interface. + * BufferedData represents a data collection in the memory. Data could be accepted and be drain to other collection. + *

+ * {@link #accept(Object)} and {@link #read()} wouldn't be required to thread-safe. */ -public interface QueueBuffer { +public interface BufferedData { /** - * Save data into the queue; + * Accept the data into the cache if it fits the conditions. The implementation maybe wouldn't accept the new input + * data. * - * @param data to add. - * @return true if saved + * @param data to be added potentially. */ - boolean save(T data); + void accept(T data); /** - * Set different strategy when queue is full. + * Read all existing buffered data, and clear the memory. */ - void setStrategy(BufferStrategy strategy); - - /** - * Obtain the existing data from the queue - */ - void obtain(List consumeList); - - int getBufferSize(); + List read(); } diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/Item.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/Item.java new file mode 100644 index 00000000..40f5c79b --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/Item.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.server.core.worker.data; + +/** + * @author nantian created at 2021/8/23 15:14 + *

+ * 对应设备的属性 + */ +public interface Item { + + /** + * 设备ID 唯一 + * + * @return string + */ + String host(); + + /** + * 属性标识 唯一 + * + * @return string + */ + String key(); +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java new file mode 100644 index 00000000..c0cd1d9a --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ItemValue.java @@ -0,0 +1,55 @@ +package com.zmops.zeus.iot.server.core.worker.data; + +import lombok.Getter; +import lombok.Setter; + +/** + * @author nantian created at 2021/8/23 15:15 + */ + +@Getter +@Setter +public class ItemValue implements Item { + + private String host; // 【设备ID】 + + private String key; // 【属性标识】 + + // 【设备上报 值】,都是文本 + // Zabbix 会根据配置的ITEM 类型,进行转换,如果失败就报错 + private String value; + + private Long clock; // 秒,如果为 Null,则 zabbix 以接收时间为准 + + private Long ns; // 纳秒,如果为 Null,则 zabbix 以接收时间为准 + + + public ItemValue(String host, Long clock) { + this.host = host; + if (clock != null) { + this.clock = clock; + } + } + + /** + * 设置 数据时间,单独设置 以设备推送的时间数据为准 + * + * @param clock 毫秒,70年到现在 + * @param ns 纳秒,0-9位数 + */ + public void setTime(Long clock, Long ns) { + this.clock = clock; + this.ns = ns; + } + + + @Override + public String host() { + return getHost(); + } + + @Override + public String key() { + return getKey(); + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ZabbixTrapper.java b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ZabbixTrapper.java new file mode 100644 index 00000000..ea89c2b3 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/worker/data/ZabbixTrapper.java @@ -0,0 +1,26 @@ +package com.zmops.zeus.iot.server.core.worker.data; + +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author nantian created at 2021/8/23 16:49 + */ +public class ZabbixTrapper { + + + @Getter + private final String request = "sender data"; + + @Setter + @Getter + private List data; + + public ZabbixTrapper(List itemValues) { + data = new ArrayList<>(); + data.addAll(itemValues); + } +} diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/server/jetty/JettyJsonHandler.java b/iot-server/server-core/src/main/java/com/zmops/zeus/server/jetty/JettyJsonHandler.java new file mode 100644 index 00000000..d2c54e03 --- /dev/null +++ b/iot-server/server-core/src/main/java/com/zmops/zeus/server/jetty/JettyJsonHandler.java @@ -0,0 +1,13 @@ +package com.zmops.zeus.server.jetty; + +import com.google.gson.JsonElement; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +public abstract class JettyJsonHandler { + public abstract String pathSpec(); + public abstract JsonElement doPost(HttpServletRequest req) throws IOException; + public abstract String getJsonBody(HttpServletRequest req) throws IOException; + +} diff --git a/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine b/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine new file mode 100644 index 00000000..02f80702 --- /dev/null +++ b/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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 +# +# http://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. +# +# + +com.zmops.zeus.iot.server.core.storage.StorageModule +com.zmops.zeus.iot.server.core.CoreModule diff --git a/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-health-checker/pom.xml b/iot-server/server-health-checker/pom.xml index 99a1701e..7716707c 100644 --- a/iot-server/server-health-checker/pom.xml +++ b/iot-server/server-health-checker/pom.xml @@ -15,7 +15,7 @@ com.zmops library-module - 1.0-beta + 1.0.3-RELEASE compile diff --git a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/module/HealthCheckerModule.java b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/module/HealthCheckerModule.java index 7a9da970..1dbc5dd8 100644 --- a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/module/HealthCheckerModule.java +++ b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/module/HealthCheckerModule.java @@ -19,7 +19,7 @@ package com.zmops.zeus.iot.server.health.checker.module; import com.zmops.zeus.iot.server.health.checker.provider.HealthQueryService; -import com.zmops.zeus.iot.server.library.module.ModuleDefine; +import com.zmops.zeus.server.library.module.ModuleDefine; /** * HealthCheckerModule intends to provide a channel to expose the healthy status of modules to external. diff --git a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerConfig.java b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerConfig.java index 1b15ef8b..84c30b82 100644 --- a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerConfig.java +++ b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerConfig.java @@ -18,7 +18,7 @@ package com.zmops.zeus.iot.server.health.checker.provider; -import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import com.zmops.zeus.server.library.module.ModuleConfig; import lombok.Getter; diff --git a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java index 8a7faa6e..54aec501 100644 --- a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java +++ b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthCheckerProvider.java @@ -20,15 +20,13 @@ import com.google.common.util.concurrent.AtomicDouble; import com.zmops.zeus.iot.server.health.checker.module.HealthCheckerModule; -import com.zmops.zeus.iot.server.library.module.*; - import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; +import com.zmops.zeus.server.library.module.*; import io.vavr.collection.Stream; import lombok.extern.slf4j.Slf4j; - import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -41,12 +39,12 @@ */ @Slf4j public class HealthCheckerProvider extends ModuleProvider { - private final AtomicDouble score = new AtomicDouble(); - private final AtomicReference details = new AtomicReference<>(); - private final HealthCheckerConfig config = new HealthCheckerConfig(); - private MetricsCollector collector; - private MetricsCreator metricsCreator; - private ScheduledExecutorService ses; + private final AtomicDouble score = new AtomicDouble(); + private final AtomicReference details = new AtomicReference<>(); + private final HealthCheckerConfig config = new HealthCheckerConfig(); + private MetricsCollector collector; + private MetricsCreator metricsCreator; + private ScheduledExecutorService ses; @Override public String name() { diff --git a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java index 46cfd820..7db5b1e1 100644 --- a/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java +++ b/iot-server/server-health-checker/src/main/java/com/zmops/zeus/iot/server/health/checker/provider/HealthQueryService.java @@ -19,17 +19,16 @@ package com.zmops.zeus.iot.server.health.checker.provider; import com.google.common.util.concurrent.AtomicDouble; -import com.zmops.zeus.iot.server.library.module.Service; +import com.zmops.zeus.server.library.module.Service; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; - import java.util.concurrent.atomic.AtomicReference; @RequiredArgsConstructor public class HealthQueryService implements Service { - private final AtomicDouble score; + private final AtomicDouble score; private final AtomicReference details; public HealthStatus checkHealth() { @@ -44,7 +43,7 @@ public HealthStatus checkHealth() { @Setter static class HealthStatus { // score == 0 means healthy, otherwise it's unhealthy. - private int score; + private int score; private String details; } } diff --git a/iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine similarity index 100% rename from iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine diff --git a/iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-health-checker/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ApplicationConfiguration.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ApplicationConfiguration.java deleted file mode 100644 index 0d205b67..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ApplicationConfiguration.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.module; - -import java.util.HashMap; -import java.util.Properties; - -/** - * Modulization configurations. The {@link ModuleManager} is going to start, lookup, start modules based on this. - */ -public class ApplicationConfiguration { - private HashMap modules = new HashMap<>(); - - public String[] moduleList() { - return modules.keySet().toArray(new String[0]); - } - - public ModuleConfiguration addModule(String moduleName) { - ModuleConfiguration newModule = new ModuleConfiguration(); - modules.put(moduleName, newModule); - return newModule; - } - - public boolean has(String moduleName) { - return modules.containsKey(moduleName); - } - - public ModuleConfiguration getModuleConfiguration(String name) { - return modules.get(name); - } - - /** - * The configurations about a certain module. - */ - public static class ModuleConfiguration { - private HashMap providers = new HashMap<>(); - - private ModuleConfiguration() { - } - - public Properties getProviderConfiguration(String name) { - return providers.get(name).getProperties(); - } - - public boolean has(String name) { - return providers.containsKey(name); - } - - public ModuleConfiguration addProviderConfiguration(String name, Properties properties) { - ProviderConfiguration newProvider = new ProviderConfiguration(properties); - providers.put(name, newProvider); - return this; - } - } - - /** - * The configuration about a certain provider of a module. - */ - public static class ProviderConfiguration { - private Properties properties; - - ProviderConfiguration(Properties properties) { - this.properties = properties; - } - - private Properties getProperties() { - return properties; - } - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java deleted file mode 100644 index dbea1943..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/BootstrapFlow.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.module; - -import com.zmops.zeus.iot.server.library.util.CollectionUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -class BootstrapFlow { - private static final Logger LOGGER = LoggerFactory.getLogger(BootstrapFlow.class); - - private Map loadedModules; - private List startupSequence; - - BootstrapFlow(Map loadedModules) throws CycleDependencyException, ModuleNotFoundException { - this.loadedModules = loadedModules; - startupSequence = new LinkedList<>(); - - makeSequence(); - } - - @SuppressWarnings("unchecked") - void start(ModuleManager moduleManager) throws ModuleNotFoundException, ServiceNotProvidedException, ModuleStartException { - for (ModuleProvider provider : startupSequence) { - LOGGER.info("start the provider {} in {} module.", provider.name(), provider.getModuleName()); - provider.requiredCheck(provider.getModule().services()); - provider.start(); - } - } - - void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { - for (ModuleProvider provider : startupSequence) { - provider.notifyAfterCompleted(); - } - } - - private void makeSequence() throws CycleDependencyException, ModuleNotFoundException { - List allProviders = new ArrayList<>(); - for (final ModuleDefine module : loadedModules.values()) { - String[] requiredModules = module.provider().requiredModules(); - if (requiredModules != null) { - for (String requiredModule : requiredModules) { - if (!loadedModules.containsKey(requiredModule)) { - throw new ModuleNotFoundException( - requiredModule + " module is required by " - + module.provider().getModuleName() + "." - + module.provider().name() + ", but not found."); - } - } - } - allProviders.add(module.provider()); - } - - do { - int numOfToBeSequenced = allProviders.size(); - for (int i = 0; i < allProviders.size(); i++) { - ModuleProvider provider = allProviders.get(i); - String[] requiredModules = provider.requiredModules(); - if (CollectionUtils.isNotEmpty(requiredModules)) { - boolean isAllRequiredModuleStarted = true; - for (String module : requiredModules) { - // find module in all ready existed startupSequence - boolean exist = false; - for (ModuleProvider moduleProvider : startupSequence) { - if (moduleProvider.getModuleName().equals(module)) { - exist = true; - break; - } - } - if (!exist) { - isAllRequiredModuleStarted = false; - break; - } - } - if (isAllRequiredModuleStarted) { - startupSequence.add(provider); - allProviders.remove(i); - i--; - } - } else { - startupSequence.add(provider); - allProviders.remove(i); - i--; - } - } - - if (numOfToBeSequenced == allProviders.size()) { - StringBuilder unSequencedProviders = new StringBuilder(); - allProviders.forEach(provider -> unSequencedProviders.append(provider.getModuleName()).append("[provider=").append(provider.getClass().getName()).append("]\n")); - if (unSequencedProviders.length() > 0) { - throw new CycleDependencyException("Exist cycle module dependencies in \n" + unSequencedProviders.substring(0, unSequencedProviders.length() - 1)); - } - } - } - while (allProviders.size() != 0); - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java deleted file mode 100644 index ebe29a22..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefine.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.module; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Field; -import java.util.Enumeration; -import java.util.Properties; -import java.util.ServiceLoader; - -/** - * A module definition. - */ -public abstract class ModuleDefine implements ModuleProviderHolder { - - private static final Logger LOGGER = LoggerFactory.getLogger(ModuleDefine.class); - - private ModuleProvider loadedProvider = null; - - private final String name; - - public ModuleDefine(String name) { - this.name = name; - } - - /** - * @return the module name - */ - public final String name() { - return name; - } - - /** - * @return the {@link Service} provided by this module. - */ - public abstract Class[] services(); - - /** - * Run the prepare stage for the module, including finding all potential providers, and asking them to prepare. - * - * @param moduleManager of this module - * @param configuration of this module - * @throws ProviderNotFoundException when even don't find a single one providers. - */ - void prepare(ModuleManager moduleManager, ApplicationConfiguration.ModuleConfiguration configuration, - ServiceLoader moduleProviderLoader) throws ProviderNotFoundException, ServiceNotProvidedException, ModuleConfigException, ModuleStartException { - for (ModuleProvider provider : moduleProviderLoader) { - if (!configuration.has(provider.name())) { - continue; - } - - if (provider.module().equals(getClass())) { - if (loadedProvider == null) { - loadedProvider = provider; - loadedProvider.setManager(moduleManager); - loadedProvider.setModuleDefine(this); - } else { - throw new DuplicateProviderException(this.name() + " module has one " + loadedProvider.name() + "[" + loadedProvider - .getClass() - .getName() + "] provider already, " + provider.name() + "[" + provider.getClass() - .getName() + "] is defined as 2nd provider."); - } - } - - } - - if (loadedProvider == null) { - throw new ProviderNotFoundException(this.name() + " module no provider found."); - } - - LOGGER.info("Prepare the {} provider in {} module.", loadedProvider.name(), this.name()); - try { - copyProperties(loadedProvider.createConfigBeanIfAbsent(), configuration.getProviderConfiguration(loadedProvider.name()), this.name(), loadedProvider.name()); - } catch (IllegalAccessException e) { - throw new ModuleConfigException(this.name() + " module config transport to config bean failure.", e); - } - loadedProvider.prepare(); - } - - private void copyProperties(ModuleConfig dest, Properties src, String moduleName, - String providerName) throws IllegalAccessException { - if (dest == null) { - return; - } - Enumeration propertyNames = src.propertyNames(); - while (propertyNames.hasMoreElements()) { - String propertyName = (String) propertyNames.nextElement(); - Class destClass = dest.getClass(); - try { - Field field = getDeclaredField(destClass, propertyName); - field.setAccessible(true); - field.set(dest, src.get(propertyName)); - } catch (NoSuchFieldException e) { - LOGGER.warn(propertyName + " setting is not supported in " + providerName + " provider of " + moduleName + " module"); - } - } - } - - private Field getDeclaredField(Class destClass, String fieldName) throws NoSuchFieldException { - if (destClass != null) { - Field[] fields = destClass.getDeclaredFields(); - for (Field field : fields) { - if (field.getName().equals(fieldName)) { - return field; - } - } - return getDeclaredField(destClass.getSuperclass(), fieldName); - } - - throw new NoSuchFieldException(); - } - - @Override - public final ModuleProvider provider() throws DuplicateProviderException, ProviderNotFoundException { - if (loadedProvider == null) { - throw new ProviderNotFoundException("There is no module provider in " + this.name() + " module!"); - } - - return loadedProvider; - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefineHolder.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefineHolder.java deleted file mode 100644 index 3021a6d2..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleDefineHolder.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.module; - -public interface ModuleDefineHolder { - - boolean has(String moduleName); - - ModuleProviderHolder find(String moduleName) throws ModuleNotFoundRuntimeException; -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java deleted file mode 100644 index 53c67145..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleManager.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.module; - -import java.util.*; - -/** - * The ModuleManager takes charge of all {@link ModuleDefine}s in collector. - */ -public class ModuleManager implements ModuleDefineHolder { - private boolean isInPrepareStage = true; - private final Map loadedModules = new HashMap<>(); - - /** - * Init the given modules - */ - public void init(ApplicationConfiguration applicationConfiguration) - throws ModuleNotFoundException, ProviderNotFoundException, ServiceNotProvidedException, CycleDependencyException, ModuleConfigException, ModuleStartException { - - String[] moduleNames = applicationConfiguration.moduleList(); - ServiceLoader moduleServiceLoader = ServiceLoader.load(ModuleDefine.class); - ServiceLoader moduleProviderLoader = ServiceLoader.load(ModuleProvider.class); - - HashSet moduleSet = new HashSet<>(Arrays.asList(moduleNames)); - for (ModuleDefine module : moduleServiceLoader) { - if (moduleSet.contains(module.name())) { - module.prepare(this, applicationConfiguration.getModuleConfiguration(module.name()), moduleProviderLoader); - loadedModules.put(module.name(), module); - moduleSet.remove(module.name()); - } - } - // Finish prepare stage - isInPrepareStage = false; - - if (moduleSet.size() > 0) { - throw new ModuleNotFoundException(moduleSet.toString() + " missing."); - } - - BootstrapFlow bootstrapFlow = new BootstrapFlow(loadedModules); - - bootstrapFlow.start(this); - bootstrapFlow.notifyAfterCompleted(); - } - - @Override - public boolean has(String moduleName) { - return loadedModules.get(moduleName) != null; - } - - @Override - public ModuleProviderHolder find(String moduleName) throws ModuleNotFoundRuntimeException { - assertPreparedStage(); - ModuleDefine module = loadedModules.get(moduleName); - if (module != null) - return module; - throw new ModuleNotFoundRuntimeException(moduleName + " missing."); - } - - private void assertPreparedStage() { - if (isInPrepareStage) { - throw new AssertionError("Still in preparing stage."); - } - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundRuntimeException.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundRuntimeException.java deleted file mode 100644 index a01cb99b..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleNotFoundRuntimeException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.module; - -public class ModuleNotFoundRuntimeException extends RuntimeException { - - public ModuleNotFoundRuntimeException(Throwable cause) { - super(cause); - } - - public ModuleNotFoundRuntimeException(String message) { - super(message); - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProvider.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProvider.java deleted file mode 100644 index 5eb42d49..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProvider.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.module; - -import lombok.Setter; - -import java.util.HashMap; -import java.util.Map; - -/** - * The ModuleProvider is an implementation of a {@link ModuleDefine}. - *

- * And each moduleDefine can have one or more implementation, which depends on `application.yml` - */ -public abstract class ModuleProvider implements ModuleServiceHolder { - @Setter - private ModuleManager manager; - @Setter - private ModuleDefine moduleDefine; - private final Map, Service> services = new HashMap<>(); - - public ModuleProvider() { - } - - protected final ModuleManager getManager() { - return manager; - } - - /** - * @return the name of this provider. - */ - public abstract String name(); - - /** - * @return the moduleDefine name - */ - public abstract Class module(); - - /** - * - */ - public abstract ModuleConfig createConfigBeanIfAbsent(); - - /** - * In prepare stage, the moduleDefine should initialize things which are irrelative other modules. - */ - public abstract void prepare() throws ServiceNotProvidedException, ModuleStartException; - - /** - * In start stage, the moduleDefine has been ready for interop. - */ - public abstract void start() throws ServiceNotProvidedException, ModuleStartException; - - /** - * This callback executes after all modules start up successfully. - */ - public abstract void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException; - - /** - * @return moduleDefine names which does this moduleDefine require? - */ - public abstract String[] requiredModules(); - - /** - * Register an implementation for the service of this moduleDefine provider. - */ - @Override - public final void registerServiceImplementation(Class serviceType, Service service) throws ServiceNotProvidedException { - if (serviceType.isInstance(service)) { - this.services.put(serviceType, service); - } else { - throw new ServiceNotProvidedException(serviceType + " is not implemented by " + service); - } - } - - /** - * Make sure all required services have been implemented. - * - * @param requiredServices must be implemented by the moduleDefine. - * @throws ServiceNotProvidedException when exist unimplemented service. - */ - void requiredCheck(Class[] requiredServices) throws ServiceNotProvidedException { - if (requiredServices == null) - return; - - for (Class service : requiredServices) { - if (!services.containsKey(service)) { - throw new ServiceNotProvidedException("Service:" + service.getName() + " not provided"); - } - } - - if (requiredServices.length != services.size()) { - throw new ServiceNotProvidedException("The " + this.name() + " provider in " + moduleDefine.name() + " moduleDefine provide more service implementations than ModuleDefine requirements."); - } - } - - @Override - public @SuppressWarnings("unchecked") - T getService(Class serviceType) throws ServiceNotProvidedException { - Service serviceImpl = services.get(serviceType); - if (serviceImpl != null) { - return (T) serviceImpl; - } - - throw new ServiceNotProvidedException("Service " + serviceType.getName() + " should not be provided, based on moduleDefine define."); - } - - ModuleDefine getModule() { - return moduleDefine; - } - - String getModuleName() { - return moduleDefine.name(); - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProviderHolder.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProviderHolder.java deleted file mode 100644 index dc379f9c..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleProviderHolder.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.module; - -public interface ModuleProviderHolder { - - ModuleServiceHolder provider() throws DuplicateProviderException, ProviderNotFoundException; -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleServiceHolder.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleServiceHolder.java deleted file mode 100644 index d7a2865e..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ModuleServiceHolder.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.module; - -public interface ModuleServiceHolder { - - void registerServiceImplementation(Class serviceType, Service service) throws ServiceNotProvidedException; - - T getService(Class serviceType) throws ServiceNotProvidedException; -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ProviderNotFoundException.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ProviderNotFoundException.java deleted file mode 100644 index 8877a1a5..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ProviderNotFoundException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.module; - -public class ProviderNotFoundException extends RuntimeException { - - public ProviderNotFoundException(String message) { - super(message); - } - - public ProviderNotFoundException(Throwable e) { - super(e); - } -} diff --git a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ServiceNotProvidedException.java b/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ServiceNotProvidedException.java deleted file mode 100644 index 31b189bb..00000000 --- a/iot-server/server-library/library-module/src/main/java/com/zmops/zeus/iot/server/library/module/ServiceNotProvidedException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.module; - -public class ServiceNotProvidedException extends RuntimeException { - public ServiceNotProvidedException(String message) { - super(message); - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/Server.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/Server.java deleted file mode 100644 index 2e7a465d..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/Server.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.server; - -public interface Server { - - String hostPort(); - - String serverClassify(); - - void initialize(); - - void start() throws ServerException; - - boolean isSSLOpen(); - - boolean isStatusEqual(Server target); -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyHandler.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyHandler.java deleted file mode 100644 index e8c61858..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.server.jetty; - -import com.zmops.zeus.iot.server.library.server.ServerHandler; - -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -public abstract class JettyHandler extends HttpServlet implements ServerHandler { - - public abstract String pathSpec(); - - @Override - protected final void service(HttpServletRequest req, - HttpServletResponse resp) throws ServletException, IOException { - String method = req.getMethod(); - - // 只支持 Post 和 Get - if (method.equals("POST") || method.equals("GET")) { - super.service(req, resp); - } else { - resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); - } - } - - @Override - public final void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { - super.service(req, res); - } - - @Override - protected final void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - super.doHead(req, resp); - } - - @Override - protected final void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - super.doPut(req, resp); - } - - @Override - protected final void doDelete(HttpServletRequest req, - HttpServletResponse resp) throws ServletException, IOException { - super.doDelete(req, resp); - } - - @Override - protected final void doOptions(HttpServletRequest req, - HttpServletResponse resp) throws ServletException, IOException { - super.doOptions(req, resp); - } - - @Override - protected final void doTrace(HttpServletRequest req, - HttpServletResponse resp) throws ServletException, IOException { - super.doTrace(req, resp); - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyJsonHandler.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyJsonHandler.java deleted file mode 100644 index d9326ed9..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyJsonHandler.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.server.jetty; - -import com.google.gson.JsonElement; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.PrintWriter; - -import static java.util.Objects.nonNull; - -/** - * @author nantian Jetty JSON 处理逻辑 - */ -public abstract class JettyJsonHandler extends JettyHandler { - private static final Logger LOGGER = LoggerFactory.getLogger(JettyJsonHandler.class); - - @Override - protected final void doPost(HttpServletRequest req, HttpServletResponse resp) { - try { - reply(resp, doPost(req)); - } catch (ArgumentsParseException | IOException e) { - try { - replyError(resp, e.getMessage(), HttpServletResponse.SC_BAD_REQUEST); - } catch (IOException replyException) { - LOGGER.error(replyException.getMessage(), e); - } - } - } - - protected abstract JsonElement doPost(HttpServletRequest req) throws ArgumentsParseException, IOException; - - private void reply(HttpServletResponse response, JsonElement resJson) throws IOException { - response.setContentType("application/json"); - response.setCharacterEncoding("utf-8"); - response.setStatus(HttpServletResponse.SC_OK); - - PrintWriter out = response.getWriter(); - if (nonNull(resJson)) { - out.print(resJson); - } - out.flush(); - out.close(); - } - - private void replyError(HttpServletResponse response, String errorMessage, int status) throws IOException { - response.setContentType("application/json"); - response.setCharacterEncoding("utf-8"); - response.setStatus(status); - response.setHeader("error-message", errorMessage); - - PrintWriter out = response.getWriter(); - out.flush(); - out.close(); - } - - public String getJsonBody(HttpServletRequest req) throws IOException { - StringBuffer stringBuffer = new StringBuffer(); - String line = null; - BufferedReader reader = req.getReader(); - while ((line = reader.readLine()) != null) { - stringBuffer.append(line); - } - return stringBuffer.toString(); - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServer.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServer.java deleted file mode 100644 index e1368b67..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServer.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.server.jetty; - - -import com.zmops.zeus.iot.server.library.server.Server; -import com.zmops.zeus.iot.server.library.server.ServerException; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpConnectionFactory; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.handler.gzip.GzipHandler; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.servlet.ServletMapping; -import org.eclipse.jetty.util.thread.QueuedThreadPool; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Objects; - -public class JettyServer implements Server { - - private static final Logger LOGGER = LoggerFactory.getLogger(JettyServer.class); - - private org.eclipse.jetty.server.Server server; - private ServletContextHandler servletContextHandler; - private JettyServerConfig jettyServerConfig; - - public JettyServer(JettyServerConfig config) { - this.jettyServerConfig = config; - } - - @Override - public String hostPort() { - return jettyServerConfig.getHost() + ":" + jettyServerConfig.getPort(); - } - - @Override - public String serverClassify() { - return "Jetty"; - } - - @Override - public void initialize() { - QueuedThreadPool threadPool = new QueuedThreadPool(); - threadPool.setMinThreads(jettyServerConfig.getJettyMinThreads()); - threadPool.setMaxThreads(jettyServerConfig.getJettyMaxThreads()); - - server = new org.eclipse.jetty.server.Server(threadPool); - - HttpConfiguration httpConfiguration = new HttpConfiguration(); - - GzipHandler gzipHandler = new GzipHandler(); - server.setHandler(gzipHandler); - - - httpConfiguration.setRequestHeaderSize(jettyServerConfig.getJettyHttpMaxRequestHeaderSize()); - - ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory(httpConfiguration)); - connector.setHost(jettyServerConfig.getHost()); - connector.setPort(jettyServerConfig.getPort()); - connector.setIdleTimeout(jettyServerConfig.getJettyIdleTimeOut()); - connector.setAcceptorPriorityDelta(jettyServerConfig.getJettyAcceptorPriorityDelta()); - connector.setAcceptQueueSize(jettyServerConfig.getJettyAcceptQueueSize()); - server.setConnectors(new Connector[]{connector}); - - servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS); - servletContextHandler.setContextPath(jettyServerConfig.getContextPath()); - LOGGER.info("http server root context path: {}", jettyServerConfig.getContextPath()); - - server.setHandler(servletContextHandler); - - JettyDefaultHandler defaultHandler = new JettyDefaultHandler(); - ServletHolder defaultHolder = new ServletHolder(); - defaultHolder.setServlet(defaultHandler); - - servletContextHandler.addServlet(defaultHolder, defaultHandler.pathSpec()); - } - - public void addHandler(JettyHandler handler) { - LOGGER.info( - "Bind handler {} into jetty server {}:{}", - handler.getClass().getSimpleName(), jettyServerConfig.getHost(), jettyServerConfig.getPort() - ); - - ServletHolder servletHolder = new ServletHolder(); - servletHolder.setServlet(handler); - servletContextHandler.addServlet(servletHolder, handler.pathSpec()); - } - - @Override - public boolean isSSLOpen() { - return false; - } - - @Override - public boolean isStatusEqual(Server target) { - return equals(target); - } - - @Override - public void start() throws ServerException { - LOGGER.info("start server, host: {}, port: {}", jettyServerConfig.getHost(), jettyServerConfig.getPort()); - try { - if (LOGGER.isDebugEnabled()) { - if (servletContextHandler.getServletHandler() != null && servletContextHandler.getServletHandler().getServletMappings() != null) { - - for (ServletMapping servletMapping : servletContextHandler.getServletHandler().getServletMappings()) { - LOGGER.debug("jetty servlet mappings: {} register by {}", servletMapping.getPathSpecs(), servletMapping.getServletName()); - } - - } - } - - server.start(); - } catch (Exception e) { - throw new JettyServerException(e.getMessage(), e); - } - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - JettyServer that = (JettyServer) o; - return jettyServerConfig.getPort() == that.jettyServerConfig.getPort() - && Objects.equals(jettyServerConfig.getHost(), that.jettyServerConfig.getHost()); - } - - @Override - public int hashCode() { - return Objects.hash(jettyServerConfig.getHost(), jettyServerConfig.getPort()); - } - -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerConfig.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerConfig.java deleted file mode 100644 index 7aa2f177..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerConfig.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.server.jetty; - -import lombok.Builder; -import lombok.Getter; -import lombok.Setter; - -@Setter -@Getter -@Builder -public class JettyServerConfig { - - private String host; - private int port; - private String contextPath; - - @Builder.Default - private int jettyMinThreads = 1; - @Builder.Default - private int jettyMaxThreads = 200; - @Builder.Default - private long jettyIdleTimeOut = 30000; - @Builder.Default - private int jettyAcceptorPriorityDelta = 0; - @Builder.Default - private int jettyAcceptQueueSize = 0; - @Builder.Default - private int jettyHttpMaxRequestHeaderSize = 8192; -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerException.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerException.java deleted file mode 100644 index 5d809d1b..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/jetty/JettyServerException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.server.jetty; - -import com.zmops.zeus.iot.server.library.server.ServerException; - -public class JettyServerException extends ServerException { - - public JettyServerException(String message) { - super(message); - } - - public JettyServerException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/pool/CustomThreadFactory.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/pool/CustomThreadFactory.java deleted file mode 100644 index 7cafdebf..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/pool/CustomThreadFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.server.pool; - -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -public class CustomThreadFactory implements ThreadFactory { - private final AtomicInteger poolNumber = new AtomicInteger(1); - private final ThreadGroup group; - private final AtomicInteger threadNumber = new AtomicInteger(1); - private final String namePrefix; - - public CustomThreadFactory(String name) { - SecurityManager s = System.getSecurityManager(); - group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); - namePrefix = name + "-" + poolNumber.getAndIncrement() + "-thread-"; - } - - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); - if (t.isDaemon()) - t.setDaemon(false); - if (t.getPriority() != Thread.NORM_PRIORITY) - t.setPriority(Thread.NORM_PRIORITY); - return t; - } -} \ No newline at end of file diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/AbstractSslContext.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/AbstractSslContext.java deleted file mode 100644 index 466d5b31..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/AbstractSslContext.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.server.ssl; - -import com.zmops.zeus.iot.server.library.util.MultipleFilesChangeMonitor; -import io.netty.buffer.ByteBufAllocator; -import io.netty.handler.ssl.ApplicationProtocolNegotiator; -import io.netty.handler.ssl.SslContext; -import lombok.AccessLevel; -import lombok.Setter; - - -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLSessionContext; -import java.util.List; - -public abstract class AbstractSslContext extends SslContext { - private final MultipleFilesChangeMonitor monitor; - - @Setter(AccessLevel.PROTECTED) - private volatile SslContext ctx; - - protected AbstractSslContext(final String privateKeyFile, final String certChainFile) { - updateContext(privateKeyFile, certChainFile); - monitor = new MultipleFilesChangeMonitor( - 10, - readableContents -> updateContext(privateKeyFile, certChainFile), - certChainFile, - privateKeyFile); - } - - protected AbstractSslContext(final String caFile) { - updateContext(caFile); - monitor = new MultipleFilesChangeMonitor( - 10, - readableContents -> updateContext(caFile), - caFile); - } - - protected abstract void updateContext(String caFile); - - protected abstract void updateContext(final String privateKeyFile, final String certChainFile); - - public void start() { - monitor.start(); - } - - @Override - public final boolean isClient() { - return ctx.isClient(); - } - - @Override - public final List cipherSuites() { - return ctx.cipherSuites(); - } - - @Override - public final long sessionCacheSize() { - return ctx.sessionCacheSize(); - } - - @Override - public final long sessionTimeout() { - return ctx.sessionTimeout(); - } - - @Override - public final ApplicationProtocolNegotiator applicationProtocolNegotiator() { - return ctx.applicationProtocolNegotiator(); - } - - @Override - public final SSLEngine newEngine(ByteBufAllocator alloc) { - return ctx.newEngine(alloc); - } - - @Override - public final SSLEngine newEngine(ByteBufAllocator alloc, String peerHost, int peerPort) { - return ctx.newEngine(alloc, peerHost, peerPort); - } - - @Override - public final SSLSessionContext sessionContext() { - return ctx.sessionContext(); - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/HttpDynamicSslContext.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/HttpDynamicSslContext.java deleted file mode 100644 index 2fe8cd76..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/HttpDynamicSslContext.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.server.ssl; - -import io.netty.handler.ssl.SslContextBuilder; - -import javax.net.ssl.SSLException; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.file.Paths; -import java.security.GeneralSecurityException; - -public class HttpDynamicSslContext extends AbstractSslContext { - - public static HttpDynamicSslContext forServer(String privateKeyFile, String certChainFile) { - return new HttpDynamicSslContext(privateKeyFile, certChainFile); - } - - public static HttpDynamicSslContext forClient(String caFile) { - return new HttpDynamicSslContext(caFile); - } - - protected HttpDynamicSslContext(String privateKeyFile, String certChainFile) { - super(privateKeyFile, certChainFile); - } - - protected HttpDynamicSslContext(String caFile) { - super(caFile); - } - - @Override - protected void updateContext(String caFile) { - try { - setCtx(SslContextBuilder.forClient().trustManager(Paths.get(caFile).toFile()).build()); - } catch (SSLException e) { - throw new IllegalArgumentException(e); - } - } - - @Override - protected void updateContext(final String privateKeyFile, final String certChainFile) { - try { - setCtx(SslContextBuilder - .forServer( - new FileInputStream(Paths.get(certChainFile).toFile()), - PrivateKeyUtil.loadDecryptionKey(privateKeyFile)).build()); - } catch (GeneralSecurityException | IOException e) { - throw new IllegalArgumentException(e); - } - } -} diff --git a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/PrivateKeyUtil.java b/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/PrivateKeyUtil.java deleted file mode 100644 index fa9b5fa3..00000000 --- a/iot-server/server-library/library-server/src/main/java/com/zmops/zeus/iot/server/library/server/ssl/PrivateKeyUtil.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.server.ssl; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.GeneralSecurityException; -import java.util.Base64; - -/** - * Util intends to parse PKCS#1 and PKCS#8 at same time. - */ -public class PrivateKeyUtil { - private static final String PKCS_1_PEM_HEADER = "-----BEGIN RSA PRIVATE KEY-----"; - private static final String PKCS_1_PEM_FOOTER = "-----END RSA PRIVATE KEY-----"; - private static final String PKCS_8_PEM_HEADER = "-----BEGIN PRIVATE KEY-----"; - private static final String PKCS_8_PEM_FOOTER = "-----END PRIVATE KEY-----"; - - /** - * Load a RSA decryption key from a file (PEM or DER). - */ - public static InputStream loadDecryptionKey(String keyFilePath) throws GeneralSecurityException, IOException { - byte[] keyDataBytes = Files.readAllBytes(Paths.get(keyFilePath)); - String keyDataString = new String(keyDataBytes, StandardCharsets.UTF_8); - - if (keyDataString.contains(PKCS_1_PEM_HEADER)) { - // OpenSSL / PKCS#1 Base64 PEM encoded file - keyDataString = keyDataString.replace(PKCS_1_PEM_HEADER, ""); - keyDataString = keyDataString.replace(PKCS_1_PEM_FOOTER, ""); - keyDataString = keyDataString.replace("\n", ""); - return readPkcs1PrivateKey(Base64.getDecoder().decode(keyDataString)); - } - - return new ByteArrayInputStream(keyDataString.getBytes()); - } - - /** - * Create a InputStream instance from raw PKCS#1 bytes. Raw Java API can't recognize ASN.1 format, so we should - * convert it into a pkcs#8 format Java can understand. - */ - private static InputStream readPkcs1PrivateKey(byte[] pkcs1Bytes) throws GeneralSecurityException { - int pkcs1Length = pkcs1Bytes.length; - int totalLength = pkcs1Length + 22; - byte[] pkcs8Header = new byte[]{ - 0x30, (byte) 0x82, (byte) ((totalLength >> 8) & 0xff), (byte) (totalLength & 0xff), // Sequence + total length - 0x2, 0x1, 0x0, // Integer (0) - 0x30, 0xD, 0x6, 0x9, 0x2A, (byte) 0x86, 0x48, (byte) 0x86, (byte) 0xF7, 0xD, 0x1, 0x1, 0x1, 0x5, 0x0, // Sequence: 1.2.840.113549.1.1.1, NULL - 0x4, (byte) 0x82, (byte) ((pkcs1Length >> 8) & 0xff), (byte) (pkcs1Length & 0xff) // Octet string + length - }; - StringBuilder pkcs8 = new StringBuilder(PKCS_8_PEM_HEADER); - pkcs8.append("\n").append(new String(Base64.getEncoder().encode(join(pkcs8Header, pkcs1Bytes)))); - pkcs8.append("\n").append(PKCS_8_PEM_FOOTER); - return new ByteArrayInputStream(pkcs8.toString().getBytes()); - } - - private static byte[] join(byte[] byteArray1, byte[] byteArray2) { - byte[] bytes = new byte[byteArray1.length + byteArray2.length]; - System.arraycopy(byteArray1, 0, bytes, 0, byteArray1.length); - System.arraycopy(byteArray2, 0, bytes, byteArray1.length, byteArray2.length); - return bytes; - } -} diff --git a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/CollectionUtils.java b/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/CollectionUtils.java deleted file mode 100644 index 855f093e..00000000 --- a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/CollectionUtils.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.util; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class CollectionUtils { - - public static boolean isEmpty(Map map) { - return map == null || map.size() == 0; - } - - public static boolean isEmpty(List list) { - return list == null || list.size() == 0; - } - - public static boolean isEmpty(Set set) { - return set == null || set.size() == 0; - } - - public static boolean isNotEmpty(List list) { - return !isEmpty(list); - } - - public static boolean isNotEmpty(Set set) { - return !isEmpty(set); - } - - public static boolean isNotEmpty(Map map) { - return !isEmpty(map); - } - - public static boolean isNotEmpty(T[] array) { - return array != null && array.length > 0; - } - - public static boolean isEmpty(byte[] array) { - return array == null || array.length == 0; - } - - public static boolean isNotEmpty(byte[] array) { - return !isEmpty(array); - } -} diff --git a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/MultipleFilesChangeMonitor.java b/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/MultipleFilesChangeMonitor.java deleted file mode 100644 index 71f90d3a..00000000 --- a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/MultipleFilesChangeMonitor.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.util; - -import com.zmops.zeus.iot.server.util.StringUtil; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import java.io.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; - -/** - * MultipleFilesChangeMonitor provides the capability to detect file or multiple files changed. It provide second level - * change detection and feedback mechanism. - *

- * Due to memory cost, this monitor mechanism is not suitable for small files and usually being changed on the runtime - * by user manually or 3rd party tool. Typical, these files are config information or authentication files. - */ -@Slf4j -public class MultipleFilesChangeMonitor { - /** - * The backend scheduler to trigger all file monitoring. - */ - private static ScheduledFuture FILE_MONITOR_TASK_SCHEDULER; - private static final ReentrantLock SCHEDULER_CHANGE_LOCK = new ReentrantLock(); - /** - * The list contains all monitors. - */ - private static final List MONITOR_INSTANCES = new ArrayList<>(); - - /** - * The timestamp when last time do status checked. - */ - private long lastCheckTimestamp = 0; - /** - * The period of watching thread checking the file status. Unit is the second. - */ - private final long watchingPeriodInSec; - private final List watchedFiles; - private final FilesChangedNotifier notifier; - - /** - * Create a new monitor for the given files - * - * @param watchingPeriodInSec The check period. - * @param notifier to accept the file changed notification. - * @param files to be monitored. If an element of list is NULL, the virtual(NULL) file is treated - * unchangeable. - */ - public MultipleFilesChangeMonitor(long watchingPeriodInSec, - FilesChangedNotifier notifier, - String... files) { - watchedFiles = new ArrayList<>(); - this.watchingPeriodInSec = watchingPeriodInSec; - this.notifier = notifier; - for (final String file : files) { - WatchedFile monitor; - if (StringUtil.isEmpty(file)) { - monitor = new NoopWatchedFile(); - } else { - monitor = new WatchedFile(file); - } - watchedFiles.add(monitor); - } - } - - /** - * Check file changed status, if so, send the notification. - */ - private void checkAndNotify() { - if (System.currentTimeMillis() - lastCheckTimestamp < watchingPeriodInSec * 1000) { - // Don't reach the period threshold, ignore this check. - return; - } - - boolean isChanged = false; - for (final WatchedFile watchedFile : watchedFiles) { - isChanged = isChanged || watchedFile.detectContentChanged(); - } - if (isChanged) { - List contents = new ArrayList<>(watchedFiles.size()); - watchedFiles.forEach(file -> { - contents.add(file.fileContent); - }); - try { - notifier.filesChanged(contents); - } catch (Exception e) { - log.error("Files=" + this + " notification process failure.", e); - } - } - } - - /** - * One file changed will cause all related files loaded from the disk again with lastModifiedTimestamp updated. - */ - public static void scanChanges() { - MONITOR_INSTANCES.forEach(group -> { - try { - group.checkAndNotify(); - } catch (Throwable t) { - log.error("Files change detection failure, gourp = ", t); - } - }); - } - - /** - * Start the change monitoring. - */ - public void start() { - SCHEDULER_CHANGE_LOCK.lock(); - try { - if (FILE_MONITOR_TASK_SCHEDULER == null) { - FILE_MONITOR_TASK_SCHEDULER = Executors.newSingleThreadScheduledExecutor() - .scheduleAtFixedRate( - MultipleFilesChangeMonitor::scanChanges, 1, 200, - TimeUnit.MILLISECONDS - ); - } - - if (MONITOR_INSTANCES.contains(this)) { - throw new IllegalStateException("This FileChangeMonitor has been started."); - } - - this.checkAndNotify(); - MONITOR_INSTANCES.add(this); - } finally { - SCHEDULER_CHANGE_LOCK.unlock(); - } - } - - /** - * Stop the change monitoring. - */ - public void stop() { - SCHEDULER_CHANGE_LOCK.lock(); - try { - MONITOR_INSTANCES.remove(this); - } finally { - SCHEDULER_CHANGE_LOCK.unlock(); - } - } - - @Override - public String toString() { - return "MultipleFilesChangeMonitor{" + - "watchedFiles=" + watchedFiles + - '}'; - } - - /** - * The callback when files changed. - */ - public interface FilesChangedNotifier { - /** - * Notify the new content by providing the file input stream for all files in this group. - * - * @param readableContents include the new contents. NULL if the file doesn't exist. - */ - void filesChanged(List readableContents) throws Exception; - } - - /** - * WatchedFile represents a file change detector. It could detect the file changed based on modified time and file - * content at the binary level. It load the file content into the memory as cache to do the comparison. - */ - @RequiredArgsConstructor - @Slf4j - private static class WatchedFile { - /** - * The absolute path of the monitored file. - */ - private final String filePath; - /** - * The last modify time of the {@link #filePath} - */ - private long lastModifiedTimestamp = 0; - /** - * File content at the latest status. - */ - private byte[] fileContent; - - /** - * Detect the file content change, if yes, reload the file content into the memory as cached data. - * - * @return true if file content changed. - */ - boolean detectContentChanged() { - File targetFile = new File(filePath); - if (!targetFile.exists()) { - if (lastModifiedTimestamp == 0) { - //File doesn't exist before, no change detected. - return false; - } else { - // File has been deleted. Reset the modified timestamp. - lastModifiedTimestamp = 0; - return true; - } - } else { - long lastModified = targetFile.lastModified(); - if (lastModified != lastModifiedTimestamp) { - // File modified timestamp changed. Need to read the file content. - try (FileInputStream fileInputStream = new FileInputStream(targetFile)) { - byte[] b = new byte[1024]; - ByteArrayOutputStream os = new ByteArrayOutputStream(); - int c; - while ((c = fileInputStream.read(b)) != -1) { - os.write(b, 0, c); - } - byte[] newContent = os.toByteArray(); - if (!Arrays.equals(newContent, fileContent)) { - fileContent = newContent; - return true; - } else { - return false; - } - } catch (FileNotFoundException e) { - log.error("The existed file turns to missing, watch file=" + filePath, e); - } catch (IOException e) { - log.error("Read file failure, watch file=" + filePath, e); - } finally { - lastModifiedTimestamp = lastModified; - } - } - return false; - } - } - } - - private static class NoopWatchedFile extends WatchedFile { - public NoopWatchedFile() { - super(null); - } - - /** - * @return false, as an noop file never changes. - */ - @Override - boolean detectContentChanged() { - return false; - } - } -} diff --git a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/ResourceUtils.java b/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/ResourceUtils.java deleted file mode 100644 index 6addb0be..00000000 --- a/iot-server/server-library/library-util/src/main/java/com/zmops/zeus/iot/server/library/util/ResourceUtils.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.library.util; - -import java.io.*; -import java.net.URL; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -public class ResourceUtils { - - public static Reader read(String fileName) throws FileNotFoundException { - return new InputStreamReader(readToStream(fileName)); - } - - public static InputStream readToStream(String fileName) throws FileNotFoundException { - URL url = ResourceUtils.class.getClassLoader().getResource(fileName); - if (url == null) { - throw new FileNotFoundException("file not found: " + fileName); - } - return ResourceUtils.class.getClassLoader().getResourceAsStream(fileName); - } - - public static File[] getPathFiles(String path) throws FileNotFoundException { - URL url = ResourceUtils.class.getClassLoader().getResource(path); - if (url == null) { - throw new FileNotFoundException("path not found: " + path); - } - return Arrays.stream(Objects.requireNonNull(new File(url.getPath()).listFiles(), "No files in " + path)) - .filter(File::isFile).toArray(File[]::new); - } - - public static File[] getPathFiles(String parentPath, String[] fileNames) throws FileNotFoundException { - URL url = ResourceUtils.class.getClassLoader().getResource(parentPath); - if (url == null) { - throw new FileNotFoundException("path not found: " + parentPath); - } - final Set nameSet = new HashSet<>(Arrays.asList(fileNames)); - final File[] listFiles = Objects.requireNonNull(new File(url.getPath()) - .listFiles((dir, name) -> nameSet.contains(name)), "No files in " + parentPath); - - if (listFiles.length == 0) { - throw new FileNotFoundException("files not found:" + nameSet); - } - return listFiles; - } -} diff --git a/iot-server/server-library/library-server/pom.xml b/iot-server/server-localdb/pom.xml similarity index 58% rename from iot-server/server-library/library-server/pom.xml rename to iot-server/server-localdb/pom.xml index 9d91331a..3a15d8d5 100644 --- a/iot-server/server-library/library-server/pom.xml +++ b/iot-server/server-localdb/pom.xml @@ -3,36 +3,31 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - server-library + iot-server com.zmops 1.0-beta 4.0.0 - library-server - - - 8 - 8 - 9.4.40.v20210413 - + server-localdb + IoT Server 服务组件状态实时本地持久化存储,启动恢复 com.zmops - library-util - 1.0-beta - - - org.eclipse.jetty - jetty-server - ${jetty.version} + library-module + 1.0.3-RELEASE - org.eclipse.jetty - jetty-servlet - ${jetty.version} + com.zmops + server-client + 1.0-beta + + 8 + 8 + + \ No newline at end of file diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/module/LocalH2Module.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/module/LocalH2Module.java new file mode 100644 index 00000000..4f879c0d --- /dev/null +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/module/LocalH2Module.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.server.h2.module; + +import com.zmops.zeus.iot.server.h2.service.InsertDAO; +import com.zmops.zeus.server.library.module.ModuleDefine; + +/** + * @author nantian created at 2021/10/24 16:56 + */ +public class LocalH2Module extends ModuleDefine { + + public static final String NAME = "local-h2"; + + public LocalH2Module() { + super(NAME); + } + + @Override + public Class[] services() { + return new Class[]{ + InsertDAO.class + }; + } +} diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Config.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Config.java new file mode 100644 index 00000000..d13af60e --- /dev/null +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Config.java @@ -0,0 +1,26 @@ +package com.zmops.zeus.iot.server.h2.provider; + +import com.zmops.zeus.server.library.module.ModuleConfig; +import lombok.Getter; +import lombok.Setter; + +/** + * @author nantian created at 2021/10/24 16:45 + *

+ * H2 配置,用于 IoT Server 本地组件状态缓存 + */ + +@Getter +@Setter +public class LocalH2Config extends ModuleConfig { + + private String driver = "org.h2.jdbcx.JdbcDataSource"; + private String url = "jdbc:h2:~/zeus_iot_db;DB_CLOSE_DELAY=-1"; + private String user = "sa"; + private String password = "sa"; + + /** + * 模块版本号 + */ + private String version; +} diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2InsertDAO.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2InsertDAO.java new file mode 100644 index 00000000..85098f3f --- /dev/null +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2InsertDAO.java @@ -0,0 +1,61 @@ +package com.zmops.zeus.iot.server.h2.provider; + +import com.zmops.zeus.iot.server.client.jdbc.JDBCClientException; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.iot.server.h2.service.InsertDAO; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author yefei + **/ +public class LocalH2InsertDAO implements InsertDAO { + + private final JDBCHikariCPClient h2Client; + + public LocalH2InsertDAO(JDBCHikariCPClient h2Client) { + this.h2Client = h2Client; + } + + @Override + public void insert(String sql) { + try { + h2Client.execute(h2Client.getConnection(), sql); + } catch (JDBCClientException e) { + e.printStackTrace(); + } + } + + @Override + public int update(String sql, Object... params) { + int r = 0; + try { + r = h2Client.executeUpdate(h2Client.getConnection(), sql, params); + } catch (JDBCClientException e) { + e.printStackTrace(); + } + return r; + } + + @Override + public ResultSet queryRes(String sql, Object... params) { + ResultSet resultSet = null; + try { + resultSet = h2Client.executeQuery(h2Client.getConnection(), sql, params); + } catch (JDBCClientException e) { + e.printStackTrace(); + } + return resultSet; + } + + @Override + public void delete(String sql) { + try { + h2Client.execute(h2Client.getConnection(), sql); + } catch (JDBCClientException e) { + e.printStackTrace(); + } + } + +} diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Provider.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Provider.java new file mode 100644 index 00000000..5d4d4b89 --- /dev/null +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/provider/LocalH2Provider.java @@ -0,0 +1,125 @@ +package com.zmops.zeus.iot.server.h2.provider; + +import com.zmops.zeus.iot.server.client.jdbc.JDBCClientException; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.iot.server.h2.module.LocalH2Module; +import com.zmops.zeus.iot.server.h2.service.InsertDAO; +import com.zmops.zeus.server.library.module.*; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.util.Properties; + +/** + * @author nantian created at 2021/10/24 16:57 + */ +public class LocalH2Provider extends ModuleProvider { + + private final LocalH2Config localH2Config; + private JDBCHikariCPClient h2Client; + + public LocalH2Provider() { + this.localH2Config = new LocalH2Config(); + } + + @Override + public String name() { + return "default"; + } + + @Override + public Class module() { + return LocalH2Module.class; + } + + @Override + public ModuleConfig createConfigBeanIfAbsent() { + return localH2Config; + } + + @Override + public void prepare() throws ServiceNotProvidedException, ModuleStartException { + + Properties settings = new Properties(); + settings.setProperty("dataSourceClassName", localH2Config.getDriver()); + settings.setProperty("dataSource.url", localH2Config.getUrl()); + settings.setProperty("dataSource.user", localH2Config.getUser()); + settings.setProperty("dataSource.password", localH2Config.getPassword()); + h2Client = new JDBCHikariCPClient(settings); + + h2Client.connect(); + + this.registerServiceImplementation(InsertDAO.class, new LocalH2InsertDAO(h2Client)); + + try { + Connection connection = h2Client.getConnection(); + h2Client.execute( + connection, "CREATE TABLE if not exists PROTOCOL_COMPONENT(" + + " ID INT PRIMARY KEY," + + " NAME VARCHAR(64)," + + " UNIQUE_ID VARCHAR(32)," + + " FILE_NAME VARCHAR(64)," + + " STATUS VARCHAR(8)," + + " REMARK VARCHAR(255)," + + " BIZ_NAME VARCHAR(64)," + + " BIZ_VERSION VARCHAR(32)" + + ");"); + + h2Client.execute( + connection, "CREATE TABLE if not exists PROTOCOL_GATEWAY(" + + " ID INT PRIMARY KEY," + + " NAME VARCHAR(64)," + + " PROTOCOL_COMPONENT_ID INT," + + " PROTOCOL_SERVICE_ID INT," + + " REMARK VARCHAR(255)," + + " STATUS VARCHAR(8)" + + ");"); + + h2Client.execute( + connection, "CREATE TABLE if not exists PROTOCOL_SERVICE(" + + " ID INT PRIMARY KEY," + + " NAME VARCHAR(64)," + + " REMARK VARCHAR(255)," + + " URL VARCHAR(128)," + + " IP VARCHAR(16)," + + " PORT INT," + + " MSG_LENGTH INT," + + " CLIENT_ID VARCHAR(32)," + + " PROTOCOL VARCHAR(16)" + + ");"); + + h2Client.execute( + connection, "CREATE TABLE if not exists PROTOCOL_GATEWAY_MQTT(" + + " TOPIC VARCHAR(64)," + + " PROTOCOL_COMPONENT_ID INT," + + " PROTOCOL_GATEWAY_ID INT" + + ");"); + + ResultSet rs2 = h2Client.executeQuery(connection, "select * from PROTOCOL_COMPONENT;"); + + System.out.println(rs2); + + + } catch (JDBCClientException e) { + // throw new IOException(e.getMessage(), e); + e.printStackTrace(); + } + + + } + + @Override + public void start() throws ServiceNotProvidedException, ModuleStartException { + + } + + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { + + } + + @Override + public String[] requiredModules() { + return new String[0]; + } +} diff --git a/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/service/InsertDAO.java b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/service/InsertDAO.java new file mode 100644 index 00000000..5324ba0e --- /dev/null +++ b/iot-server/server-localdb/src/main/java/com/zmops/zeus/iot/server/h2/service/InsertDAO.java @@ -0,0 +1,19 @@ +package com.zmops.zeus.iot.server.h2.service; + +import com.zmops.zeus.server.library.module.Service; + +import java.sql.ResultSet; + +/** + * @author yefei + **/ +public interface InsertDAO extends Service { + + void insert(String sql); + + int update(String sql, Object... params); + + ResultSet queryRes(String sql, Object... params); + + void delete(String sql); +} diff --git a/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine similarity index 94% rename from iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine index 4e0077b4..4973cd13 100644 --- a/iot-server/server-core/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine +++ b/iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine @@ -16,4 +16,4 @@ # # -com.zmops.zeus.iot.server.core.CoreModule +com.zmops.zeus.iot.server.h2.module.LocalH2Module diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 92% rename from iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider index 67ba6f53..ec147ae4 100644 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine +++ b/iot-server/server-localdb/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider @@ -16,4 +16,4 @@ # # -com.zmops.zeus.iot.server.receiver.mqtt.module.MqttReceiverModule +com.zmops.zeus.iot.server.h2.provider.LocalH2Provider diff --git a/iot-server/server-receiver-plugin/coap-receiver-plugin/pom.xml b/iot-server/server-receiver-plugin/coap-receiver-plugin/pom.xml deleted file mode 100644 index c28fc373..00000000 --- a/iot-server/server-receiver-plugin/coap-receiver-plugin/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - server-receiver-plugin - com.zmops - 1.0-beta - - 4.0.0 - - coap-receiver-plugin - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/pom.xml b/iot-server/server-receiver-plugin/http-receiver-plugin/pom.xml deleted file mode 100644 index 5884284b..00000000 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - server-receiver-plugin - com.zmops - 1.0-beta - - 4.0.0 - - http-receiver-plugin - - - com.zmops - library-module - 1.0-beta - - - org.apache.camel - camel-netty4-http - ${camel.version} - - - io.netty - netty-example - - - - - com.zmops - server-sender - 1.0-beta - compile - - - com.zmops - server-core - 1.0-beta - compile - - - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/module/HttpReceiverModule.java b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/module/HttpReceiverModule.java deleted file mode 100644 index e1176088..00000000 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/module/HttpReceiverModule.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.http.module; - -import com.zmops.zeus.iot.server.library.module.ModuleDefine; - -/** - * @author nantian created at 2021/8/14 0:13 - *

- * Http 协议 接收报文 - */ -public class HttpReceiverModule extends ModuleDefine { - - public static final String NAME = "receiver-http"; - - public HttpReceiverModule() { - super(NAME); - } - - @Override - public Class[] services() { - return new Class[0]; - } -} diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/predicate/HeaderPredicate.java b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/predicate/HeaderPredicate.java deleted file mode 100644 index 187857a9..00000000 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/predicate/HeaderPredicate.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.http.predicate; - -import org.apache.camel.Exchange; -import org.apache.camel.Predicate; - -/** - * @author nantian created at 2021/8/16 18:19 - */ -public class HeaderPredicate implements Predicate { - - @Override - public boolean matches(Exchange exchange) { - - - return exchange.getIn().getHeader("username").equals("zhangsan"); - } -} diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpReceiverConfig.java b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpReceiverConfig.java deleted file mode 100644 index cd43a94c..00000000 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpReceiverConfig.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.http.provider; - -import com.zmops.zeus.iot.server.library.module.ModuleConfig; -import lombok.Getter; -import lombok.Setter; - -/** - * @author nantian created at 2021/8/14 22:47 - */ - -@Getter -@Setter -public class HttpReceiverConfig extends ModuleConfig { - - - /** - * Export http port - */ - private int port = 8080; -} diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpReceiverPluginProvider.java b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpReceiverPluginProvider.java deleted file mode 100644 index 4b1cb289..00000000 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpReceiverPluginProvider.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.http.provider; - -import com.zmops.zeus.iot.server.core.CoreModule; -import com.zmops.zeus.iot.server.core.camel.CamelContextHolderService; -import com.zmops.zeus.iot.server.library.module.*; -import com.zmops.zeus.iot.server.receiver.http.module.HttpReceiverModule; - -/** - * @author nantian created at 2021/8/14 22:29 - */ -public class HttpReceiverPluginProvider extends ModuleProvider { - - private final HttpReceiverConfig httpReceiverConfig; - - // CamelContextHolder - private CamelContextHolderService camelService; - - public HttpReceiverPluginProvider() { - this.httpReceiverConfig = new HttpReceiverConfig(); - } - - @Override - public String name() { - return "default"; - } - - @Override - public Class module() { - return HttpReceiverModule.class; - } - - @Override - public ModuleConfig createConfigBeanIfAbsent() { - return httpReceiverConfig; - } - - @Override - public void prepare() throws ServiceNotProvidedException, ModuleStartException { - - } - - @Override - public void start() throws ServiceNotProvidedException, ModuleStartException { - camelService = getManager().find(CoreModule.NAME).provider().getService(CamelContextHolderService.class); - } - - @Override - public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { - camelService.addRoutes(new HttpRouteBuilder(httpReceiverConfig)); - } - - @Override - public String[] requiredModules() { - return new String[]{ - CoreModule.NAME - }; - } -} diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java b/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java deleted file mode 100644 index edc51ce9..00000000 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/http/provider/HttpRouteBuilder.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.http.provider; - -import com.zmops.zeus.iot.server.receiver.http.predicate.HeaderPredicate; -import org.apache.camel.builder.RouteBuilder; - -/** - * @author nantian created at 2021/8/14 22:41 - */ -public class HttpRouteBuilder extends RouteBuilder { - - private final HttpReceiverConfig config; - - public HttpRouteBuilder(HttpReceiverConfig config) { - this.config = config; - } - - @Override - public void configure() throws Exception { - fromF("netty4-http:http://0.0.0.0:%d/foo", config.getPort()) - .threads(10) - .choice() - .when(new HeaderPredicate()) - .to("Zabbix"); - } -} diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/module/MqttReceiverModule.java b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/module/MqttReceiverModule.java deleted file mode 100644 index 65baa80d..00000000 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/module/MqttReceiverModule.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.mqtt.module; - -import com.zmops.zeus.iot.server.library.module.ModuleDefine; - -/** - * @author yefei - */ -public class MqttReceiverModule extends ModuleDefine { - - public static final String NAME = "receiver-mqtt"; - - public MqttReceiverModule() { - super(NAME); - } - - @Override - public Class[] services() { - return new Class[0]; - } -} diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/process/MqttPacketProcess.java b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/process/MqttPacketProcess.java deleted file mode 100644 index 868f47ca..00000000 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/process/MqttPacketProcess.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.mqtt.process; - -import org.apache.camel.Exchange; -import org.apache.camel.Processor; - -/** - * @author yefei - */ -public class MqttPacketProcess implements Processor { - - @Override - public void process(Exchange exchange) throws Exception { - System.out.println(exchange.getMessage()); - } -} diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttReceiverConfig.java b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttReceiverConfig.java deleted file mode 100644 index d2bb261a..00000000 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttReceiverConfig.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.mqtt.provider; - -import com.zmops.zeus.iot.server.library.module.ModuleConfig; -import lombok.Getter; -import lombok.Setter; - -/** - * @author yefei - */ - -@Getter -@Setter -public class MqttReceiverConfig extends ModuleConfig { - - - /** - * Export http port - */ - private int port = 9020; -} diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttReceiverPluginProvider.java b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttReceiverPluginProvider.java deleted file mode 100644 index 50d70961..00000000 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttReceiverPluginProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.mqtt.provider; - -import com.zmops.zeus.iot.server.core.CoreModule; -import com.zmops.zeus.iot.server.core.camel.CamelContextHolderService; -import com.zmops.zeus.iot.server.library.module.*; -import com.zmops.zeus.iot.server.receiver.mqtt.module.MqttReceiverModule; - -/** - * @author yefei - */ -public class MqttReceiverPluginProvider extends ModuleProvider { - - private final MqttReceiverConfig mqttReceiverConfig; - - private CamelContextHolderService camelService; - - public MqttReceiverPluginProvider() { - this.mqttReceiverConfig = new MqttReceiverConfig(); - } - - @Override - public String name() { - return "default"; - } - - @Override - public Class module() { - return MqttReceiverModule.class; - } - - @Override - public ModuleConfig createConfigBeanIfAbsent() { - return mqttReceiverConfig; - } - - @Override - public void prepare() throws ServiceNotProvidedException, ModuleStartException { - - } - - @Override - public void start() throws ServiceNotProvidedException, ModuleStartException { - camelService = getManager().find(CoreModule.NAME).provider().getService(CamelContextHolderService.class); - } - - @Override - public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { - camelService.addRoutes(new MqttRouteBuilder(mqttReceiverConfig)); - } - - @Override - public String[] requiredModules() { - return new String[]{ - CoreModule.NAME - }; - } -} diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java deleted file mode 100644 index 20490532..00000000 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/mqtt/provider/MqttRouteBuilder.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.mqtt.provider; - -import com.zmops.zeus.iot.server.receiver.mqtt.process.MqttPacketProcess; -import org.apache.camel.builder.RouteBuilder; - -/** - * @author yefei - */ -public class MqttRouteBuilder extends RouteBuilder { - - - private final MqttReceiverConfig mqttReceiverConfig; - - public MqttRouteBuilder(MqttReceiverConfig mqttReceiverConfig) { - this.mqttReceiverConfig = mqttReceiverConfig; - } - - @Override - public void configure() throws Exception { - fromF("mqtt://127.0.0.1:%d?subscribeTopicNames=test.mqtt.topic", mqttReceiverConfig.getPort()) - .process(new MqttPacketProcess()) - .to("Zabbix"); - } -} diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider deleted file mode 100644 index 4f8a532e..00000000 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider +++ /dev/null @@ -1,19 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You 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 -# -# http://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. -# -# - -com.zmops.zeus.iot.server.receiver.mqtt.provider.MqttReceiverPluginProvider diff --git a/iot-server/server-receiver-plugin/opc-ua-receiver-plugin/pom.xml b/iot-server/server-receiver-plugin/opc-ua-receiver-plugin/pom.xml deleted file mode 100644 index 06244903..00000000 --- a/iot-server/server-receiver-plugin/opc-ua-receiver-plugin/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - server-receiver-plugin - com.zmops - 1.0-beta - - 4.0.0 - - opc-ua-receiver-plugin - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-server/server-receiver-plugin/pom.xml b/iot-server/server-receiver-plugin/pom.xml deleted file mode 100644 index 88a9680d..00000000 --- a/iot-server/server-receiver-plugin/pom.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - iot-server - com.zmops - 1.0-beta - - 4.0.0 - - server-receiver-plugin - pom - - http-receiver-plugin - udp-receiver-plugin - mqtt-receiver-plugin - coap-receiver-plugin - tcp-receiver-plugin - opc-ua-receiver-plugin - - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-server/server-receiver-plugin/readme.md b/iot-server/server-receiver-plugin/readme.md deleted file mode 100644 index e8e7b730..00000000 --- a/iot-server/server-receiver-plugin/readme.md +++ /dev/null @@ -1,7 +0,0 @@ -#### 网络协议接入模块 -- HTTP -- COAP -- MQTT -- TCP -- UDP -- OPC diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/module/TcpReceiverModule.java b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/module/TcpReceiverModule.java deleted file mode 100644 index 15615d33..00000000 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/module/TcpReceiverModule.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.tcp.module; - -import com.zmops.zeus.iot.server.library.module.ModuleDefine; - -/** - * @author nantian created at 2021/8/17 11:25 - */ -public class TcpReceiverModule extends ModuleDefine { - - public static final String NAME = "receiver-tcp"; - - public TcpReceiverModule() { - super(NAME); - } - - @Override - public Class[] services() { - return new Class[0]; - } -} diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/process/TcpPacketProcess.java b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/process/TcpPacketProcess.java deleted file mode 100644 index df5f2d0b..00000000 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/process/TcpPacketProcess.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.tcp.process; - -import org.apache.camel.Exchange; -import org.apache.camel.Processor; - -/** - * @author nantian created at 2021/8/17 11:36 - */ -public class TcpPacketProcess implements Processor { - - @Override - public void process(Exchange exchange) throws Exception { - - } -} diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpReceiverConfig.java b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpReceiverConfig.java deleted file mode 100644 index 8ac7c9b1..00000000 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpReceiverConfig.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.tcp.provider; - -import com.zmops.zeus.iot.server.library.module.ModuleConfig; -import lombok.Getter; -import lombok.Setter; - -/** - * @author nantian created at 2021/8/14 22:47 - */ - -@Getter -@Setter -public class TcpReceiverConfig extends ModuleConfig { - - - /** - * Export http port - */ - private int port = 9020; -} diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpReceiverPluginProvider.java b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpReceiverPluginProvider.java deleted file mode 100644 index 5ba29e7d..00000000 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpReceiverPluginProvider.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.tcp.provider; - -import com.zmops.zeus.iot.server.core.CoreModule; -import com.zmops.zeus.iot.server.core.camel.CamelContextHolderService; -import com.zmops.zeus.iot.server.library.module.*; -import com.zmops.zeus.iot.server.receiver.tcp.module.TcpReceiverModule; - -/** - * @author nantian created at 2021/8/14 22:29 - */ -public class TcpReceiverPluginProvider extends ModuleProvider { - - private final TcpReceiverConfig tcpReceiverConfig; - - // CamelContextHolder - private CamelContextHolderService camelService; - - public TcpReceiverPluginProvider() { - this.tcpReceiverConfig = new TcpReceiverConfig(); - } - - @Override - public String name() { - return "default"; - } - - @Override - public Class module() { - return TcpReceiverModule.class; - } - - @Override - public ModuleConfig createConfigBeanIfAbsent() { - return tcpReceiverConfig; - } - - @Override - public void prepare() throws ServiceNotProvidedException, ModuleStartException { - - } - - @Override - public void start() throws ServiceNotProvidedException, ModuleStartException { - camelService = getManager().find(CoreModule.NAME).provider().getService(CamelContextHolderService.class); - } - - @Override - public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { - camelService.addRoutes(new TcpRouteBuilder(tcpReceiverConfig)); - } - - @Override - public String[] requiredModules() { - return new String[]{ - CoreModule.NAME - }; - } -} diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpRouteBuilder.java b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpRouteBuilder.java deleted file mode 100644 index fe44598f..00000000 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/java/com/zmops/zeus/iot/server/receiver/tcp/provider/TcpRouteBuilder.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.zmops.zeus.iot.server.receiver.tcp.provider; - -import com.zmops.zeus.iot.server.receiver.tcp.process.TcpPacketProcess; -import org.apache.camel.builder.RouteBuilder; - -/** - * @author nantian created at 2021/8/17 11:32 - */ -public class TcpRouteBuilder extends RouteBuilder { - - - private TcpReceiverConfig tcpReceiverConfig; - - public TcpRouteBuilder(TcpReceiverConfig tcpReceiverConfig) { - this.tcpReceiverConfig = tcpReceiverConfig; - } - - @Override - public void configure() throws Exception { - fromF("netty4:tcp://0.0.0.0:%d", tcpReceiverConfig.getPort()).process(new TcpPacketProcess()); - } -} diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider deleted file mode 100644 index 3c5347e3..00000000 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider +++ /dev/null @@ -1,19 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You 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 -# -# http://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. -# -# - -com.zmops.zeus.iot.server.receiver.tcp.provider.TcpReceiverPluginProvider diff --git a/iot-server/server-receiver-plugin/udp-receiver-plugin/pom.xml b/iot-server/server-receiver-plugin/udp-receiver-plugin/pom.xml deleted file mode 100644 index 21a584f3..00000000 --- a/iot-server/server-receiver-plugin/udp-receiver-plugin/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - server-receiver-plugin - com.zmops - 1.0-beta - - 4.0.0 - - udp-receiver-plugin - - - 8 - 8 - - - \ No newline at end of file diff --git a/iot-server/server-sender/pom.xml b/iot-server/server-sender/pom.xml index 64672f98..abbad98d 100644 --- a/iot-server/server-sender/pom.xml +++ b/iot-server/server-sender/pom.xml @@ -10,12 +10,12 @@ 4.0.0 server-sender + com.zmops library-module - 1.0-beta - compile + 1.0.3-RELEASE diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/module/ZabbixSenderModule.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/module/ZabbixSenderModule.java index 5f4e63ad..565e538f 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/module/ZabbixSenderModule.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/module/ZabbixSenderModule.java @@ -1,7 +1,7 @@ package com.zmops.zeus.iot.server.sender.module; -import com.zmops.zeus.iot.server.library.module.ModuleDefine; -import com.zmops.zeus.iot.server.sender.provider.service.ZabbixSenderService; +import com.zmops.zeus.iot.server.sender.service.ZabbixSenderService; +import com.zmops.zeus.server.library.module.ModuleDefine; /** * @author nantian created at 2021/8/14 14:35 diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/ZabbixSenderClient.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderClient.java similarity index 80% rename from iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/ZabbixSenderClient.java rename to iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderClient.java index fd3c60e6..ab708690 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/ZabbixSenderClient.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderClient.java @@ -1,6 +1,5 @@ -package com.zmops.zeus.iot.server.sender.provider.protocol; +package com.zmops.zeus.iot.server.sender.provider; -import com.zmops.zeus.iot.server.sender.provider.ZabbixSenderModuleConfig; import lombok.extern.slf4j.Slf4j; import java.net.InetSocketAddress; @@ -8,6 +7,8 @@ /** * @author nantian created at 2021/8/14 14:46 + *

+ * Zabbix 发送 Socket Client */ @Slf4j @@ -23,8 +24,7 @@ public ZabbixSenderClient(ZabbixSenderModuleConfig config) { * 启动 TCP Sender 客户端 */ public void start() { - log.debug("Zabbix Sender 模块已经启动,Trapper 服务地址:{}:{}", - socketConfig.getHost(), socketConfig.getPort()); + log.debug("Zabbix Sender 模块已经启动,Trapper 服务地址:{}:{}", socketConfig.getHost(), socketConfig.getPort()); } @@ -41,7 +41,6 @@ public static Socket getSocket() { } catch (Exception e) { e.printStackTrace(); } - return trapperSocket; } } diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderModuleConfig.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderModuleConfig.java index 187e5aba..ea64e47b 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderModuleConfig.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderModuleConfig.java @@ -1,6 +1,6 @@ package com.zmops.zeus.iot.server.sender.provider; -import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import com.zmops.zeus.server.library.module.ModuleConfig; import lombok.Getter; import lombok.Setter; diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderProvider.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderProvider.java index 16e52e8c..22ef3ba6 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderProvider.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/ZabbixSenderProvider.java @@ -1,9 +1,8 @@ package com.zmops.zeus.iot.server.sender.provider; -import com.zmops.zeus.iot.server.library.module.*; import com.zmops.zeus.iot.server.sender.module.ZabbixSenderModule; -import com.zmops.zeus.iot.server.sender.provider.protocol.ZabbixSenderClient; -import com.zmops.zeus.iot.server.sender.provider.service.ZabbixSenderService; +import com.zmops.zeus.iot.server.sender.service.ZabbixSenderService; +import com.zmops.zeus.server.library.module.*; import lombok.extern.slf4j.Slf4j; /** diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixTrapperRequest.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixTrapperRequest.java deleted file mode 100644 index e2e0e500..00000000 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/protocol/bean/ZabbixTrapperRequest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 - * - * http://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.zmops.zeus.iot.server.sender.provider.protocol.bean; - -import lombok.Data; -import lombok.Getter; -import lombok.Setter; - -import java.util.List; - - -public class ZabbixTrapperRequest { - - /** - * Request type - */ - private ZabbixProtocolType type; - - @Setter - @Getter - private String request = ZabbixProtocolType.SENDER_DATA.getName(); - - /** - * Agent push data - * - * @see ZabbixProtocolType#AGENT_DATA - */ - @Setter - @Getter - private List data; - - @Setter - @Getter - private long clock = System.currentTimeMillis() / 1000L; - - @Setter - @Getter - private long ns = System.nanoTime() % 1_000_000_000L; - - @Data - public static class SenderData { - private String host; - private String key; - private String value; - private long clock; - private long ns; - - public SenderData() { - this.clock = System.currentTimeMillis() / 1000L; - this.ns = System.nanoTime() % 1_000_000_000L; - } - } - -} diff --git a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/service/ZabbixSenderService.java b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java similarity index 65% rename from iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/service/ZabbixSenderService.java rename to iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java index f3a6ec5a..8b4ccf93 100644 --- a/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/provider/service/ZabbixSenderService.java +++ b/iot-server/server-sender/src/main/java/com/zmops/zeus/iot/server/sender/service/ZabbixSenderService.java @@ -1,9 +1,9 @@ -package com.zmops.zeus.iot.server.sender.provider.service; +package com.zmops.zeus.iot.server.sender.service; import com.google.gson.Gson; -import com.zmops.zeus.iot.server.library.module.ModuleManager; -import com.zmops.zeus.iot.server.library.module.Service; -import com.zmops.zeus.iot.server.sender.provider.protocol.ZabbixSenderClient; +import com.zmops.zeus.iot.server.sender.provider.ZabbixSenderClient; +import com.zmops.zeus.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.module.Service; import lombok.extern.slf4j.Slf4j; import java.io.IOException; @@ -31,11 +31,30 @@ public ZabbixSenderService(ModuleManager moduleManager) { this.moduleManager = moduleManager; } + /** + * 指定格式的 JSON + * + * @param message see + * https://www.zabbix.com/documentation/current/manual/appendix/items/trapper + * + * { + * "request":"sender data", + * "data":[ + * { + * "host":"device.info", + * "key":"device.temp", + * "value":"86" + * } + * ] + * } + * @return String + * @throws IOException ex + */ public String sendData(String message) throws IOException { Socket trapperSocket = ZabbixSenderClient.getSocket(); - int payloadLength = message.length(); + int payloadLength = length(message); byte[] header = new byte[]{ 'Z', 'B', 'X', 'D', '\1', (byte) (payloadLength & 0xFF), @@ -61,7 +80,8 @@ public String sendData(String message) throws IOException { StringBuilder resp = new StringBuilder(); int headLength = 13; - int bRead = 0; + int bRead = 0; + while (true) { bRead = resStream.read(response); if (bRead <= 0) break; @@ -87,19 +107,41 @@ public String sendData(String message) throws IOException { * @return String */ private String zabbixResponseToMap(String resp) { - Map result = gson.fromJson(resp, Map.class); - String[] infos = result.get("info").split(";"); - Map resultMap = new HashMap<>(); + String info = result.get("info"); + if (info == null) { + return resp; + } + String[] infos = info.split(";"); + + Map resultMap = new HashMap<>(); for (String i : infos) { String[] ii = i.split(":"); resultMap.put(ii[0].trim(), ii[1]); } resultMap.put("response", result.get("response")); - return gson.toJson(resultMap); } + + /** + * 计算字符串长度 中文3个字节 + * @param value + * @return + */ + public static int length(String value) { + int valueLength = 0; + String chinese = "[\u0391-\uFFE5]"; + for (int i = 0; i < value.length(); i++) { + String temp = value.substring(i, i + 1); + if (temp.matches(chinese)) { + valueLength += 3; + } else { + valueLength += 1; + } + } + return valueLength; + } } diff --git a/iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine similarity index 100% rename from iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine diff --git a/iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-sender/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-starter/conf/ark/bootstrap.properties b/iot-server/server-starter/conf/ark/bootstrap.properties new file mode 100644 index 00000000..c3d121ec --- /dev/null +++ b/iot-server/server-starter/conf/ark/bootstrap.properties @@ -0,0 +1,5 @@ +logging.path=./logs + +#com.alipay.sofa.ark.master.biz=server-starter + +com.alipay.sofa.ark.master.biz=Startup In IDE \ No newline at end of file diff --git a/iot-server/server-starter/pom.xml b/iot-server/server-starter/pom.xml index 3361d93e..dad2bf41 100644 --- a/iot-server/server-starter/pom.xml +++ b/iot-server/server-starter/pom.xml @@ -9,6 +9,11 @@ 4.0.0 + + 1.11.0 + ./src/main/webapp/assets + + server-starter @@ -22,11 +27,80 @@ server-health-checker 1.0-beta + + + com.zmops + runtime-server-plugin + 1.0.3-RELEASE + + + ch.qos.logback + logback-classic + + + + + + com.alipay.sofa + sofa-ark-support-starter + 1.1.6 + + + ch.qos.logback + logback-classic + + + ch.qos.logback + logback-core + + + com.alipay.sofa + log-sofa-boot-starter + + + + - - 8 - 8 - + + iot-server + + + org.apache.maven.plugins + maven-assembly-plugin + + + assembly + package + + single + + + + src/main/assembly/assembly.xml + + + + + + + com.alipay.sofa + sofa-ark-maven-plugin + 1.1.6 + + + + repackage + + + server-starter + ./target + executable-ark + + + + + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/assembly/assembly.xml b/iot-server/server-starter/src/main/assembly/assembly.xml new file mode 100644 index 00000000..7281a1e6 --- /dev/null +++ b/iot-server/server-starter/src/main/assembly/assembly.xml @@ -0,0 +1,33 @@ + + + + assembly + + dir + + + + /libs + runtime + + + \ No newline at end of file diff --git a/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java b/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java deleted file mode 100644 index d5ba30b9..00000000 --- a/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IOTServerStartUp.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.zmops.zeus.iot.server.starter; - -/** - * @author nantian created at 2021/8/13 15:26 - *

- * 宙斯服务 协议层启动 - */ -public class IOTServerStartUp { - - public static void main(String[] args) { - IOTServerBootstrap.start(); - } -} diff --git a/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java b/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java new file mode 100644 index 00000000..b3435976 --- /dev/null +++ b/iot-server/server-starter/src/main/java/com/zmops/zeus/iot/server/starter/IoTServerStartUp.java @@ -0,0 +1,20 @@ +package com.zmops.zeus.iot.server.starter; + +import com.alipay.sofa.ark.support.startup.SofaArkBootstrap; +import lombok.extern.slf4j.Slf4j; + +/** + * @author nantian created at 2021/8/13 15:26 + *

+ * 宙斯服务 协议层启动 + */ +@Slf4j +public class IoTServerStartUp { + + public static void main(String[] args) { + SofaArkBootstrap.launch(args); + IoTServerBootstrap.start(); + + log.info("IoT Server Platform start successfully ..."); + } +} diff --git a/iot-server/server-library/pom.xml b/iot-server/server-storage-plugin/pom.xml similarity index 78% rename from iot-server/server-library/pom.xml rename to iot-server/server-storage-plugin/pom.xml index cb2a1dad..331985d7 100644 --- a/iot-server/server-library/pom.xml +++ b/iot-server/server-storage-plugin/pom.xml @@ -9,12 +9,12 @@ 4.0.0 - server-library + server-storage-plugin pom - library-module - library-util - library-server + server-tdengine-plugin + server-influxdb-plugin + server-none-storage diff --git a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/pom.xml b/iot-server/server-storage-plugin/server-influxdb-plugin/pom.xml similarity index 76% rename from iot-server/server-receiver-plugin/mqtt-receiver-plugin/pom.xml rename to iot-server/server-storage-plugin/server-influxdb-plugin/pom.xml index a5f2b571..cba1a098 100644 --- a/iot-server/server-receiver-plugin/mqtt-receiver-plugin/pom.xml +++ b/iot-server/server-storage-plugin/server-influxdb-plugin/pom.xml @@ -3,35 +3,35 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - server-receiver-plugin + server-storage-plugin com.zmops 1.0-beta 4.0.0 - mqtt-receiver-plugin + server-influxdb-plugin 8 8 - - org.apache.camel - camel-mqtt - ${camel.version} + org.influxdb + influxdb-java + 2.15 com.zmops library-module - ${project.version} + 1.0.3-RELEASE com.zmops server-core - 1.0-beta + ${project.version} + \ No newline at end of file diff --git a/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/InfluxClient.java b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/InfluxClient.java new file mode 100644 index 00000000..91f22ed9 --- /dev/null +++ b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/InfluxClient.java @@ -0,0 +1,239 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.zmops.zeus.iot.server.storage.plugin.jdbc.influxdb; + + +import com.zmops.zeus.iot.server.client.Client; +import com.zmops.zeus.iot.server.client.healthcheck.DelegatedHealthChecker; +import com.zmops.zeus.iot.server.client.healthcheck.HealthCheckable; +import com.zmops.zeus.server.library.util.CollectionUtils; +import com.zmops.zeus.server.library.util.HealthChecker; +import lombok.extern.slf4j.Slf4j; +import okhttp3.OkHttpClient; + +import org.influxdb.InfluxDB; +import org.influxdb.InfluxDBFactory; +import org.influxdb.dto.BatchPoints; +import org.influxdb.dto.Point; +import org.influxdb.dto.Query; +import org.influxdb.dto.QueryResult; +import org.influxdb.querybuilder.time.TimeInterval; + +import java.io.IOException; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.ti; + +/** + * InfluxDB connection maintainer, provides base data write/query API. + */ +@Slf4j +public class InfluxClient implements Client, HealthCheckable { + private final DelegatedHealthChecker healthChecker = new DelegatedHealthChecker(); + private final InfluxStorageConfig config; + private InfluxDB influx; + /** + * A constant, the name of time field in Time-series database. + */ + public static final String TIME = "time"; + + private final String database; + + public InfluxClient(InfluxStorageConfig config) { + this.config = config; + this.database = config.getDatabase(); + } + + public final String getDatabase() { + return database; + } + + @Override + public void connect() { + try { + InfluxDB.ResponseFormat responseFormat = InfluxDB.ResponseFormat.valueOf(config.getConnectionResponseFormat()); + influx = InfluxDBFactory.connect(config.getUrl(), config.getUser(), config.getPassword(), + new OkHttpClient.Builder().readTimeout(3, TimeUnit.MINUTES) + .writeTimeout(3, TimeUnit.MINUTES), + responseFormat + ); + influx.query(new Query("CREATE DATABASE " + database)); + influx.enableGzip(); + + if (config.isBatchEnabled()) { + influx.enableBatch(config.getActions(), config.getDuration(), TimeUnit.MILLISECONDS); + } + + influx.setDatabase(database); + healthChecker.health(); + } catch (Throwable e) { + healthChecker.unHealth(e); + throw e; + } + } + + /** + * To get a connection of InfluxDB. + * + * @return InfluxDB's connection + */ + private InfluxDB getInflux() { + return influx; + } + + /** + * Execute a query against InfluxDB and return a set of {@link QueryResult.Result}s. Normally, InfluxDB supports + * combining multiple statements into one query, so that we do get multi-results. + * + * @throws IOException if there is an error on the InfluxDB server or communication error. + */ + public List query(Query query) throws IOException { + if (log.isDebugEnabled()) { + log.debug("SQL Statement: {}", query.getCommand()); + } + try { + QueryResult result = getInflux().query(new Query(query.getCommand())); + if (result.hasError()) { + throw new IOException(result.getError()); + } + healthChecker.health(); + return result.getResults(); + } catch (Throwable e) { + healthChecker.unHealth(e); + throw new IOException(e.getMessage() + System.lineSeparator() + "SQL Statement: " + query.getCommand(), e); + } + } + + /** + * Execute a query against InfluxDB with a single statement. + * + * @throws IOException if there is an error on the InfluxDB server or communication error + */ + public List queryForSeries(Query query) throws IOException { + List results = query(query); + + if (CollectionUtils.isEmpty(results)) { + return null; + } + return results.get(0).getSeries(); + } + + /** + * Execute a query against InfluxDB with a single statement but return a single {@link QueryResult.Series}. + * + * @throws IOException if there is an error on the InfluxDB server or communication error + */ + public QueryResult.Series queryForSingleSeries(Query query) throws IOException { + List series = queryForSeries(query); + if (CollectionUtils.isEmpty(series)) { + return null; + } + return series.get(0); + } + + /** + * Execute a query against InfluxDB with a `select count(*)` statement and return the count only. + * + * @throws IOException if there is an error on the InfluxDB server or communication error + */ + public int getCounter(Query query) throws IOException { + QueryResult.Series series = queryForSingleSeries(query); + if (log.isDebugEnabled()) { + log.debug("SQL: {} result: {}", query.getCommand(), series); + } + if (Objects.isNull(series)) { + return 0; + } + return ((Number) series.getValues().get(0).get(1)).intValue(); + } + + /** + * Data management, to drop a time-series by measurement and time-series name specified. If an exception isn't + * thrown, it means execution success. Notice, drop series don't support to drop series by range + * + * @throws IOException if there is an error on the InfluxDB server or communication error + */ + public void dropSeries(String measurement, long timeBucket) throws IOException { + Query query = new Query("DROP SERIES FROM " + measurement + " WHERE time_bucket='" + timeBucket + "'"); + this.query(query); + } + + public void deleteByQuery(String measurement, long timestamp) throws IOException { + this.query(new Query("delete from " + measurement + " where time < " + timestamp + "ms")); + } + + /** + * Write a {@link Point} into InfluxDB. Note that, the {@link Point} is written into buffer of InfluxDB Client and + * wait for buffer flushing. + */ + public void write(Point point) { + try { + getInflux().write(point); + this.healthChecker.health(); + } catch (Throwable e) { + healthChecker.unHealth(e); + throw e; + } + } + + /** + * A batch operation of write. {@link Point}s flush directly. + */ + public void write(BatchPoints points) { + try { + getInflux().write(points); + this.healthChecker.health(); + } catch (Throwable e) { + healthChecker.unHealth(e); + throw e; + } + } + + @Override + public void shutdown() throws IOException { + try { + getInflux().close(); + this.healthChecker.health(); + } catch (Throwable e) { + healthChecker.unHealth(e); + throw new IOException(e); + } + } + + /** + * Convert to InfluxDB {@link TimeInterval}. + */ + public static TimeInterval timeIntervalTS(long timestamp) { + return ti(timestamp, "ms"); + } + +// /** +// * Convert to InfluxDB {@link TimeInterval}. +// */ +// public static TimeInterval timeIntervalTB(long timeBucket) { +// return ti(TimeBucket.getTimestamp(timeBucket), "ms"); +// } + + @Override + public void registerChecker(HealthChecker healthChecker) { + this.healthChecker.register(healthChecker); + } +} diff --git a/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/InfluxStorageConfig.java b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/InfluxStorageConfig.java new file mode 100644 index 00000000..0e2922c8 --- /dev/null +++ b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/InfluxStorageConfig.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.zmops.zeus.iot.server.storage.plugin.jdbc.influxdb; + +import com.zmops.zeus.server.library.module.ModuleConfig; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class InfluxStorageConfig extends ModuleConfig { + private String url = ""; + private String user = ""; + private String password = ""; + private String database = ""; + + private int actions; + private int duration; + private boolean batchEnabled = true; + + private int fetchTaskLogMaxSize = 5000; + private String connectionResponseFormat = "MSGPACK"; +} diff --git a/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/InfluxStorageProvider.java b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/InfluxStorageProvider.java new file mode 100644 index 00000000..c14655cf --- /dev/null +++ b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/InfluxStorageProvider.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.zmops.zeus.iot.server.storage.plugin.jdbc.influxdb; + +import com.zmops.zeus.iot.server.core.CoreModule; +import com.zmops.zeus.iot.server.core.storage.IBatchDAO; +import com.zmops.zeus.iot.server.core.storage.StorageDAO; +import com.zmops.zeus.iot.server.core.storage.StorageModule; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.influxdb.dao.BatchDAO; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.influxdb.dao.InfluxStorageDAO; +import com.zmops.zeus.iot.server.telemetry.TelemetryModule; +import com.zmops.zeus.iot.server.telemetry.api.HealthCheckMetrics; +import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; +import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import com.zmops.zeus.server.library.module.*; +import lombok.extern.slf4j.Slf4j; + + +@Slf4j +public class InfluxStorageProvider extends ModuleProvider { + private final InfluxStorageConfig config; + private InfluxClient client; + + public InfluxStorageProvider() { + config = new InfluxStorageConfig(); + } + + @Override + public String name() { + return "influxdb"; + } + + @Override + public Class module() { + return StorageModule.class; + } + + @Override + public ModuleConfig createConfigBeanIfAbsent() { + return config; + } + + @Override + public void prepare() throws ServiceNotProvidedException { + + client = new InfluxClient(config); + + this.registerServiceImplementation(IBatchDAO.class, new BatchDAO(client)); + this.registerServiceImplementation(StorageDAO.class, new InfluxStorageDAO(client)); + + } + + @Override + public void start() throws ServiceNotProvidedException, ModuleStartException { + MetricsCreator metricCreator = getManager().find(TelemetryModule.NAME).provider().getService(MetricsCreator.class); + HealthCheckMetrics healthChecker = metricCreator.createHealthCheckerGauge( + "storage_influxdb", MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE); + + client.registerChecker(healthChecker); + client.connect(); + } + + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException { + + } + + @Override + public String[] requiredModules() { + return new String[]{CoreModule.NAME}; + } +} diff --git a/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/BatchDAO.java b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/BatchDAO.java new file mode 100644 index 00000000..0dc3786d --- /dev/null +++ b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/BatchDAO.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.zmops.zeus.iot.server.storage.plugin.jdbc.influxdb.dao; + +import com.zmops.zeus.iot.server.client.request.InsertRequest; +import com.zmops.zeus.iot.server.client.request.PrepareRequest; +import com.zmops.zeus.iot.server.core.storage.IBatchDAO; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.influxdb.InfluxClient; +import com.zmops.zeus.server.library.util.CollectionUtils; +import lombok.extern.slf4j.Slf4j; +import org.influxdb.dto.BatchPoints; + +import java.util.List; + +@Slf4j +public class BatchDAO implements IBatchDAO { + private final InfluxClient client; + + public BatchDAO(InfluxClient client) { + this.client = client; + } + + @Override + public void insert(InsertRequest insertRequest) { + client.write(((InfluxInsertRequest) insertRequest).getPoint()); + } + + @Override + public void flush(List prepareRequests) { + if (CollectionUtils.isEmpty(prepareRequests)) { + return; + } + + if (log.isDebugEnabled()) { + log.debug("batch sql statements execute, data size: {}", prepareRequests.size()); + } + + final BatchPoints.Builder builder = BatchPoints.builder(); + prepareRequests.forEach(e -> { + builder.point(((InfluxInsertRequest) e).getPoint()); + }); + + client.write(builder.build()); + } +} diff --git a/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/InfluxInsertRequest.java b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/InfluxInsertRequest.java new file mode 100644 index 00000000..cd7b243d --- /dev/null +++ b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/InfluxInsertRequest.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.zmops.zeus.iot.server.storage.plugin.jdbc.influxdb.dao; + +import com.google.common.collect.Maps; +import com.zmops.zeus.iot.server.client.request.InsertRequest; +import com.zmops.zeus.iot.server.core.analysis.manual.history.History; +import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; +import com.zmops.zeus.iot.server.core.storage.StorageData; +import com.zmops.zeus.iot.server.core.storage.model.Model; +import org.influxdb.dto.Point; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * InfluxDB Point wrapper. + */ +public class InfluxInsertRequest implements InsertRequest { + private final Point.Builder builder; + private final Map fields = Maps.newHashMap(); + + public InfluxInsertRequest(Model model, T storageData) { + String deviceid = ""; + Integer itemid = 0; + String value = ""; + Long time = 0L; + + if (model.getName().equals("history")) { + + History history = (History) storageData; + deviceid = history.getDeviceId(); + itemid = history.getItemid(); + value = history.getValue(); + time = history.getClock(); + fields.put("value", Double.parseDouble(value)); + } else { + UIntHistory uihistory = (UIntHistory) storageData; + deviceid = uihistory.getDeviceId(); + itemid = uihistory.getItemid(); + value = uihistory.getValue(); + time = uihistory.getClock(); + fields.put("value", Long.parseLong(value)); + } + + builder = Point.measurement("h_" + itemid) + .fields(fields); + builder.tag("deviceid", deviceid); + builder.tag("itemid", itemid + ""); + builder.time(time, TimeUnit.NANOSECONDS); + } + + public InfluxInsertRequest time(long time, TimeUnit unit) { + builder.time(time, unit); + return this; + } + + public Point getPoint() { + return builder.build(); + } +} \ No newline at end of file diff --git a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegisterImpl.java b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/InfluxStorageDAO.java similarity index 61% rename from iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegisterImpl.java rename to iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/InfluxStorageDAO.java index 24709ad6..0dda6bc4 100644 --- a/iot-server/server-core/src/main/java/com/zmops/zeus/iot/server/core/server/JettyHandlerRegisterImpl.java +++ b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/InfluxStorageDAO.java @@ -16,21 +16,24 @@ * */ -package com.zmops.zeus.iot.server.core.server; +package com.zmops.zeus.iot.server.storage.plugin.jdbc.influxdb.dao; -import com.zmops.zeus.iot.server.library.server.jetty.JettyHandler; -import com.zmops.zeus.iot.server.library.server.jetty.JettyServer; -public class JettyHandlerRegisterImpl implements JettyHandlerRegister { +import com.zmops.zeus.iot.server.core.storage.IRecordDAO; +import com.zmops.zeus.iot.server.core.storage.StorageDAO; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.influxdb.InfluxClient; - private final JettyServer server; +public class InfluxStorageDAO implements StorageDAO { + private final InfluxClient influxClient; - public JettyHandlerRegisterImpl(JettyServer server) { - this.server = server; + public InfluxStorageDAO(InfluxClient influxClient) { + this.influxClient = influxClient; } + @Override - public void addHandler(JettyHandler serverHandler) { - server.addHandler(serverHandler); + public IRecordDAO newRecordDao() { + return new RecordDAO(); } + } diff --git a/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/RecordDAO.java b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/RecordDAO.java new file mode 100644 index 00000000..b6e78115 --- /dev/null +++ b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/influxdb/dao/RecordDAO.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.zmops.zeus.iot.server.storage.plugin.jdbc.influxdb.dao; + +import com.zmops.zeus.iot.server.client.request.InsertRequest; +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.storage.IRecordDAO; +import com.zmops.zeus.iot.server.core.storage.model.Model; +import com.zmops.zeus.server.datacarrier.common.AtomicRangeInteger; + + +public class RecordDAO implements IRecordDAO { + private static final int PADDING_SIZE = 1_000_000; + private static final AtomicRangeInteger SUFFIX = new AtomicRangeInteger(0, PADDING_SIZE); + + public RecordDAO() { + + } + + @Override + public InsertRequest prepareBatchInsert(Model model, Record record) { + + final InfluxInsertRequest request = new InfluxInsertRequest(model, record); + + return request; + } + + +} diff --git a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 91% rename from iot-server/server-receiver-plugin/http-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-storage-plugin/server-influxdb-plugin/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider index e905c432..ca65a35b 100644 --- a/iot-server/server-receiver-plugin/http-receiver-plugin/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider +++ b/iot-server/server-storage-plugin/server-influxdb-plugin/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider @@ -16,4 +16,5 @@ # # -com.zmops.zeus.iot.server.receiver.http.provider.HttpReceiverPluginProvider + +com.zmops.zeus.iot.server.storage.plugin.jdbc.influxdb.InfluxStorageProvider \ No newline at end of file diff --git a/iot-server/server-library/library-util/pom.xml b/iot-server/server-storage-plugin/server-none-storage/pom.xml similarity index 68% rename from iot-server/server-library/library-util/pom.xml rename to iot-server/server-storage-plugin/server-none-storage/pom.xml index 4e9c86fb..69aca8e2 100644 --- a/iot-server/server-library/library-util/pom.xml +++ b/iot-server/server-storage-plugin/server-none-storage/pom.xml @@ -3,26 +3,29 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - server-library + server-storage-plugin com.zmops 1.0-beta - ../pom.xml 4.0.0 - library-util - - - 8 - 8 - - + server-none-storage com.zmops - iot-util + library-module + 1.0.3-RELEASE + + + com.zmops + server-core ${project.version} + + 8 + 8 + + \ No newline at end of file diff --git a/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/BatchDaoNoop.java b/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/BatchDaoNoop.java new file mode 100644 index 00000000..8b54a14c --- /dev/null +++ b/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/BatchDaoNoop.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.server.storage.plugin.none; + +import com.zmops.zeus.iot.server.core.storage.IBatchDAO; +import com.zmops.zeus.iot.server.client.request.InsertRequest; +import com.zmops.zeus.iot.server.client.request.PrepareRequest; + +import java.util.List; + +/** + * @author nantian created at 2021/9/27 21:28 + */ +public class BatchDaoNoop implements IBatchDAO { + + @Override + public void insert(InsertRequest insertRequest) { + + } + + @Override + public void flush(List prepareRequests) { + + } +} diff --git a/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/NoneStorageProvider.java b/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/NoneStorageProvider.java new file mode 100644 index 00000000..a5259673 --- /dev/null +++ b/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/NoneStorageProvider.java @@ -0,0 +1,52 @@ +package com.zmops.zeus.iot.server.storage.plugin.none; + +import com.zmops.zeus.iot.server.core.storage.IBatchDAO; +import com.zmops.zeus.iot.server.core.storage.StorageDAO; +import com.zmops.zeus.iot.server.core.storage.StorageModule; +import com.zmops.zeus.server.library.module.*; + +/** + * @author nantian created at 2021/9/27 21:18 + *

+ * Proxy 模式下,或者 不使用默认的 TDEngine 时 + */ +public class NoneStorageProvider extends ModuleProvider { + @Override + public String name() { + return "none"; + } + + @Override + public Class module() { + return StorageModule.class; + } + + @Override + public ModuleConfig createConfigBeanIfAbsent() { + return new ModuleConfig() { + }; + } + + @Override + public void prepare() throws ServiceNotProvidedException, ModuleStartException { + + this.registerServiceImplementation(IBatchDAO.class, new BatchDaoNoop()); + this.registerServiceImplementation(StorageDAO.class, new StorageDAONoop()); + + } + + @Override + public void start() throws ServiceNotProvidedException, ModuleStartException { + + } + + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { + + } + + @Override + public String[] requiredModules() { + return new String[0]; + } +} diff --git a/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/StorageDAONoop.java b/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/StorageDAONoop.java new file mode 100644 index 00000000..8828c327 --- /dev/null +++ b/iot-server/server-storage-plugin/server-none-storage/src/main/java/com/zmops/zeus/iot/server/storage/plugin/none/StorageDAONoop.java @@ -0,0 +1,15 @@ +package com.zmops.zeus.iot.server.storage.plugin.none; + +import com.zmops.zeus.iot.server.core.storage.IRecordDAO; +import com.zmops.zeus.iot.server.core.storage.StorageDAO; + +/** + * @author nantian created at 2021/9/27 21:29 + */ +public class StorageDAONoop implements StorageDAO { + + @Override + public IRecordDAO newRecordDao() { + return null; + } +} diff --git a/iot-server/server-storage-plugin/server-none-storage/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider b/iot-server/server-storage-plugin/server-none-storage/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider new file mode 100644 index 00000000..e6a4eba8 --- /dev/null +++ b/iot-server/server-storage-plugin/server-none-storage/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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 +# +# http://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. +# +# + +com.zmops.zeus.iot.server.storage.plugin.none.NoneStorageProvider diff --git a/iot-server/server-receiver-plugin/tcp-receiver-plugin/pom.xml b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml similarity index 63% rename from iot-server/server-receiver-plugin/tcp-receiver-plugin/pom.xml rename to iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml index bcd2a5f5..32f4c3a5 100644 --- a/iot-server/server-receiver-plugin/tcp-receiver-plugin/pom.xml +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/pom.xml @@ -3,43 +3,35 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - server-receiver-plugin + server-storage-plugin com.zmops 1.0-beta 4.0.0 - tcp-receiver-plugin + server-tdengine-plugin + + 8 + 8 + - org.apache.camel - camel-netty4 - ${camel.version} - - - io.netty - netty-example - - + com.taosdata.jdbc + taos-jdbcdriver + 2.0.32 com.zmops library-module - ${project.version} + 1.0.3-RELEASE com.zmops server-core 1.0-beta - compile - - 8 - 8 - - \ No newline at end of file diff --git a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/ProducerThreadPartitioner.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLBuilder.java similarity index 54% rename from iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/ProducerThreadPartitioner.java rename to iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLBuilder.java index 80a5a08c..1538d792 100644 --- a/iot-common/iot-datacarrier/src/main/java/com/zmops/zeus/iot/server/datacarrier/partition/ProducerThreadPartitioner.java +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLBuilder.java @@ -16,22 +16,41 @@ * */ -package com.zmops.zeus.iot.server.datacarrier.partition; +package com.zmops.zeus.iot.server.storage.plugin.jdbc; /** - * use threadid % total to partition + * SQLBuilder */ -public class ProducerThreadPartitioner implements IDataPartitioner { - public ProducerThreadPartitioner() { +public class SQLBuilder { + private static String LINE_END = System.lineSeparator(); + + private StringBuilder text; + + public SQLBuilder() { + this.text = new StringBuilder(); } - @Override - public int partition(int total, T data) { - return (int) Thread.currentThread().getId() % total; + public SQLBuilder(String initLine) { + this(); + this.appendLine(initLine); + } + + public SQLBuilder append(String fragment) { + text.append(fragment); + return this; + } + + public SQLBuilder appendLine(String line) { + text.append(line).append(LINE_END); + return this; + } + + public String toStringInNewLine() { + return LINE_END + toString(); } @Override - public int maxRetryCount() { - return 1; + public String toString() { + return text.toString(); } } diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java new file mode 100644 index 00000000..9eefa240 --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/SQLExecutor.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 + * + * http://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.zmops.zeus.iot.server.storage.plugin.jdbc; + +import com.zmops.zeus.iot.server.client.request.InsertRequest; +import lombok.Getter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; + +/** + * A SQL executor. + */ +public class SQLExecutor implements InsertRequest { + + private static final Logger LOGGER = LoggerFactory.getLogger(SQLExecutor.class); + + @Getter + private final String sql; + private final List param; + + public SQLExecutor(String sql, List param) { + this.sql = sql; + this.param = param; + } + + public void invoke(Connection connection) throws SQLException { + PreparedStatement preparedStatement = connection.prepareStatement(sql); + + for (int i = 0; i < param.size(); i++) { + preparedStatement.setObject(i + 1, param.get(i)); + } + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("execute sql in batch: {}, parameters: {}", sql, param); + } + preparedStatement.execute(); + } +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java new file mode 100644 index 00000000..796a42c9 --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineBatchDAO.java @@ -0,0 +1,125 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine; + +import com.zmops.zeus.iot.server.core.UnexpectedException; +import com.zmops.zeus.iot.server.core.storage.IBatchDAO; +import com.zmops.zeus.iot.server.client.jdbc.JDBCClientException; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.iot.server.client.request.InsertRequest; +import com.zmops.zeus.iot.server.client.request.PrepareRequest; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLBuilder; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLExecutor; +import com.zmops.zeus.server.datacarrier.DataCarrier; +import com.zmops.zeus.server.datacarrier.consumer.BulkConsumePool; +import com.zmops.zeus.server.datacarrier.consumer.ConsumerPoolFactory; +import com.zmops.zeus.server.datacarrier.consumer.IConsumer; +import com.zmops.zeus.server.library.util.CollectionUtils; +import lombok.extern.slf4j.Slf4j; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @author nantian created at 2021/9/4 0:31 + */ +@Slf4j +public class TDEngineBatchDAO implements IBatchDAO { + + private final JDBCHikariCPClient tdengineClient; + private final DataCarrier dataCarrier; + + private final ExecutorService executor = Executors.newFixedThreadPool(10); + + public TDEngineBatchDAO(JDBCHikariCPClient client) { + this.tdengineClient = client; + + String name = "TDENGINE_ASYNCHRONOUS_BATCH_PERSISTENT"; + + BulkConsumePool.Creator creator = new BulkConsumePool.Creator(name, 1, 20); + try { + ConsumerPoolFactory.INSTANCE.createIfAbsent(name, creator); + } catch (Exception e) { + throw new UnexpectedException(e.getMessage(), e); + } + + this.dataCarrier = new DataCarrier<>(4, 2500); + this.dataCarrier.consume(ConsumerPoolFactory.INSTANCE.get(name), new TDEngineBatchConsumer(this)); + } + + + @Override + public void flush(List prepareRequests) { + if (CollectionUtils.isEmpty(prepareRequests)) { + return; + } + + if (log.isDebugEnabled()) { + log.debug("batch sql statements execute, data size: {}", prepareRequests.size()); + } + + SQLBuilder execSql = new SQLBuilder(" INSERT INTO "); + for (PrepareRequest prepareRequest : prepareRequests) { + SQLExecutor sqlExecutor = (SQLExecutor) prepareRequest; + execSql.appendLine(sqlExecutor.getSql()); + } + execSql.append(";"); + + executor.submit(() -> { + PreparedStatement preparedStatement; + Connection connection = null; + try { + connection = tdengineClient.getConnection(); + preparedStatement = connection.prepareStatement(execSql.toString()); + preparedStatement.execute(); + } catch (SQLException | JDBCClientException e) { + e.printStackTrace(); + } finally { + try { + if (connection != null) { + connection.close(); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + }); + + + } + + @Override + public void insert(InsertRequest insertRequest) { + this.dataCarrier.produce(insertRequest); + } + + private static class TDEngineBatchConsumer implements IConsumer { + + private final TDEngineBatchDAO tdengineBatchDAO; + + private TDEngineBatchConsumer(TDEngineBatchDAO h2BatchDAO) { + this.tdengineBatchDAO = h2BatchDAO; + } + + @Override + public void init() { + + } + + @Override + public void consume(List prepareRequests) { + tdengineBatchDAO.flush(prepareRequests); + } + + @Override + public void onError(List prepareRequests, Throwable t) { + log.error(t.getMessage(), t); + } + + @Override + public void onExit() { + } + } +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java new file mode 100644 index 00000000..0e5bd558 --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineDatabaseInstaller.java @@ -0,0 +1,53 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine; + +import com.zmops.zeus.iot.server.core.storage.StorageException; +import com.zmops.zeus.iot.server.client.Client; +import com.zmops.zeus.iot.server.client.jdbc.JDBCClientException; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.server.library.module.ModuleManager; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + * @author nantian created at 2021/9/4 1:16 + */ +public class TDEngineDatabaseInstaller { + + protected final Client client; + private final ModuleManager moduleManager; + private final TDEngineStorageConfig config; + + private static final String CREATE_ZEUS_STABLE_HISTORY = "create stable if not exists history(clock TIMESTAMP, value DOUBLE) tags (deviceid BINARY(64), itemid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_HISTORY_UINT = "create stable if not exists history_uint(clock TIMESTAMP, value BIGINT) tags (deviceid BINARY(64), itemid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_HISTORY_TEXT = "create stable if not exists history_text(clock TIMESTAMP, value NCHAR(2048)) tags (deviceid BINARY(64), itemid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_HISTORY_STR = "create stable if not exists history_str(clock TIMESTAMP, value NCHAR(255)) tags (deviceid BINARY(64), itemid BINARY(20))"; + + + private static final String CREATE_ZEUS_STABLE_TRENDS = "create stable if not exists trends(clock TIMESTAMP, value_min DOUBLE, value_avg DOUBLE, value_max DOUBLE) tags (hostid BINARY(64), itemid BINARY(20))"; + private static final String CREATE_ZEUS_STABLE_TRENDS_UINT = "create stable if not exists trends_uint(clock TIMESTAMP, value_min BIGINT, value_avg BIGINT, value_max BIGINT) tags (hostid BINARY(64), itemid BINARY(20))"; + + public TDEngineDatabaseInstaller(Client client, ModuleManager moduleManager, TDEngineStorageConfig config) { + this.config = config; + this.client = client; + this.moduleManager = moduleManager; + } + + protected void createDatabase() throws StorageException { + JDBCHikariCPClient jdbcHikariCPClient = (JDBCHikariCPClient) client; + try (Connection connection = jdbcHikariCPClient.getConnection()) { + + jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_HISTORY); + jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_HISTORY_UINT); + jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_HISTORY_TEXT); + jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_HISTORY_STR); + jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_TRENDS); + jdbcHikariCPClient.execute(connection, CREATE_ZEUS_STABLE_TRENDS_UINT); + + } catch (JDBCClientException | SQLException e) { + throw new StorageException(e.getMessage(), e); + } + + } + +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java new file mode 100644 index 00000000..16ef582c --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageConfig.java @@ -0,0 +1,24 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine; + +import com.zmops.zeus.server.library.module.ModuleConfig; +import lombok.Getter; +import lombok.Setter; + +/** + * @author nantian created at 2021/9/3 23:40 + */ +@Setter +@Getter +public class TDEngineStorageConfig extends ModuleConfig { + + private final String driver = "com.taosdata.jdbc.TSDBDriver"; + + private String url = ""; + private String user = ""; + private String password = ""; + + private int dataKeep = 365; //数据保留天数 + private int oneFileDays = 10; // 每多少天一个数据文件 + private int memoryBlocks = 6; // 内存块数 + private int dataUpdate = 1; // 是否允许更新数据,1 允许 +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java new file mode 100644 index 00000000..79e525bc --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/TDEngineStorageProvider.java @@ -0,0 +1,84 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine; + +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.iot.server.core.CoreModule; +import com.zmops.zeus.iot.server.core.storage.IBatchDAO; +import com.zmops.zeus.iot.server.core.storage.StorageDAO; +import com.zmops.zeus.iot.server.core.storage.StorageException; +import com.zmops.zeus.iot.server.core.storage.StorageModule; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.dao.TDEngineStorageDAO; +import com.zmops.zeus.iot.server.telemetry.TelemetryModule; +import com.zmops.zeus.iot.server.telemetry.api.HealthCheckMetrics; +import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; +import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import com.zmops.zeus.server.library.module.*; + +import java.util.Properties; + +/** + * @author nantian created at 2021/9/3 23:39 + */ +public class TDEngineStorageProvider extends ModuleProvider { + + private final TDEngineStorageConfig config; + private JDBCHikariCPClient client; + + public TDEngineStorageProvider() { + this.config = new TDEngineStorageConfig(); + } + + @Override + public String name() { + return "tdengine"; + } + + @Override + public Class module() { + return StorageModule.class; + } + + @Override + public ModuleConfig createConfigBeanIfAbsent() { + return config; + } + + @Override + public void prepare() throws ServiceNotProvidedException, ModuleStartException { + Properties settings = new Properties(); + settings.setProperty("jdbcUrl", config.getUrl()); + settings.setProperty("dataSource.user", config.getUser()); + settings.setProperty("dataSource.password", config.getPassword()); + client = new JDBCHikariCPClient(settings); + + this.registerServiceImplementation(IBatchDAO.class, new TDEngineBatchDAO(client)); + this.registerServiceImplementation(StorageDAO.class, new TDEngineStorageDAO(getManager(), client)); + } + + @Override + public void start() throws ServiceNotProvidedException, ModuleStartException { + + MetricsCreator metricCreator = getManager().find(TelemetryModule.NAME).provider().getService(MetricsCreator.class); + HealthCheckMetrics healthChecker = metricCreator.createHealthCheckerGauge("storage_tdengine", MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE); + + client.registerChecker(healthChecker); + client.connect(); + + TDEngineDatabaseInstaller installer = new TDEngineDatabaseInstaller(client, getManager(), config); + try { + installer.createDatabase(); + } catch (StorageException e) { + e.printStackTrace(); + } +// getManager().find(CoreModule.NAME).provider().getService(ModelCreator.class).addModelListener(installer); + } + + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { + + } + + @Override + public String[] requiredModules() { + return new String[]{CoreModule.NAME}; + } +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineRecordDAO.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineRecordDAO.java new file mode 100644 index 00000000..146ac37b --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineRecordDAO.java @@ -0,0 +1,26 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.dao; + +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.storage.IRecordDAO; +import com.zmops.zeus.iot.server.core.storage.model.Model; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.iot.server.client.request.InsertRequest; + +import java.io.IOException; + +/** + * @author nantian created at 2021/9/5 0:27 + */ +public class TDEngineRecordDAO extends TDEngineSqlExecutor implements IRecordDAO { + + private final JDBCHikariCPClient jdbcClient; + + public TDEngineRecordDAO(JDBCHikariCPClient jdbcClient) { + this.jdbcClient = jdbcClient; + } + + @Override + public InsertRequest prepareBatchInsert(Model model, Record record) throws IOException { + return getInsertExecutor(model.getName(), record); + } +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java new file mode 100644 index 00000000..2257a077 --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineSqlExecutor.java @@ -0,0 +1,68 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.dao; + +import com.zmops.zeus.iot.server.core.analysis.manual.history.History; +import com.zmops.zeus.iot.server.core.analysis.manual.history.StrHistory; +import com.zmops.zeus.iot.server.core.analysis.manual.history.TextHistory; +import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; +import com.zmops.zeus.iot.server.core.storage.StorageData; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLBuilder; +import com.zmops.zeus.iot.server.storage.plugin.jdbc.SQLExecutor; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author nantian created at 2021/9/5 0:29 + */ + +@Slf4j +public class TDEngineSqlExecutor { + + protected SQLExecutor getInsertExecutor(String modelName, T metrics) { + + SQLBuilder sqlBuilder = new SQLBuilder(); + + if (modelName.equals("history")) { + + History history = (History) metrics; + sqlBuilder.append("h_").append(metrics.itemid() + " USING ").append("history (deviceid, itemid) TAGS") + .append("('").append(history.getDeviceId()).append("'") + .append(",").append(history.getItemid() + " )") + .append(" VALUES (") + .append(history.getClock() + "").append(",").append(history.getValue()).append(")"); + + } else if (modelName.equals("history_uint")) { + + UIntHistory uihistory = (UIntHistory) metrics; + sqlBuilder.append("huint_").append(metrics.itemid() + " USING ").append("history_uint (deviceid, itemid) TAGS") + .append(" ('").append(uihistory.getDeviceId()).append("'") + .append(",").append(uihistory.getItemid() + " )") + .append(" VALUES (") + .append(uihistory.getClock() + "").append(",").append(uihistory.getValue()).append(")"); + } else if (modelName.equals("history_text")) { + + TextHistory textHistory = (TextHistory) metrics; + String value = textHistory.getValue().replaceAll(",", "\\,"); + + sqlBuilder.append("htxt_").append(metrics.itemid() + " USING ").append("history_text (deviceid, itemid) TAGS") + .append(" ('").append(textHistory.getDeviceId()).append("'") + .append(",").append(textHistory.getItemid() + " )") + .append(" VALUES (") + .append(textHistory.getClock() + "").append(",'").append(value).append("')"); + } else if (modelName.equals("history_str")) { + + StrHistory strHistory = (StrHistory) metrics; + String value = strHistory.getValue().replaceAll(",", "\\,"); + sqlBuilder.append("hstr_").append(metrics.itemid() + " USING ").append("history_str (deviceid, itemid) TAGS") + .append(" ('").append(strHistory.getDeviceId()).append("'") + .append(",").append(strHistory.getItemid() + " )") + .append(" VALUES (") + .append(strHistory.getClock() + "").append(",'").append(value).append("')"); + } + + List param = new ArrayList<>(); + return new SQLExecutor(sqlBuilder.toString(), param); + } + +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java new file mode 100644 index 00000000..f309abb9 --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/java/com/zmops/zeus/iot/server/storage/plugin/jdbc/tdengine/dao/TDEngineStorageDAO.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.dao; + +import com.zmops.zeus.iot.server.core.storage.IRecordDAO; +import com.zmops.zeus.iot.server.core.storage.StorageDAO; +import com.zmops.zeus.iot.server.client.jdbc.hikaricp.JDBCHikariCPClient; +import com.zmops.zeus.server.library.module.ModuleManager; +import lombok.RequiredArgsConstructor; + +/** + * @author nantian created at 2021/9/6 16:33 + */ +@RequiredArgsConstructor +public class TDEngineStorageDAO implements StorageDAO { + + private final ModuleManager manager; + private final JDBCHikariCPClient client; + + + @Override + public IRecordDAO newRecordDao() { + return new TDEngineRecordDAO(client); + } +} diff --git a/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider new file mode 100644 index 00000000..4f238716 --- /dev/null +++ b/iot-server/server-storage-plugin/server-tdengine-plugin/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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 +# +# http://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. +# +# + + +com.zmops.zeus.iot.server.storage.plugin.jdbc.tdengine.TDEngineStorageProvider \ No newline at end of file diff --git a/iot-server/server-telemetry/telemetry-api/pom.xml b/iot-server/server-telemetry/telemetry-api/pom.xml index d914f617..3f5ccc39 100644 --- a/iot-server/server-telemetry/telemetry-api/pom.xml +++ b/iot-server/server-telemetry/telemetry-api/pom.xml @@ -14,7 +14,13 @@ com.zmops library-module - 1.0-beta + 1.0.3-RELEASE + compile + + + com.zmops + library-util + 1.0.3-RELEASE compile diff --git a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/TelemetryModule.java b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/TelemetryModule.java index 2a48563b..d522619e 100644 --- a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/TelemetryModule.java +++ b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/TelemetryModule.java @@ -20,7 +20,7 @@ import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; -import com.zmops.zeus.iot.server.library.module.ModuleDefine; +import com.zmops.zeus.server.library.module.ModuleDefine; /** * Telemetry module definition diff --git a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/HealthCheckMetrics.java b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/HealthCheckMetrics.java index bb52a83d..26cbeb64 100644 --- a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/HealthCheckMetrics.java +++ b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/HealthCheckMetrics.java @@ -18,7 +18,7 @@ package com.zmops.zeus.iot.server.telemetry.api; -import com.zmops.zeus.iot.server.library.util.HealthChecker; +import com.zmops.zeus.server.library.util.HealthChecker; import lombok.extern.slf4j.Slf4j; diff --git a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCollector.java b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCollector.java index 200c2475..dba11614 100644 --- a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCollector.java +++ b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCollector.java @@ -19,7 +19,7 @@ package com.zmops.zeus.iot.server.telemetry.api; -import com.zmops.zeus.iot.server.library.module.Service; +import com.zmops.zeus.server.library.module.Service; /** * Collect all metrics from telemetry. diff --git a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCreator.java b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCreator.java index 1c3d264d..728d7b3f 100644 --- a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCreator.java +++ b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/api/MetricsCreator.java @@ -20,7 +20,7 @@ import com.google.common.base.Preconditions; import com.google.common.base.Strings; -import com.zmops.zeus.iot.server.library.module.Service; +import com.zmops.zeus.server.library.module.Service; /** diff --git a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/MetricsCollectorNoop.java b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/MetricsCollectorNoop.java index 0fc4b586..43da813d 100644 --- a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/MetricsCollectorNoop.java +++ b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/MetricsCollectorNoop.java @@ -19,7 +19,6 @@ package com.zmops.zeus.iot.server.telemetry.none; - import com.zmops.zeus.iot.server.telemetry.api.MetricFamily; import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; diff --git a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/NoneTelemetryProvider.java b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/NoneTelemetryProvider.java index 8139008d..1a638bc3 100644 --- a/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/NoneTelemetryProvider.java +++ b/iot-server/server-telemetry/telemetry-api/src/main/java/com/zmops/zeus/iot/server/telemetry/none/NoneTelemetryProvider.java @@ -19,10 +19,10 @@ package com.zmops.zeus.iot.server.telemetry.none; -import com.zmops.zeus.iot.server.library.module.*; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; +import com.zmops.zeus.server.library.module.*; /** * A nutshell telemetry implementor. diff --git a/iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine b/iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine similarity index 100% rename from iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleDefine rename to iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine diff --git a/iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-telemetry/telemetry-api/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-telemetry/telemetry-prometheus/pom.xml b/iot-server/server-telemetry/telemetry-prometheus/pom.xml index f809ee3b..81143099 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/pom.xml +++ b/iot-server/server-telemetry/telemetry-prometheus/pom.xml @@ -42,8 +42,8 @@ com.zmops - library-server - 1.0-beta + zeus-server-jetty + 1.0.3-RELEASE compile diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/BaseMetrics.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/BaseMetrics.java index cefd247c..82b22d3b 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/BaseMetrics.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/BaseMetrics.java @@ -18,9 +18,9 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import io.prometheus.client.SimpleCollector; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; import com.zmops.zeus.iot.server.telemetry.api.TelemetryRelatedContext; +import io.prometheus.client.SimpleCollector; import java.util.HashMap; import java.util.Map; diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusConfig.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusConfig.java index eacd1f51..e4fb6fea 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusConfig.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusConfig.java @@ -18,7 +18,7 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import com.zmops.zeus.iot.server.library.module.ModuleConfig; +import com.zmops.zeus.server.library.module.ModuleConfig; import lombok.Getter; import lombok.Setter; diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusCounterMetrics.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusCounterMetrics.java index 42f814ef..42f580ee 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusCounterMetrics.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusCounterMetrics.java @@ -18,9 +18,9 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import io.prometheus.client.Counter; import com.zmops.zeus.iot.server.telemetry.api.CounterMetrics; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import io.prometheus.client.Counter; /** * Counter metrics in Prometheus implementor. diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusGaugeMetrics.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusGaugeMetrics.java index 11480d08..07004589 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusGaugeMetrics.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusGaugeMetrics.java @@ -18,9 +18,9 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import io.prometheus.client.Gauge; import com.zmops.zeus.iot.server.telemetry.api.GaugeMetrics; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import io.prometheus.client.Gauge; import java.util.Optional; diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusHistogramMetrics.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusHistogramMetrics.java index 3b4d8ccb..53cada9f 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusHistogramMetrics.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusHistogramMetrics.java @@ -18,9 +18,9 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import io.prometheus.client.Histogram; import com.zmops.zeus.iot.server.telemetry.api.HistogramMetrics; import com.zmops.zeus.iot.server.telemetry.api.MetricsTag; +import io.prometheus.client.Histogram; /** * HistogramMetrics metrics in Prometheus implementor. @@ -30,7 +30,7 @@ public class PrometheusHistogramMetrics extends HistogramMetrics { private final double[] buckets; public PrometheusHistogramMetrics(String name, String tips, MetricsTag.Keys labels, MetricsTag.Values values, - double... buckets) { + double... buckets) { inner = new InnerMetricObject(name, tips, labels, values); this.buckets = buckets; } diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCollector.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCollector.java index 34934e39..d9e76f2f 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCollector.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCollector.java @@ -18,10 +18,10 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import io.prometheus.client.Collector; -import io.prometheus.client.CollectorRegistry; import com.zmops.zeus.iot.server.telemetry.api.MetricFamily; import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; +import io.prometheus.client.Collector; +import io.prometheus.client.CollectorRegistry; import java.util.ArrayList; import java.util.Enumeration; @@ -29,14 +29,15 @@ import java.util.List; public class PrometheusMetricsCollector implements MetricsCollector { - @Override public Iterable collect() { + @Override + public Iterable collect() { Enumeration mfs = CollectorRegistry.defaultRegistry.metricFamilySamples(); List result = new LinkedList<>(); while (mfs.hasMoreElements()) { Collector.MetricFamilySamples metricFamilySamples = mfs.nextElement(); List samples = new ArrayList<>(metricFamilySamples.samples.size()); MetricFamily m = new MetricFamily(metricFamilySamples.name, MetricFamily.Type.valueOf(metricFamilySamples.type - .name()), metricFamilySamples.help, samples); + .name()), metricFamilySamples.help, samples); result.add(m); for (Collector.MetricFamilySamples.Sample sample : metricFamilySamples.samples) { samples.add(new MetricFamily.Sample(sample.name, sample.labelNames, sample.labelValues, sample.value, sample.timestampMs)); diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCreator.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCreator.java index 355316f0..39150caf 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCreator.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusMetricsCreator.java @@ -26,7 +26,7 @@ public class PrometheusMetricsCreator implements MetricsCreator { @Override public CounterMetrics createCounter(String name, String tips, MetricsTag.Keys tagKeys, - MetricsTag.Values tagValues) { + MetricsTag.Values tagValues) { return new PrometheusCounterMetrics(name, tips, tagKeys, tagValues); } @@ -37,7 +37,7 @@ public GaugeMetrics createGauge(String name, String tips, MetricsTag.Keys tagKey @Override public HistogramMetrics createHistogramMetric(String name, String tips, MetricsTag.Keys tagKeys, - MetricsTag.Values tagValues, double... buckets) { + MetricsTag.Values tagValues, double... buckets) { return new PrometheusHistogramMetrics(name, tips, tagKeys, tagValues, buckets); } } diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusTelemetryProvider.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusTelemetryProvider.java index 43909f36..d93fa0b1 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusTelemetryProvider.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/PrometheusTelemetryProvider.java @@ -18,11 +18,11 @@ package com.zmops.zeus.iot.server.telemetry.prometheus; -import com.zmops.zeus.iot.server.library.module.*; import com.zmops.zeus.iot.server.telemetry.TelemetryModule; import com.zmops.zeus.iot.server.telemetry.api.MetricsCollector; import com.zmops.zeus.iot.server.telemetry.api.MetricsCreator; import com.zmops.zeus.iot.server.telemetry.prometheus.httpserver.HttpServer; +import com.zmops.zeus.server.library.module.*; import io.prometheus.client.hotspot.DefaultExports; /** diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java index 0ef00847..807b64ea 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServer.java @@ -19,7 +19,8 @@ package com.zmops.zeus.iot.server.telemetry.prometheus.httpserver; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import com.zmops.zeus.iot.server.library.server.ssl.HttpDynamicSslContext; +import com.zmops.zeus.iot.server.telemetry.prometheus.PrometheusConfig; +import com.zmops.zeus.server.ssl.HttpDynamicSslContext; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; @@ -29,8 +30,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import com.zmops.zeus.iot.server.telemetry.prometheus.PrometheusConfig; - import java.util.Optional; import java.util.concurrent.ThreadFactory; @@ -54,10 +53,10 @@ public void start() throws InterruptedException { } // Configure the server. - ThreadFactory tf = new ThreadFactoryBuilder().setDaemon(true).build(); - EventLoopGroup bossGroup = new NioEventLoopGroup(1, tf); - EventLoopGroup workerGroup = new NioEventLoopGroup(0, tf); - ServerBootstrap b = new ServerBootstrap(); + ThreadFactory tf = new ThreadFactoryBuilder().setDaemon(true).build(); + EventLoopGroup bossGroup = new NioEventLoopGroup(1, tf); + EventLoopGroup workerGroup = new NioEventLoopGroup(0, tf); + ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServerHandler.java b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServerHandler.java index c063c1a6..382e9b86 100644 --- a/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServerHandler.java +++ b/iot-server/server-telemetry/telemetry-prometheus/src/main/java/com/zmops/zeus/iot/server/telemetry/prometheus/httpserver/HttpServerHandler.java @@ -42,8 +42,8 @@ @Slf4j public class HttpServerHandler extends SimpleChannelInboundHandler { - private final CollectorRegistry registry = CollectorRegistry.defaultRegistry; - private final StringBuilderWriter buf = new StringBuilderWriter(); + private final CollectorRegistry registry = CollectorRegistry.defaultRegistry; + private final StringBuilderWriter buf = new StringBuilderWriter(); @Override public void channelReadComplete(ChannelHandlerContext ctx) { diff --git a/iot-server/server-telemetry/telemetry-prometheus/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider b/iot-server/server-telemetry/telemetry-prometheus/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider similarity index 100% rename from iot-server/server-telemetry/telemetry-prometheus/src/main/resources/META-INF/services/com.zmops.zeus.iot.server.library.module.ModuleProvider rename to iot-server/server-telemetry/telemetry-prometheus/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider diff --git a/iot-server/server-transfer/pom.xml b/iot-server/server-transfer/pom.xml new file mode 100644 index 00000000..09c574cb --- /dev/null +++ b/iot-server/server-transfer/pom.xml @@ -0,0 +1,81 @@ + + + + iot-server + com.zmops + 1.0-beta + + 4.0.0 + 读取 Zabbix 历史数据文件 + + server-transfer + + + 8 + 8 + + + + + com.zmops + zeus-transfer-tailx + 1.0.3-RELEASE + + + + + + + + + + + + + + + + + + + com.zmops + library-module + 1.0.3-RELEASE + + + com.zmops + server-core + 1.0-beta + compile + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/module/ServerTransferModule.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/module/ServerTransferModule.java new file mode 100644 index 00000000..5f06b94f --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/module/ServerTransferModule.java @@ -0,0 +1,21 @@ +package com.zmops.zeus.iot.server.transfer.module; + +import com.zmops.zeus.server.library.module.ModuleDefine; + +/** + * @author nantian created at 2021/9/22 16:39 + */ +public class ServerTransferModule extends ModuleDefine { + + public static final String NAME = "server-transfer"; + + + public ServerTransferModule() { + super(NAME); + } + + @Override + public Class[] services() { + return new Class[0]; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java new file mode 100644 index 00000000..49918e81 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferConfig.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.server.transfer.provider; + +import com.zmops.zeus.server.library.module.ModuleConfig; +import lombok.Getter; +import lombok.Setter; + +/** + * @author nantian created at 2021/9/22 16:46 + *

+ * ndjson 文件读取配置 + */ +@Getter +@Setter +public class ServerTransferConfig extends ModuleConfig { + + private String name; + + private String pattern; + + // 文件读取超时 线程回收 + private Integer fileMaxWait; + +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java new file mode 100644 index 00000000..c3471da0 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/provider/ServerTransferProvider.java @@ -0,0 +1,84 @@ +package com.zmops.zeus.iot.server.transfer.provider; + + +import com.zmops.zeus.iot.server.core.CoreModule; +import com.zmops.zeus.iot.server.transfer.module.ServerTransferModule; +import com.zmops.zeus.server.library.module.*; +import com.zmops.zeus.server.transfer.core.TransferManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author nantian created at 2021/9/22 16:44 + */ +public class ServerTransferProvider extends ModuleProvider { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServerTransferProvider.class); + + private final ServerTransferConfig config; + + public ServerTransferProvider() { + this.config = new ServerTransferConfig(); + } + + @Override + public String name() { + return "default"; + } + + @Override + public Class module() { + return ServerTransferModule.class; + } + + @Override + public ModuleConfig createConfigBeanIfAbsent() { + return config; + } + + @Override + public void prepare() throws ServiceNotProvidedException, ModuleStartException { + + } + + + /** + * Stopping agent gracefully if get killed. + * + * @param manager - agent manager + */ + private static void stopManagerIfKilled(TransferManager manager) { + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + try { + LOGGER.info("stopping agent gracefully"); + manager.stop(); + } catch (Exception ex) { + LOGGER.error("exception while stopping threads", ex); + } + })); + } + + @Override + public void start() throws ServiceNotProvidedException, ModuleStartException { +// TransferManager manager = new TransferManager(config); +// try { +// manager.start(); +// stopManagerIfKilled(manager); +//// manager.join(); +// } catch (Exception e) { +// e.printStackTrace(); +// } + } + + @Override + public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException { + + } + + @Override + public String[] requiredModules() { + return new String[]{ + CoreModule.NAME + }; + } +} diff --git a/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java new file mode 100644 index 00000000..0eef9ed6 --- /dev/null +++ b/iot-server/server-transfer/src/main/java/com/zmops/zeus/iot/server/transfer/sender/SenderManager.java @@ -0,0 +1,126 @@ +package com.zmops.zeus.iot.server.transfer.sender; + +import com.alibaba.fastjson.JSON; +import com.zmops.zeus.iot.server.core.analysis.manual.history.History; +import com.zmops.zeus.iot.server.core.analysis.manual.history.StrHistory; +import com.zmops.zeus.iot.server.core.analysis.manual.history.TextHistory; +import com.zmops.zeus.iot.server.core.analysis.manual.history.UIntHistory; +import com.zmops.zeus.iot.server.core.analysis.record.Record; +import com.zmops.zeus.iot.server.core.analysis.worker.RecordStreamProcessor; +import com.zmops.zeus.server.transfer.conf.JobProfile; +import com.zmops.zeus.server.transfer.core.task.TaskPositionManager; +import com.zmops.zeus.server.transfer.metrics.PluginMetric; +import lombok.Getter; +import lombok.Setter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.StandardCharsets; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + + +/** + * 发送管理 + */ +public class SenderManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(SenderManager.class); + + private final TaskPositionManager taskPositionManager; + private final String sourceFilePath; + + private final PluginMetric metric = new PluginMetric(); + + public SenderManager(JobProfile jobConf, String bid, String sourceFilePath) { + taskPositionManager = TaskPositionManager.getTaskPositionManager(); + this.sourceFilePath = sourceFilePath; + } + + /** + * Send message to proxy by batch, use message cache. + * + * @param bid - bid 方便以后企业版 区分数据来源 + * @param tid - tid + * @param bodyList - body list + * @param retry - retry time + */ + public void sendBatch(String jobId, String bid, String tid, List bodyList, int retry, long dataTime) { + try { + bodyList.forEach(body -> { + ItemValue itemValue = JSON.parseObject(new String(body, StandardCharsets.UTF_8), ItemValue.class); + + Record record; + + if (itemValue.getType() == 3) { //uint + record = new UIntHistory(); + } else if (itemValue.getType() == 0) { + record = new History(); + } else if (itemValue.getType() == 4) { //text + record = new TextHistory(); + } else if (itemValue.getType() == 1) { + record = new StrHistory(); + } else { + return; + } + + record.setItemid(itemValue.itemid); + record.setValue(itemValue.getHost().get("host"), itemValue.value, itemValue.getTimestamp()); + + RecordStreamProcessor.getInstance().in(record); + }); + + metric.sendSuccessNum.incr(bodyList.size()); + taskPositionManager.updateFileSinkPosition(jobId, sourceFilePath, bodyList.size()); + + String fileName; + if (!System.getProperty("os.name").toLowerCase().startsWith("win")) { + String[] i = sourceFilePath.split("/"); + fileName = i[i.length - 1]; + } else { + fileName = sourceFilePath; + } + + LOGGER.info("send bid [{}] with message size [{}], the job id is [{}],the tid is [{}], read file is {}, " + + "dataTime is {}", bid, bodyList.size(), jobId, tid, fileName, dataTime); + + } catch (Exception exception) { + LOGGER.error("Exception caught", exception); + // retry time + try { + TimeUnit.SECONDS.sleep(1); + sendBatch(jobId, bid, tid, bodyList, retry + 1, dataTime); + } catch (Exception ignored) { + // ignore it. + } + } + } + + @Setter + @Getter + static class ItemValue { + + private Integer type; + + private String name; + + private Long clock; + + private Integer itemid; + + private List> item_tags; + + private List groups; + + private Long ns; + + private String value; + + private Map host; + + public Long getTimestamp() { + return Long.valueOf(clock + String.format("%09d", ns).substring(0, 3)); + } + } +} diff --git a/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine b/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine new file mode 100644 index 00000000..22ed049f --- /dev/null +++ b/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleDefine @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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 +# +# http://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. +# +# + +com.zmops.zeus.iot.server.transfer.module.ServerTransferModule diff --git a/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider b/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider new file mode 100644 index 00000000..3f87ef2f --- /dev/null +++ b/iot-server/server-transfer/src/main/resources/META-INF/services/com.zmops.zeus.server.library.module.ModuleProvider @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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 +# +# http://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. +# +# + +com.zmops.zeus.iot.server.transfer.provider.ServerTransferProvider diff --git a/iot-server/server-transfer/src/main/resources/job.json b/iot-server/server-transfer/src/main/resources/job.json new file mode 100644 index 00000000..e030a11f --- /dev/null +++ b/iot-server/server-transfer/src/main/resources/job.json @@ -0,0 +1,13 @@ +{ + "job": { + "id": 1, + "dir": { + "path": "" + } + }, + "proxy": { + "bid": "bid10", + "tid": "bid10" + }, + "op": "add" +} \ No newline at end of file diff --git a/iot-server/server-web/pom.xml b/iot-server/server-web/pom.xml new file mode 100644 index 00000000..a8592113 --- /dev/null +++ b/iot-server/server-web/pom.xml @@ -0,0 +1,78 @@ + + + + iot-server + com.zmops + 1.0-beta + + 4.0.0 + + server-web + + + 8 + 8 + + + + + com.zmops + library-web + 1.0.3-RELEASE + + + + com.zmops + runtime-server + 1.0.3-RELEASE + + + + org.apache.logging.log4j + log4j-web + + + + com.zmops + zeus-commons + 1.0.3-RELEASE + + + com.zmops + library-module + 1.0.3-RELEASE + compile + + + com.zmops + server-camel-receiver + 1.0-beta + compile + + + cn.hutool + hutool-all + 5.7.6 + + + + org.apache.commons + commons-lang3 + 3.12.0 + + + + org.projectlombok + lombok + + + com.zmops + server-localdb + 1.0-beta + compile + + + + \ No newline at end of file diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java new file mode 100644 index 00000000..58503b08 --- /dev/null +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/config/IoTConfig.java @@ -0,0 +1,36 @@ +package com.zmops.zeus.iot.web.config; + +import com.zmops.zeus.server.library.web.config.*; + +/** + * @author nantian created at 2021/11/22 20:48 + */ +public class IoTConfig extends WebConfig { + + @Override + public void configConstant(Constants constants) { + constants.setDevMode(true); + constants.setMaxPostSize(1024 * 1024 * 100); + if (!System.getProperty("os.name").toLowerCase().startsWith("win")) { + constants.setBaseUploadPath("D:\\protocol\\upload"); + } else { + constants.setBaseUploadPath("//opt//zeus//zeus-iot-bin//upload"); + } + } + + @Override + public void configRoute(Routes routes) { + routes.setBaseViewPath("/pages"); + routes.scan("com.zmops.zeus.iot.web.controller."); + } + + @Override + public void configHandler(Handlers handlers) { + + } + + @Override + public void configInterceptor(Interceptors interceptors) { + + } +} diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java new file mode 100644 index 00000000..dd882e30 --- /dev/null +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/IndexController.java @@ -0,0 +1,14 @@ +package com.zmops.zeus.iot.web.controller; + +import com.zmops.zeus.server.library.web.core.Controller; +import com.zmops.zeus.server.library.web.core.Path; + +/** + * @author nantian created at 2021/11/23 23:24 + */ + +@Path(value = "/protocol", viewPath = "/") +public class IndexController extends Controller { + + +} diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/ProtocolComponentController.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/ProtocolComponentController.java new file mode 100644 index 00000000..c0fdc41d --- /dev/null +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/ProtocolComponentController.java @@ -0,0 +1,87 @@ +package com.zmops.zeus.iot.web.controller; + +import com.alipay.sofa.ark.api.ArkClient; +import com.alipay.sofa.ark.api.ClientResponse; +import com.zmops.zeus.iot.server.h2.module.LocalH2Module; +import com.zmops.zeus.iot.server.h2.service.InsertDAO; +import com.zmops.zeus.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.web.core.Controller; +import com.zmops.zeus.server.library.web.core.Path; +import com.zmops.zeus.server.library.web.upload.UploadFile; + +import java.io.File; +import java.io.IOException; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * @author yefei + **/ +@Path(value = "/protocol/component") +public class ProtocolComponentController extends Controller { + + public void saveProtocolComponent() { + String id = getPara("protocolComponentId"); + String uniqueId = getPara("uniqueId"); + InsertDAO localH2InsertDAO = ModuleManager.getInstance() + .find(LocalH2Module.NAME).provider().getService(InsertDAO.class); + localH2InsertDAO.insert("insert into protocol_component(id,unique_id) values(" + id + "," + uniqueId + ")"); + + renderNull(); + } + + public void upload() { + UploadFile file = getFile(); + + try { + String filePath = file.getFile().getCanonicalPath(); + + renderJson("filePath", filePath); + } catch (IOException e) { + e.printStackTrace(); + } + } + + + public void installArk() throws SQLException { + String id = getPara("protocolComponentId"); + String fileName = getPara("fileName"); + InsertDAO localH2InsertDAO = ModuleManager.getInstance() + .find(LocalH2Module.NAME).provider().getService(InsertDAO.class); + ClientResponse response; + try { + if (!System.getProperty("os.name").toLowerCase().startsWith("win")) { + response = ArkClient.installBiz(new File("D:\\protocol\\upload\\" + fileName)); + } else { + response = ArkClient.installBiz(new File("//opt//zeus//zeus-iot-bin//upload//" + fileName)); + } + String bizName = response.getBizInfos().iterator().next().getBizName(); + String bizVersion = response.getBizInfos().iterator().next().getBizVersion(); + int r = localH2InsertDAO.update("update protocol_component set file_name=?, biz_name=?,biz_version = ? where id=?", fileName, bizName, bizVersion, id); + + renderJson(response); + + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void uninstallArk() throws SQLException { + String id = getPara("protocolComponentId"); + InsertDAO localH2InsertDAO = ModuleManager.getInstance() + .find(LocalH2Module.NAME).provider().getService(InsertDAO.class); + ResultSet rs = localH2InsertDAO.queryRes("select * from protocol_component where id=?", id); + String bizName = ""; + String bizVersion = ""; + while (rs.next()) { + bizName = rs.getString(7); + bizVersion = rs.getString(8); + } + try { + ClientResponse response = ArkClient.uninstallBiz(bizName, bizVersion); + renderJson(response); + } catch (Throwable e) { + e.printStackTrace(); + } + } +} diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/ProtocolGatewayController.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/ProtocolGatewayController.java new file mode 100644 index 00000000..c8e1c850 --- /dev/null +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/ProtocolGatewayController.java @@ -0,0 +1,201 @@ +package com.zmops.zeus.iot.web.controller; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.zmops.zeus.iot.server.h2.module.LocalH2Module; +import com.zmops.zeus.iot.server.h2.service.InsertDAO; +import com.zmops.zeus.iot.server.receiver.ProtocolAction; +import com.zmops.zeus.iot.server.receiver.ProtocolEnum; +import com.zmops.zeus.iot.server.receiver.module.CamelReceiverModule; +import com.zmops.zeus.iot.server.receiver.routes.*; +import com.zmops.zeus.iot.server.receiver.service.CamelContextHolderService; +import com.zmops.zeus.iot.web.domain.ProtocolGatewayMqtt; +import com.zmops.zeus.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.web.core.Controller; +import com.zmops.zeus.server.library.web.core.Path; +import lombok.Getter; +import lombok.Setter; +import org.apache.camel.builder.RouteBuilder; +import org.apache.commons.lang3.StringUtils; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +/** + * @author nantian created at 2021/11/23 23:24 + */ + +@Path(value = "/protocol/gateway") +public class ProtocolGatewayController extends Controller { + + public void stopRoute() { + + String routeId = getPara("routeId"); + + stopGateway(routeId); + + renderNull(); + + } + + public void stopGateway(String routeId) { + + CamelContextHolderService camelContextHolderService = ModuleManager.getInstance() + .find(CamelReceiverModule.NAME).provider().getService(CamelContextHolderService.class); + + camelContextHolderService.routeShutDown(routeId); + + InsertDAO localH2InsertDAO = ModuleManager.getInstance() + .find(LocalH2Module.NAME).provider().getService(InsertDAO.class); + + localH2InsertDAO.update("update protocol_gateway set status=1 where id=?", routeId); + + } + + + public void startRoute() { + + String routeId = getPara("routeId"); + + CamelContextHolderService camelContextHolderService = ModuleManager.getInstance() + .find(CamelReceiverModule.NAME).provider().getService(CamelContextHolderService.class); + + camelContextHolderService.routeStartUp(routeId); + + + InsertDAO localH2InsertDAO = ModuleManager.getInstance() + .find(LocalH2Module.NAME).provider().getService(InsertDAO.class); + + localH2InsertDAO.update("update protocol_gateway set status=0 where id=?", routeId); + + renderNull(); + } + + public void createProtocolGateway() { + String routeId = getPara("routeId"); + String name = getPara("name"); + String protocolServiceId = getPara("protocolServiceId"); + String protocolComponentId = getPara("protocolComponentId"); + String status = getPara("status"); + String protocol = getPara("protocol"); + String option = getPara("option"); + String mqttList = getPara("mqttList"); + + InsertDAO localH2InsertDAO = ModuleManager.getInstance() + .find(LocalH2Module.NAME).provider().getService(InsertDAO.class); + localH2InsertDAO.insert("insert into protocol_gateway(id,name,protocol_service_id,protocol_component_id,status) values(" + routeId + ",'" + name + "'," + protocolServiceId + "," + protocolComponentId + ",'" + status + "')"); + + if (StringUtils.isNotBlank(mqttList)) { + saveMqttList(mqttList); + } + Map options = JSON.parseObject(option, Map.class); + createRoute(routeId, ProtocolEnum.valueOf(protocol), options); + } + + public void updateProtocolGateway() throws SQLException { + String routeId = getPara("routeId"); + stopGateway(routeId); + + String name = getPara("name"); + String protocolServiceId = getPara("protocolServiceId"); + String protocolComponentId = getPara("protocolComponentId"); + String remark = getPara("remark"); + String option = getPara("option"); + String mqttList = getPara("mqttList"); + + InsertDAO localH2InsertDAO = ModuleManager.getInstance() + .find(LocalH2Module.NAME).provider().getService(InsertDAO.class); + + StringBuilder sql = new StringBuilder("update protocol_gateway set protocol_service_id=?"); + if (StringUtils.isNotBlank(name)) { + sql.append(" ,name =?"); + } + if (StringUtils.isNotBlank(protocolComponentId)) { + sql.append(" ,protocolComponentId =?"); + } + if (StringUtils.isNotBlank(remark)) { + sql.append(" ,remark =?"); + } + sql.append(" where id=?"); + + localH2InsertDAO.update("", protocolServiceId, name, protocolComponentId, remark, routeId); + + localH2InsertDAO.delete("delete from protocol_gateway_mqtt where protocol_gateway_id = " + routeId); + if (StringUtils.isNotBlank(mqttList)) { + saveMqttList(mqttList); + } + Map options = JSON.parseObject(option, Map.class); + + ResultSet rs = localH2InsertDAO.queryRes("select * from protocol_service where id=?", protocolServiceId); + String protocol = ""; + while (rs.next()) { + protocol = rs.getString(9); + } + createRoute(routeId, ProtocolEnum.valueOf(protocol), options); + } + + public void createRoute(String routeId, ProtocolEnum protocol, Map options) { + + CamelContextHolderService camelContextHolderService = ModuleManager.getInstance() + .find(CamelReceiverModule.NAME).provider().getService(CamelContextHolderService.class); + + RouteBuilder route = null; + switch (protocol) { + case HttpServer: + route = new HttpRouteBuilder(routeId, options); + break; + case MqttClient: + route = new MqttClientRouteBuilder(routeId, options); + break; + case TcpServer: + route = new TcpServerRouteBuilder(routeId, options); + break; + case UdpServer: + route = new UdpServerRouteBuilder(routeId, options); + break; + case CoapServer: + route = new CoapServerRouteBuilder(routeId, options); + break; + case WebSocketServer: + route = new WebSocketServerRouteBuilder(routeId, options); + break; + default: + break; + } + + if (route != null) { + camelContextHolderService.addRoutes(route); + } + + + renderNull(); + } + + private void saveMqttList(String mqttList) { + List protocolGatewayMqtts = JSONObject.parseArray(mqttList, ProtocolGatewayMqtt.class); + if (protocolGatewayMqtts == null || protocolGatewayMqtts.size() <= 0) { + return; + } + InsertDAO localH2InsertDAO = ModuleManager.getInstance() + .find(LocalH2Module.NAME).provider().getService(InsertDAO.class); + protocolGatewayMqtts.forEach(mqtt -> { + localH2InsertDAO.insert("insert into protocol_gateway_mqtt(topic,protocol_component_id,protocol_gateway_id) values('" + mqtt.getTopic() + "'," + mqtt.getProtocolComponentId() + "," + mqtt.getProtocolGatewayId() + ")"); + }); + } + + + @Getter + @Setter + static class ProtocolService { + + private String routeId; + + private ProtocolEnum protocol; + + private ProtocolAction action; + + private Map options; + } +} diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/ProtocolServiceController.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/ProtocolServiceController.java new file mode 100644 index 00000000..7aa55d3f --- /dev/null +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/ProtocolServiceController.java @@ -0,0 +1,75 @@ +package com.zmops.zeus.iot.web.controller; + +import com.zmops.zeus.iot.server.h2.module.LocalH2Module; +import com.zmops.zeus.iot.server.h2.service.InsertDAO; +import com.zmops.zeus.server.library.module.ModuleManager; +import com.zmops.zeus.server.library.web.core.Controller; +import com.zmops.zeus.server.library.web.core.Path; +import org.apache.commons.lang3.StringUtils; + +/** + * @author yefei + **/ +@Path(value = "/protocol/service") +public class ProtocolServiceController extends Controller { + + public void saveProtocolService() { + String id = getPara("protocolServiceId"); + String name = getPara("name"); + String remark = getPara("remark"); + String url = getPara("url"); + String ip = getPara("ip"); + String port = getPara("port"); + String msgLength = getPara("msgLength"); + String clientId = getPara("clientId"); + String protocol = getPara("protocol"); + InsertDAO localH2InsertDAO = ModuleManager.getInstance() + .find(LocalH2Module.NAME).provider().getService(InsertDAO.class); + String sql = "insert into protocol_service(id,name,url,ip,port,msg_length,client_id,protocol,remark) " + + " values(" + id + ",'" + name + "','" + url + "','" + ip + "','" + port + "','" + msgLength + "','" + clientId + "','" + protocol + "','" + remark + "')"; + localH2InsertDAO.insert(sql); + + renderNull(); + } + + public void updateProtocolService() { + String id = getPara("protocolServiceId"); + String name = getPara("name"); + String remark = getPara("remark"); + String url = getPara("url"); + String ip = getPara("ip"); + String port = getPara("port"); + String msgLength = getPara("msgLength"); + String clientId = getPara("clientId"); + String protocol = getPara("protocol"); + + InsertDAO localH2InsertDAO = ModuleManager.getInstance() + .find(LocalH2Module.NAME).provider().getService(InsertDAO.class); + + StringBuilder sql = new StringBuilder("update protocol_service set ip=?,port=?"); + if(StringUtils.isNotBlank(name)){ + sql.append(" ,name =?"); + } + if(StringUtils.isNotBlank(remark)){ + sql.append(" ,remark =?"); + } + if(StringUtils.isNotBlank(url)){ + sql.append(" ,url =?"); + } + if(StringUtils.isNotBlank(msgLength)){ + sql.append(" ,msg_length =?"); + } + if(StringUtils.isNotBlank(clientId)){ + sql.append(" ,client_id =?"); + } + if(StringUtils.isNotBlank(protocol)){ + sql.append(" ,protocol =?"); + } + + sql.append(" where id=?"); + localH2InsertDAO.update(sql.toString(), ip, port, name, remark, url, msgLength, clientId, protocol, id); + + renderNull(); + } + +} diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/WebConsole.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/WebConsole.java new file mode 100644 index 00000000..a712ec14 --- /dev/null +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/controller/WebConsole.java @@ -0,0 +1,22 @@ +package com.zmops.zeus.iot.web.controller; + +import com.zmops.zeus.server.library.web.core.ActionKey; +import com.zmops.zeus.server.library.web.core.Controller; +import com.zmops.zeus.server.library.web.core.Path; + +/** + * @author nantian created at 2021/12/1 22:10 + */ +@Path("/") +public class WebConsole extends Controller { + + public void index() { + redirect("/zeus/index.html"); + } + + + @ActionKey("/zeus") + public void zeus() { + redirect("/zeus/index.html"); + } +} diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/domain/ProtocolComponent.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/domain/ProtocolComponent.java new file mode 100644 index 00000000..a066fdab --- /dev/null +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/domain/ProtocolComponent.java @@ -0,0 +1,24 @@ +package com.zmops.zeus.iot.web.domain; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +public class ProtocolComponent { + + private Long id; + + private String name; + + private String uniqueId; + + private String status; + + private String remark; + + private String fileName; +} diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/domain/ProtocolGateway.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/domain/ProtocolGateway.java new file mode 100644 index 00000000..629d8840 --- /dev/null +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/domain/ProtocolGateway.java @@ -0,0 +1,19 @@ +package com.zmops.zeus.iot.web.domain; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @author yefei + **/ +@Data +public class ProtocolGateway { + + private Long id; + + private String name; + private Long protocolServiceId; + private Long protocolComponentId; + private String status; + private String remark; +} diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/domain/ProtocolGatewayMqtt.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/domain/ProtocolGatewayMqtt.java new file mode 100644 index 00000000..d86b2a9b --- /dev/null +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/domain/ProtocolGatewayMqtt.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.web.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author yefei + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProtocolGatewayMqtt { + + private Long protocolGatewayId; + + private Long protocolComponentId; + + private String topic; + +} diff --git a/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/domain/ProtocolService.java b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/domain/ProtocolService.java new file mode 100644 index 00000000..f1d7b9d7 --- /dev/null +++ b/iot-server/server-web/src/main/java/com/zmops/zeus/iot/web/domain/ProtocolService.java @@ -0,0 +1,23 @@ +package com.zmops.zeus.iot.web.domain; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class ProtocolService { + + private Long id; + + private String name; + + private String protocolType; + private String remark; + + private String url; + private String ip; + private Integer port; + private Integer msgLength; + private String clientId; +} diff --git a/pom.xml b/pom.xml index 0c3a736a..a735fb45 100644 --- a/pom.xml +++ b/pom.xml @@ -8,23 +8,7 @@ zeus-iot pom 1.0-beta - - - org.springframework.boot - spring-boot-starter-parent - 2.3.12.RELEASE - - - - zeus-webapp - zeus-common - zeus-driver - zeus-rest - zeus-starter - zeus-core - zeus-alarm - zeus-application-toolkit - + Zeus IoT 物联网分布式采集平台 UTF-8 @@ -32,114 +16,216 @@ 8 8 latest + 1.8 + 1.6.2 + 2.3.12.RELEASE + + + 0.4.13 + 0.6.1 + 1.6.0 + 1.8 + 2.10 + 2.8.2 + 3.1.0 + 2.22.0 + 3.2.0 + 2.22.0 + 3.1.0 + 3.1.1 + 3.0.0-M2 + 3.8.0 + 3.1.0 + 3.0.1 + 2.5 + 4.3.0 + 3.1.0 + 1.21 + 1.5 + 2.7 + true - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-tomcat - - - org.springframework.boot - spring-boot-starter-logging - - - + + + server + + true + + + iot-server + iot-server-bom + + + + + webapp + + true + + + zeus-webapp-bom + + - - - org.springframework.boot - spring-boot-starter-log4j2 - + + dist + + true + + + zeus-iot-dist + + - - - org.springframework.boot - spring-boot-starter-undertow - - - org.springframework - spring-jdbc - - - com.alibaba - druid-spring-boot-starter - 1.2.6 - - - org.springframework.boot - spring-boot-configuration-processor - - - org.springframework.boot - spring-boot-starter-actuator - - - org.springframework.boot - spring-boot-starter-validation - + + all + + false + + + iot-server + iot-server-bom + zeus-webapp-bom + zeus-iot-dist + + + + + org.codehaus.mojo + exec-maven-plugin + ${exec-maven-plugin.version} + + + git submodule update + initialize + false + + git + + submodule + update + --init + --recursive + + + + exec + + + + + + + + - - org.freemarker - freemarker - - - com.alibaba - fastjson - 1.2.56 - - - org.aspectj - aspectjweaver - - - org.postgresql - postgresql - - - org.projectlombok - lombok - true - - - one.util - streamex - 0.7.3 - - - com.github.penggle - kaptcha - 2.3.2 - + + + + + maven-antrun-plugin + ${maven-antrun-plugin.version} + + + maven-deploy-plugin + ${maven-deploy-plugin.version} + + + maven-assembly-plugin + ${maven-assembly-plugin.version} + - - commons-lang - commons-lang - 2.6 - + + maven-jar-plugin + ${maven-jar-plugin.version} + + true + + + + maven-shade-plugin + ${maven-shade-plugin.version} + + + - - com.dtflys.forest - forest-spring-boot-starter - 1.5.1 - - - commons-logging - commons-logging - - - - - io.ebean - ebean - 12.9.3 - - + + + kr.motd.maven + os-maven-plugin + ${os-maven-plugin.version} + + + initialize + + detect + + + + + + maven-enforcer-plugin + ${maven-enforcer-plugin.version} + + + enforce-java + + enforce + + validate + + + + 1.8 + + + 3.5 + + + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + maven-resources-plugin + ${maven-resource-plugin.version} + + ${project.build.sourceEncoding} + + + + com.spotify + docker-maven-plugin + ${docker.plugin.version} + + true + + + + maven-source-plugin + ${maven-source-plugin.version} + + + attach-sources + none + + jar + + + + + + \ No newline at end of file diff --git "a/sql/v1.0/structure/2021-12-16 1653-\344\277\256\346\224\271\345\234\272\346\231\257\347\224\237\346\225\210\346\227\266\351\227\264\346\256\265\350\241\250\347\273\223\346\236\204-yefei.sql" "b/sql/v1.0/structure/2021-12-16 1653-\344\277\256\346\224\271\345\234\272\346\231\257\347\224\237\346\225\210\346\227\266\351\227\264\346\256\265\350\241\250\347\273\223\346\236\204-yefei.sql" new file mode 100644 index 00000000..ff661781 --- /dev/null +++ "b/sql/v1.0/structure/2021-12-16 1653-\344\277\256\346\224\271\345\234\272\346\231\257\347\224\237\346\225\210\346\227\266\351\227\264\346\256\265\350\241\250\347\273\223\346\236\204-yefei.sql" @@ -0,0 +1,3 @@ +ALTER table product_event_time_interval ADD COLUMN day_of_weeks varchar(16) DEFAULT null; +ALTER table product_event_time_interval ALTER COLUMN start_time type int4; +ALTER table product_event_time_interval ALTER COLUMN end_time type int4; \ No newline at end of file diff --git "a/sql/v1.0/structure/2022-01-07 1653-\346\226\260\345\242\236token session\350\241\250-yefei.sql" "b/sql/v1.0/structure/2022-01-07 1653-\346\226\260\345\242\236token session\350\241\250-yefei.sql" new file mode 100644 index 00000000..ff661781 --- /dev/null +++ "b/sql/v1.0/structure/2022-01-07 1653-\346\226\260\345\242\236token session\350\241\250-yefei.sql" @@ -0,0 +1,3 @@ +ALTER table product_event_time_interval ADD COLUMN day_of_weeks varchar(16) DEFAULT null; +ALTER table product_event_time_interval ALTER COLUMN start_time type int4; +ALTER table product_event_time_interval ALTER COLUMN end_time type int4; \ No newline at end of file diff --git "a/sql/v1.0/structure/2022-03-04 1653-\344\277\256\346\224\271\345\234\272\346\231\257\347\224\237\346\225\210\346\227\266\351\227\264\346\256\265\350\241\250\347\273\223\346\236\204-yefei.sql" "b/sql/v1.0/structure/2022-03-04 1653-\344\277\256\346\224\271\345\234\272\346\231\257\347\224\237\346\225\210\346\227\266\351\227\264\346\256\265\350\241\250\347\273\223\346\236\204-yefei.sql" new file mode 100644 index 00000000..50d9b678 --- /dev/null +++ "b/sql/v1.0/structure/2022-03-04 1653-\344\277\256\346\224\271\345\234\272\346\231\257\347\224\237\346\225\210\346\227\266\351\227\264\346\256\265\350\241\250\347\273\223\346\236\204-yefei.sql" @@ -0,0 +1,2 @@ +ALTER table product_event_time_interval ALTER COLUMN start_time type varchar(32) ; +ALTER table product_event_time_interval ALTER COLUMN end_time type varchar(32) ; \ No newline at end of file diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettingService.java b/zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettingService.java deleted file mode 100644 index 800fe07c..00000000 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettingService.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.zmops.iot.mediaType.dingtalk; - -import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.domain.alarm.MediaTypeSetting; -import com.zmops.iot.domain.alarm.query.QMediaTypeSetting; -import org.springframework.stereotype.Service; - -import java.util.Arrays; -import java.util.Optional; - -/** - * @author yefei - **/ -@Service -public class DingtalkSettingService { - - private volatile DingtalkSettings instance; - - public DingtalkSettings get() { - return getOne(); - } - - private DingtalkSettings getOne() { - if (instance != null) { - return instance; - } - MediaTypeSetting setting = new QMediaTypeSetting().type.eq("dingtalk").findOne(); - - return instance = buildDingdingSetting(setting); - } - - private DingtalkSettings buildDingdingSetting(MediaTypeSetting setting) { - JSONObject jsonObject = JSONObject.parseObject(setting.getWebhooks()); - String secret = Optional.ofNullable(jsonObject.getString("secret")).orElse(""); - String url = Optional.ofNullable(jsonObject.getString("url")).orElse(""); - return DingtalkSettings.builder().textTemplate(setting.getTemplate()) - .webhooks(Arrays.asList(new DingtalkSettings.WebHookUrl(secret, url))).build(); - } - - - public void test() { - - } -} diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java b/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java deleted file mode 100644 index 05979b85..00000000 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettingService.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.zmops.iot.mediaType.feishu; - -import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.domain.alarm.MediaTypeSetting; -import com.zmops.iot.domain.alarm.query.QMediaTypeSetting; -import com.zmops.iot.mediaType.dingtalk.DingtalkSettings; -import org.springframework.stereotype.Service; - -import java.util.Arrays; -import java.util.Optional; - -/** - * @author yefei - **/ -@Service -public class FeishuSettingService { - - private volatile FeishuSettings instance; - - public FeishuSettings get() { - return getOne(); - } - - private FeishuSettings getOne() { - if (instance != null) { - return instance; - } - MediaTypeSetting setting = new QMediaTypeSetting().type.eq("feishu").findOne(); - - return instance = buildFeishuSetting(setting); - } - - private FeishuSettings buildFeishuSetting(MediaTypeSetting setting) { - JSONObject jsonObject = JSONObject.parseObject(setting.getWebhooks()); - String secret = Optional.ofNullable(jsonObject.getString("secret")).orElse(""); - String url = Optional.ofNullable(jsonObject.getString("url")).orElse(""); - return FeishuSettings.builder().textTemplate(setting.getTemplate()) - .webhooks(Arrays.asList(new FeishuSettings.WebHookUrl(secret, url))).build(); - } - - public void test() { - - } -} diff --git a/zeus-application-toolkit/pom.xml b/zeus-application-toolkit/pom.xml deleted file mode 100644 index 5773a0a6..00000000 --- a/zeus-application-toolkit/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - zeus-iot - com.zmops - 1.0-beta - - 4.0.0 - - zeus-application-toolkit - pom - - toolkit-async - toolkit-eventbus - - - - 8 - 8 - - - \ No newline at end of file diff --git a/zeus-application-toolkit/toolkit-async/pom.xml b/zeus-application-toolkit/toolkit-async/pom.xml deleted file mode 100644 index cbfd9db9..00000000 --- a/zeus-application-toolkit/toolkit-async/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - zeus-application-toolkit - com.zmops - 1.0-beta - - 4.0.0 - - toolkit-async - - - 8 - 8 - - - \ No newline at end of file diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultCallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultCallback.java deleted file mode 100644 index 5a9e98e5..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultCallback.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.zmops.iot.async.callback; - - -import com.zmops.iot.async.worker.WorkResult; - -/** - * 默认回调类,如果不设置的话,会默认给这个回调 - * - * @author wuweifeng wrote on 2019-11-19. - */ -public class DefaultCallback implements ICallback { - private static final DefaultCallback instance = new DefaultCallback() { - @Override - public String toString() { - return "(DefaultCallback instance)"; - } - }; - - public static DefaultCallback getInstance() { - return instance; - } - - @Override - public void begin() { - // do nothing - } - - /** - * 默认情况啥回调都没有,而且将吞掉所有异常显示(只保存在{@link WorkResult}中) - */ - @Override - public void result(boolean success, T param, WorkResult workResult) { - // do nothing - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java deleted file mode 100644 index 349569ce..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/DefaultGroupCallback.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.zmops.iot.async.callback; - - -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.List; - -/** - * @author wuweifeng wrote on 2019-12-27 - * @version 1.0 - * @deprecated deprecate at version 1.5.1 , see {@link IGroupCallback} . - */ -@SuppressWarnings("DeprecatedIsStillUsed") -@Deprecated -public class DefaultGroupCallback implements IGroupCallback { - @Override - public void success(List workerWrappers) { - // do nothing - } - - @Override - public void failure(List workerWrappers, Exception e) { - // do nothing - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java deleted file mode 100644 index 03cccd68..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ICallback.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.zmops.iot.async.callback; - - -import com.zmops.iot.async.exception.EndsNormallyException; -import com.zmops.iot.async.worker.WorkResult; - -/** - * 每个执行单元执行完毕后,会回调该接口

- * 需要监听执行结果的,实现该接口即可 - * - * @author wuweifeng wrote on 2019-11-19. - */ -@FunctionalInterface -public interface ICallback { - /** - * 任务开始的监听 - */ - default void begin() { - - } - - /** - * 耗时操作执行完毕后,就给value注入值 - *

- * 只要Wrapper被调用后成功或失败/超时,该方法都会被执行。 - */ - void result(boolean success, T param, WorkResult workResult); - - /** - * 提供常量选项: - *

- * 如果发生了异常,则打印异常信息。 - * 正常结束(例如取消、跳过)的异常{@link com.zmops.iot.async.exception.EndsNormallyException}不会打印。 - */ - ICallback PRINT_EXCEPTION_STACK_TRACE = new ICallback() { - @Override - public void result(boolean success, Object param, WorkResult workResult) { - Exception ex = workResult.getEx(); - if (ex != null && !(ex instanceof EndsNormallyException)) { - ex.printStackTrace(); - } - } - - @Override - public String toString() { - return "PRINT_EXCEPTION_STACK_TRACE"; - } - }; -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java deleted file mode 100644 index c11787c7..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IGroupCallback.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.zmops.iot.async.callback; - -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.worker.OnceWork; -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.Collection; -import java.util.List; -import java.util.concurrent.ExecutorService; - -/** - * 如果是异步执行整组的话,可以用这个组回调。已经废弃 - * - * @author wuweifeng wrote on 2019-11-19. - * @deprecated deprecate at version 1.5.1 - *

- * please use {@link Async#work(long, ExecutorService, Collection, String)}. - *

- * 该方法返回的{@link OnceWork}句柄,默认不会同步等待结束, - * 这便替代了原先的 - * {@link Async#beginWorkAsync(long, ExecutorService, IGroupCallback, WorkerWrapper[])} - *

- * 需要同步等待的话调用{@link OnceWork#awaitFinish()}即可。 - *

- */ -@SuppressWarnings("DeprecatedIsStillUsed") -@Deprecated -public interface IGroupCallback { - /** - * 成功后,可以从wrapper里去getWorkResult - */ - void success(List workerWrappers); - - /** - * 失败了,也可以从wrapper里去getWorkResult - */ - void failure(List workerWrappers, Exception e); -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java deleted file mode 100644 index 8c074a3b..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/ITimeoutWorker.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.zmops.iot.async.callback; - -/** - * @author wuweifeng wrote on 2019-12-20 - * @author tcsnzh - * 远古时期的代码,估计也没人会使用。但我也不确定,因此标注废弃。 - *

- * 难受的一比,为了屎山的兼容性要在代码里保留这么多屎盆。 - * @version 1.0 - * @deprecated deprecated by version 1.5.1--SNAPSHOT - */ -@Deprecated -public interface ITimeoutWorker extends IWorker { - /** - * 每个worker都可以设置超时时间 - * - * @return 毫秒超时时间 - */ - long timeOut(); - - /** - * 是否开启单个执行单元的超时功能(有时是一个group设置个超时,而不具备关心单个worker的超时) - *

注意,如果开启了单个执行单元的超时检测,将使线程池数量多出一倍

- * - * @return 是否开启 - */ - boolean enableTimeOut(); -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IWorker.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IWorker.java deleted file mode 100644 index 00b4d2a6..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/callback/IWorker.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.zmops.iot.async.callback; - - -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.Map; - -/** - * 每个最小执行单元需要实现该接口 - * - * @author wuweifeng wrote on 2019-11-19. - */ -@FunctionalInterface -public interface IWorker { - /** - * 在这里做耗时操作,如rpc请求、IO等 - * - * @param object object - * @param allWrappers 任务包装 - */ - V action(T object, Map> allWrappers); - - /** - * 超时、异常、跳过时,返回的默认值 - * - * @return 默认值 - */ - default V defaultValue() { - return null; - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/CancelException.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/CancelException.java deleted file mode 100644 index 6e5b4617..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/CancelException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.zmops.iot.async.exception; - -/** - * 整组取消,设置该异常。 - * - * @author tcsnzh[zh.jobs@foxmail.com] create this in 2021/5/25-下午6:12 - */ -public class CancelException extends EndsNormallyException { - public CancelException() { - } - - public CancelException(String message) { - super(message); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/EndsNormallyException.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/EndsNormallyException.java deleted file mode 100644 index 336b495c..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/EndsNormallyException.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.zmops.iot.async.exception; - -/** - * 该异常表示此任务单元是正常结束的。 - * - * @author tcsnzh[zh.jobs@foxmail.com] create this in 2021/6/5-下午11:57 - */ -public abstract class EndsNormallyException extends RuntimeException { - public EndsNormallyException() { - } - - public EndsNormallyException(String message) { - super(message); - } - - public EndsNormallyException(String message, Throwable cause) { - super(message, cause); - } - - public EndsNormallyException(Throwable cause) { - super(cause); - } - - public EndsNormallyException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/SkippedException.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/SkippedException.java deleted file mode 100644 index 03520d72..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/exception/SkippedException.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.zmops.iot.async.exception; - -/** - * 如果任务在执行之前,自己后面的任务已经执行完或正在被执行,则抛该exception - * - * @author wuweifeng wrote on 2020-02-18 - * @version 1.0 - */ -public class SkippedException extends EndsNormallyException { - public SkippedException() { - this(null); - } - - public SkippedException(String message) { - super(message); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java deleted file mode 100644 index e8cb8a23..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/Async.java +++ /dev/null @@ -1,323 +0,0 @@ -package com.zmops.iot.async.executor; - - -import com.zmops.iot.async.callback.DefaultGroupCallback; -import com.zmops.iot.async.callback.IGroupCallback; -import com.zmops.iot.async.executor.timer.SystemClock; -import com.zmops.iot.async.worker.OnceWork; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.async.wrapper.WorkerWrapperGroup; - -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; - -/** - * 核心工具类。 - * - * @author wuweifeng wrote on 2019-12-18 - * @version 1.0 - */ -public class Async { - - // ========================= 任务执行核心代码 ========================= - - /** - * {@link #work(long, ExecutorService, Collection, String)}方法的简易封装。 - * 使用uuid作为工作id。使用{@link #getCommonPool()}作为线程池。 - */ - public static OnceWork work(long timeout, - Collection> workerWrappers) { - return work(timeout, getCommonPool(), workerWrappers); - } - - /** - * {@link #work(long, ExecutorService, Collection, String)}方法的简易封装。 - * 可变参式传入。使用uuid作为工作id。使用{@link #getCommonPool()}作为线程池。 - */ - public static OnceWork work(long timeout, - WorkerWrapper... workerWrappers) { - return work(timeout, getCommonPool(), workerWrappers); - } - - /** - * {@link #work(long, ExecutorService, Collection, String)}方法的简易封装。 - * 可变参式传入。使用uuid作为工作id。 - */ - public static OnceWork work(long timeout, - ExecutorService executorService, - WorkerWrapper... workerWrappers) { - return work(timeout, executorService, Arrays.asList( - Objects.requireNonNull(workerWrappers, "workerWrappers array is null"))); - } - - /** - * {@link #work(long, ExecutorService, Collection, String)}方法的简易封装。 - * 省略工作id,使用uuid。 - */ - public static OnceWork work(long timeout, - ExecutorService executorService, - Collection> workerWrappers) { - return work(timeout, executorService, workerWrappers, UUID.randomUUID().toString()); - } - - /** - * 核心方法。该方法不是同步阻塞执行的。如果想要同步阻塞执行,则调用返回值的{@link OnceWork#awaitFinish()}即可。 - * - * @param timeout 全组超时时间 - * @param executorService 执行线程池 - * @param workerWrappers 任务容器集合 - * @param workId 本次工作id - * @return 返回 {@link OnceWork}任务句柄对象。 - */ - public static OnceWork work(long timeout, - ExecutorService executorService, - Collection> workerWrappers, - String workId) { - if (workerWrappers == null || workerWrappers.isEmpty()) { - return OnceWork.emptyWork(workId); - } - //保存上次执行的线程池变量(为了兼容以前的旧功能) - Async.lastExecutorService.set(Objects.requireNonNull(executorService, "ExecutorService is null ! ")); - final WorkerWrapperGroup group = new WorkerWrapperGroup(SystemClock.now(), timeout); - final OnceWork.Impl onceWork = new OnceWork.Impl(group, workId); - group.addWrapper(workerWrappers); - workerWrappers.forEach(wrapper -> { - if (wrapper == null) { - return; - } - executorService.submit(() -> wrapper.work(executorService, timeout, group)); - }); - return onceWork; - } - - // ========================= 设置/属性选项 ========================= - - /** - * 默认线程池。 - *

- * 在v1.4及之前,该COMMON_POLL是被写死的。 - *

- * 自v1.5后: - * 该线程池将会在第一次调用{@link #getCommonPool()}时懒加载。 - * tip: - * 要注意,{@link #work(long, WorkerWrapper[])}、{@link #work(long, Collection)}这些方法, - * 不传入线程池就会默认调用{@link #getCommonPool()},就会初始化线程池。 - *

- * 该线程池将会给线程取名为asyncTool-commonPool-thread-0(数字不重复)。 - *

- */ - private static volatile ThreadPoolExecutor COMMON_POOL; - - /** - * 在以前(及现在)的版本中: - * 当执行{@link #beginWork(long, ExecutorService, Collection)}方法时,ExecutorService将会被记录下来。 - *

- * 注意,这里是个static,也就是只能有一个线程池。用户自定义线程池时,也只能定义一个 - * - * @deprecated 不明意义、毫无用处的字段。记录之前使用的线程池没啥意义。 - */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - private static final AtomicReference lastExecutorService = new AtomicReference<>(null); - - /** - * 该方法将会返回{@link #COMMON_POOL},如果还未初始化则会懒加载初始化后再返回。 - * 详情参考{@link #COMMON_POOL}上的注解 - */ - public static ThreadPoolExecutor getCommonPool() { - if (COMMON_POOL == null) { - synchronized (Async.class) { - if (COMMON_POOL == null) { - COMMON_POOL = new ThreadPoolExecutor( - Runtime.getRuntime().availableProcessors() * 2, - 1024, - 15L, - TimeUnit.SECONDS, - new LinkedBlockingQueue<>(), - new ThreadFactory() { - private final AtomicLong threadCount = new AtomicLong(0); - - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(r, - "asyncTool-commonPool-thread-" + threadCount.getAndIncrement()); - t.setDaemon(true); - return t; - } - - @Override - public String toString() { - return "asyncTool-commonPool-threadFactory"; - } - } - ) { - @Override - public String toString() { - return "asyncTool-commonPool"; - } - }; - } - } - } - return COMMON_POOL; - } - - /** - * @deprecated 不明意义的输出信息的方法 - */ - @Deprecated - public static String getThreadCount() { - return "activeCount=" + COMMON_POOL.getActiveCount() + - ",completedCount=" + COMMON_POOL.getCompletedTaskCount() + - ",largestCount=" + COMMON_POOL.getLargestPoolSize(); - } - - /** - * @param now 是否立即关闭 - * @return 如果尚未调用过{@link #getCommonPool()},即没有初始化默认线程池,返回false。否则返回true。 - */ - @SuppressWarnings("unused") - public static synchronized boolean shutDownCommonPool(boolean now) { - if (COMMON_POOL == null) { - return false; - } - if (!COMMON_POOL.isShutdown()) { - if (now) { - COMMON_POOL.shutdownNow(); - } else { - COMMON_POOL.shutdown(); - } - } - return true; - } - - // ========================= deprecated ========================= - - /** - * 同步执行一次任务。 - * - * @return 只要执行未超时,就返回true。 - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 - */ - @Deprecated - public static boolean beginWork(long timeout, - ExecutorService executorService, - Collection> workerWrappers) - throws InterruptedException { - final OnceWork work = work(timeout, executorService, workerWrappers); - work.awaitFinish(); - return work.hasTimeout(); - } - - /** - * 同步执行一次任务。 - * 如果想自定义线程池,请传pool。不自定义的话,就走默认的COMMON_POOL - * - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 - */ - @Deprecated - public static boolean beginWork(long timeout, ExecutorService executorService, WorkerWrapper... workerWrapper) - throws ExecutionException, InterruptedException { - if (workerWrapper == null || workerWrapper.length == 0) { - return false; - } - Set workerWrappers = Arrays.stream(workerWrapper).collect(Collectors.toSet()); - //noinspection unchecked - return beginWork(timeout, executorService, workerWrappers); - } - - /** - * 同步阻塞,直到所有都完成,或失败 - * - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 - */ - @Deprecated - public static boolean beginWork(long timeout, WorkerWrapper... workerWrapper) throws ExecutionException, InterruptedException { - return beginWork(timeout, getCommonPool(), workerWrapper); - } - - /** - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 - */ - @Deprecated - public static void beginWorkAsync(long timeout, IGroupCallback groupCallback, WorkerWrapper... workerWrapper) { - beginWorkAsync(timeout, getCommonPool(), groupCallback, workerWrapper); - } - - /** - * 异步执行,直到所有都完成,或失败后,发起回调 - * - * @deprecated 已经被 {@link #work(long, ExecutorService, Collection, String)}方法取代。 - */ - @Deprecated - public static void beginWorkAsync(long timeout, ExecutorService executorService, IGroupCallback groupCallback, WorkerWrapper... workerWrapper) { - if (groupCallback == null) { - groupCallback = new DefaultGroupCallback(); - } - IGroupCallback finalGroupCallback = groupCallback; - if (executorService != null) { - executorService.submit(() -> { - try { - boolean success = beginWork(timeout, executorService, workerWrapper); - if (success) { - finalGroupCallback.success(Arrays.asList(workerWrapper)); - } else { - finalGroupCallback.failure(Arrays.asList(workerWrapper), new TimeoutException()); - } - } catch (ExecutionException | InterruptedException e) { - e.printStackTrace(); - finalGroupCallback.failure(Arrays.asList(workerWrapper), e); - } - }); - } else { - final ExecutorService commonPool = getCommonPool(); - commonPool.submit(() -> { - try { - boolean success = beginWork(timeout, commonPool, workerWrapper); - if (success) { - finalGroupCallback.success(Arrays.asList(workerWrapper)); - } else { - finalGroupCallback.failure(Arrays.asList(workerWrapper), new TimeoutException()); - } - } catch (ExecutionException | InterruptedException e) { - e.printStackTrace(); - finalGroupCallback.failure(Arrays.asList(workerWrapper), e); - } - }); - } - - } - - /** - * 关闭上次使用的线程池 - * - * @deprecated 因此在v1.5时加上了废弃注解。 - *

- * 这是一个很迷的方法,多线程时调用该方法的{@link #lastExecutorService}可能会被别的线程修改而引发不必要、不可控的错误。仅建议用来测试。 - * 另外,该方法现在不会关闭默认线程池。 - *

- */ - @Deprecated - public static void shutDown() { - final ExecutorService last = lastExecutorService.get(); - if (last != COMMON_POOL) { - shutDown(last); - } - } - - /** - * 关闭指定的线程池 - * - * @param executorService 指定的线程池。传入null则会关闭默认线程池。 - * @deprecated 没啥用的方法,要关闭线程池还不如直接调用线程池的关闭方法,避免歧义。 - */ - @Deprecated - public static void shutDown(ExecutorService executorService) { - if (executorService != null) { - executorService.shutdown(); - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/PollingCenter.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/PollingCenter.java deleted file mode 100644 index ebb3710e..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/PollingCenter.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.zmops.iot.async.executor; - -import com.zmops.iot.async.util.timer.HashedWheelTimer; -import com.zmops.iot.async.util.timer.Timeout; -import com.zmops.iot.async.util.timer.Timer; -import com.zmops.iot.async.util.timer.TimerTask; -import com.zmops.iot.async.wrapper.WorkerWrapperGroup; - -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; - -/** - * 检查{@link WorkerWrapperGroup}是否调用完成的轮询中心。 - * 内部使用时间轮进行轮询。 - *

- * =========================================================================================== - *

- * 在v1.4及以前的版本,存在如下问题: - * > - * 在使用线程数量较少的线程池进行beginWork时,调用WorkerWrapper#beginNext方法时, - * 会因为本线程等待下游Wrapper执行完成而存在线程耗尽bug。线程池会死翘翘的僵住、动弹不得。 - * > - * 例如仅有2个线程的线程池,执行以下任务: - * {@code - *

- * 这是旧版本(v1.4及以前)中可能会引发线程耗尽bug的情况,在test/v15.wrappertest中示例testThreadPolling_V14Bug说明了这个bug - * 线程数:2 - * A(5ms)--B1(10ms) ---|--> C1(5ms) - * . \ | (B1、B2任一完成可执行C1、C2) - * . ---> B2(20ms) --|--> C2(5ms) - *

- * } - * 线程1执行了A,然后在{@link CompletableFuture#allOf(CompletableFuture[])}等待B1与B2执行完成。 - * 线程2执行了B1或B2中的一个,也在allOf方法等待C1、C2完成。 - * 结果没有线程执行C和B2了,导致超时而死,并且这个线程池线程有可能被耗尽。 - * > - * - * @author create by TcSnZh on 2021/5/9-下午9:22 - */ -public class PollingCenter { - - // ========== singleton instance ========== - - private static final PollingCenter instance = new PollingCenter(); - - public static PollingCenter getInstance() { - return instance; - } - - // ========== fields and methods ========== - - public void checkGroup(WorkerWrapperGroup.CheckFinishTask task) { - checkGroup(task, 0); - } - - public void checkGroup(WorkerWrapperGroup.CheckFinishTask task, long daley) { - timer.newTimeout(task, daley, TimeUnit.MILLISECONDS); - } - - private final Timer timer = new Timer() { - private final HashedWheelTimer hashedWheelTimer = new HashedWheelTimer( - r -> { - Thread thread = new Thread(r, "asyncTool-pollingThread"); - thread.setDaemon(true); - return thread; - }, - 1, - TimeUnit.MILLISECONDS, - 1024); - - @Override - public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) { - return hashedWheelTimer.newTimeout(task, delay, unit); - } - - @Override - public Set stop() { - return hashedWheelTimer.stop(); - } - - @Override - public String toString() { - return "PollingCenter.timer"; - } - }; -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/timer/SystemClock.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/timer/SystemClock.java deleted file mode 100644 index 36db5476..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/executor/timer/SystemClock.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.zmops.iot.async.executor.timer; - -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 用于解决高并发下System.currentTimeMillis卡顿 - * - * @author lry - */ -public class SystemClock { - - private final int period; - - private final AtomicLong now; - - private static class InstanceHolder { - private static final SystemClock INSTANCE = new SystemClock(1); - } - - private SystemClock(int period) { - this.period = period; - this.now = new AtomicLong(System.currentTimeMillis()); - scheduleClockUpdating(); - } - - private static SystemClock instance() { - return InstanceHolder.INSTANCE; - } - - private void scheduleClockUpdating() { - ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> { - Thread thread = new Thread(runnable, "System Clock"); - thread.setDaemon(true); - return thread; - }); - scheduler.scheduleAtFixedRate(() -> now.set(System.currentTimeMillis()), period, period, TimeUnit.MILLISECONDS); - } - - private long currentTimeMillis() { - return now.get(); - } - - /** - * 用来替换原来的System.currentTimeMillis() - */ - public static long now() { - return instance().currentTimeMillis(); - } -} \ No newline at end of file diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/BiInt.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/BiInt.java deleted file mode 100644 index a33ef921..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/BiInt.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.zmops.iot.async.util; - -import java.util.Comparator; - -/** - * 两个int值包装类。重写了{@link #hashCode()}与{@link #equals(Object)} - * - * @author create by TcSnZh on 2021/5/16-上午1:50 - */ -public final class BiInt { - // properties - - private final int m; - private final int n; - - public static final Comparator cmp_m_asc = Comparator.comparingInt(BiInt::getM); - public static final Comparator cmp_n_asc = Comparator.comparingInt(BiInt::getN); - public static final Comparator cmp_m_desc = cmp_m_asc.reversed(); - public static final Comparator cmp_n_desc = cmp_n_asc.reversed(); - public static final Comparator cmp_m_asc_n_asc = - cmp_m_asc.thenComparing(cmp_n_asc); - public static final Comparator cmp_m_asc_n_desc = - cmp_m_asc.thenComparing(cmp_n_desc); - public static final Comparator cmp_m_desc_n_asc = - cmp_m_desc.thenComparing(cmp_n_asc); - public static final Comparator cmp_m_desc_n_desc = - cmp_m_desc.thenComparing(cmp_n_desc); - public static final Comparator cmp_n_asc_m_asc = - cmp_n_asc.thenComparing(cmp_m_asc); - public static final Comparator cmp_n_asc_m_desc = - cmp_n_asc.thenComparing(cmp_m_desc); - public static final Comparator cmp_n_desc_m_asc = - cmp_n_desc.thenComparing(cmp_m_asc); - public static final Comparator cmp_n_desc_m_desc = - cmp_n_desc.thenComparing(cmp_m_desc); - - /** - * private constructor , please use {@link #of(int, int)} to build Idx object. - */ - private BiInt(int m, int n) { - this.m = m; - this.n = n; - } - - // getter - - public int getM() { - return m; - } - - public int getN() { - return n; - } - - // hashcode and equals - - @Override - public int hashCode() { - return m ^ n; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (!(o instanceof BiInt)) - return false; - BiInt idx = (BiInt) o; - return m == idx.m && n == idx.n; - } - - // toString - - @Override - public String toString() { - return "(" + m + ',' + n + ')'; - } - - // ========== static ========== - - - // 工厂方法 - - public static BiInt of(int m, int n) { - if (m == Integer.MIN_VALUE && n == Integer.MAX_VALUE) { - return MIN_TO_MAX; - } - if (m >= 0 && m < CACHE_RANGE_M && n >= 0 && n < CACHE_RANGE_M) { - return cache[m * CACHE_RANGE_M + n]; - } - return new BiInt(m, n); - } - - // 缓存区间 - - private static final BiInt MIN_TO_MAX = new BiInt(Integer.MIN_VALUE, Integer.MAX_VALUE); - private static final BiInt[] cache; // m from 0 to 31 , n from 0 to 31 , total 1023 . - private static final int CACHE_RANGE_M = 32; // 0 to 31 - private static final int CACHE_RANGE_N = 32; // 0 to 31 - - static { - cache = new BiInt[CACHE_RANGE_M * CACHE_RANGE_N]; - for (int i = 0; i < CACHE_RANGE_M; i++) { - for (int j = 0; j < CACHE_RANGE_N; j++) { - cache[i * CACHE_RANGE_M + j] = new BiInt(i, j); - } - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractArray2D.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractArray2D.java deleted file mode 100644 index a6d30a2d..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractArray2D.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import com.zmops.iot.async.util.BiInt; - -import java.util.Iterator; - -/** - * @author create by TcSnZh on 2021/5/14-下午9:51 - */ -public abstract class AbstractArray2D implements Array2D { - /** - * 用于代替null - */ - protected static final Object NULL = new Object() { - @Override - public String toString() { - return "null"; - } - - @Override - public int hashCode() { - return 0; - } - - @SuppressWarnings("EqualsDoesntCheckParameterClass") - @Override - public boolean equals(Object obj) { - //noinspection ConstantConditions - return obj == null || obj == NULL || obj.equals(null); - } - }; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(64).append(this.getClass().getSimpleName()).append('{'); - Iterator> it = iterator(); - if (it.hasNext()) { - while (true) { - Point point = it.next(); - sb.append('{').append(point.getIdx()).append(':').append(point.getElement()).append('}'); - if (!it.hasNext()) { - break; - } - sb.append(", "); - } - } - return sb.append('}').toString(); - } - - public static class PointImpl implements Point { - private final BiInt idx; - private final E element; - - public PointImpl(BiInt idx, E element) { - this.idx = idx; - this.element = element; - } - - @Override - public BiInt getIdx() { - return idx; - } - - @Override - public E getElement() { - return element; - } - - @Override - public String toString() { - return "{" + idx + ":" + element + "}"; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractDirectedGraph.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractDirectedGraph.java deleted file mode 100644 index ae17f647..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractDirectedGraph.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.AbstractSet; -import java.util.Iterator; -import java.util.Objects; -import java.util.Set; - -/** - * 抽象有向图 - * - * @author create by TcSnZh on 2021/5/13-上午11:37 - */ -public abstract class AbstractDirectedGraph implements DirectedGraph { - - @Override - public String toString() { - Set nv = nodesView(); - Set> rSet = getRelations(); - StringBuilder sb = new StringBuilder(nv.size() * 10 + rSet.size() * 20) - .append(this.getClass().getSimpleName()).append("{nodes=["); - Iterator nit = nodesView().iterator(); - if (nit.hasNext()) { - for (; ; ) { - sb.append(nit.next()); - if (!nit.hasNext()) { - break; - } - sb.append(", "); - } - } - sb.append("], relations=["); - Iterator> eit = rSet.iterator(); - if (eit.hasNext()) { - for (; ; ) { - sb.append(eit.next()); - if (!eit.hasNext()) { - break; - } - sb.append(", "); - } - } - return sb.append("]}").toString(); - } - - public abstract class AbstractNodesView extends AbstractSet { - @Override - public boolean add(N n) { - return AbstractDirectedGraph.this.addNode(n); - } - - @Override - public boolean remove(Object o) { - N o1; - //noinspection unchecked - if (!AbstractDirectedGraph.this.containsNode(o1 = (N) o)) { - return false; - } - AbstractDirectedGraph.this.removeNode(o1); - return true; - } - } - - public static abstract class AbstractEntry implements Graph.Entry { - @Override - public int hashCode() { - return this.getFrom().hashCode() ^ this.getTo().hashCode() ^ this.getRelation().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof Graph.Entry)) { - return false; - } - Graph.Entry obj1 = (Graph.Entry) obj; - return Objects.equals(this.getFrom(), obj1.getFrom()) - && Objects.equals(this.getTo(), obj1.getTo()) - && Objects.equals(this.getRelation(), obj1.getRelation()); - } - - @Override - public String toString() { - return "{from=" + getFrom() + ", relation=" + getRelation() + ", to=" + getTo() + "]"; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractStoreArk.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractStoreArk.java deleted file mode 100644 index 24c4ac2a..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/AbstractStoreArk.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.zmops.iot.async.util.collection; - -/** - * @author create by TcSnZh on 2021/5/14-上午2:33 - */ -public abstract class AbstractStoreArk implements StoreArk { - - @Override - public boolean isEmpty() { - return size() <= 0; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(size() * 10).append(this.getClass().getSimpleName()).append("{"); - if (!isEmpty()) { - stream().forEach(entry -> sb.append(entry.getKey()).append(":").append(entry.getValue()).append(", ")); - sb.delete(sb.length() - 2, sb.length()); - } - return sb.append("}").toString(); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Array2D.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Array2D.java deleted file mode 100644 index 88434c79..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Array2D.java +++ /dev/null @@ -1,169 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import com.zmops.iot.async.util.BiInt; - -import java.util.*; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -/** - * 二维数组 - * - * @author create by TcSnZh on 2021/5/14-下午9:50 - */ -@SuppressWarnings("unused") -public interface Array2D extends Iterable> { - /** - * 有多少行 - */ - int lineLength(); - - /** - * 有多少列 - */ - int columnLength(); - - /** - * 添加元素到指定位置 - * - * @param line 行 - * @param column 列 - * @param element 元素 - * @return 如果之前添加过元素,将返回替换掉的之前的元素 - * @throws IndexOutOfBoundsException 行列超出范围 - */ - E add(int line, int column, E element); - - /** - * 如果不存在的话则添加元素 - *

- * {@link #add(int, int, Object)} - * - * @return 不存在且成功添加,返回true。 - */ - default boolean addIfAbsent(int line, int column, E element) { - if (get(line, column) != null) { - return false; - } - add(line, column, element); - return true; - } - - /** - * 删除元素 - * - * @param line 行 - * @param column 列 - * @return 返回移出的元素 - * @throws IndexOutOfBoundsException 行列超出返回 - * @throws IllegalArgumentException 如果原本不存在元素 - */ - E remove(int line, int column); - - /** - * 存在则移除,不存在则返回null - * - * @param line 行 - * @param column 列 - * @return 如果不存在,返回null。存在则返回被移出的元素。 - * @throws IndexOutOfBoundsException 行列超出范围 - */ - default E removeIfAbsent(int line, int column) { - if (get(line, column) == null) { - return null; - } - return remove(line, column); - } - - /** - * 获取元素 - * - * @param line 行 - * @param column 列 - * @return 如果存在,返回该元素。不存在则返回null。 - * @throws IndexOutOfBoundsException 行列超出范围 - */ - E get(int line, int column); - - /** - * 是否包含元素 - * - * @param element 元素 - * @return 有这个元素就返回true。 - */ - boolean containsElement(E element); - - /** - * 获取整行的元素 - * - * @param line 行号 - * @return 返回key为列号,value为元素的Map - * @throws IndexOutOfBoundsException 行号超出范围 - */ - Map fullLine(int line); - - /** - * 获取整列的元素 - * - * @param column 列号 - * @return 返回key为行号,value为元素的Map - * @throws IndexOutOfBoundsException 列号超出范围 - */ - Map fullColumn(int column); - - /** - * 迭代器 - * - * @param foreachOrder 遍历顺序 - * @return 如果本容器不允许null值存在,只需返回存在的元素的键即可。如果允许null值存在,仅需返回包括人工放入的null值的键即可。 - */ - Iterator> iterator(Comparator foreachOrder); - - @Override - default Iterator> iterator() { - //noinspection unchecked - return (Iterator) iterator(BiInt.cmp_m_asc_n_asc); - } - - /** - * 流 - */ - default Stream> stream() { - return StreamSupport.stream(spliterator(), false); - } - - default Stream> parallelStream() { - return StreamSupport.stream(spliterator(), true); - } - - default Spliterator> spliterator(Comparator foreachOrder) { - return Spliterators.spliteratorUnknownSize(iterator(foreachOrder), 0); - } - - default Stream> stream(Comparator foreachOrder) { - return StreamSupport.stream(spliterator(foreachOrder), false); - } - - default Stream> parallelStream(Comparator foreachOrder) { - return StreamSupport.stream(spliterator(foreachOrder), true); - } - - /** - * 端点 - * - * @param 元素泛型 - */ - interface Point { - BiInt getIdx(); - - default int getLine() { - return getIdx().getM(); - } - - default int getColumn() { - return getIdx().getN(); - } - - E getElement(); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CachedStoreArk.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CachedStoreArk.java deleted file mode 100644 index 90fbc18f..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CachedStoreArk.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.function.Supplier; - -/** - * 一个缓存元素位置的储存柜。 - * - * @author create by TcSnZh on 2021/5/14-上午2:37 - */ -public class CachedStoreArk extends AbstractStoreArk { - private final StoreArk inner; - - private final Map cacheMap = new HashMap<>(); - - public CachedStoreArk() { - this(CommonStoreArk::new); - } - - private CachedStoreArk(Supplier> sup) { - this.inner = sup.get(); - } - - @Override - public int store(E element) { - int id = inner.store(element); - cacheMap.put(element, id); - return id; - } - - @Override - public E peek(int id) { - return inner.peek(id); - } - - @Override - public E takeOut(int id) { - E e = inner.takeOut(id); - cacheMap.remove(e); - return e; - } - - @Override - public int size() { - return inner.size(); - } - - @Override - public Iterator> iterator() { - return inner.iterator(); - } - - @Override - public int findId(E element) { - Integer idNullable = cacheMap.get(element); - return idNullable == null ? -1 : idNullable; - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonDirectedGraph.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonDirectedGraph.java deleted file mode 100644 index 89050cff..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonDirectedGraph.java +++ /dev/null @@ -1,145 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * 线程不安全的有向图。 - *

- * 不允许放入null。 - * - * @author create by TcSnZh on 2021/5/14-上午2:22 - */ -public class CommonDirectedGraph extends AbstractDirectedGraph { - - // ========== properties ========== - - private final StoreArk nodes = new CachedStoreArk<>(); - private final Array2D arr = new SparseArray2D<>(); - - // ========== methods ========== - - @Override - public boolean addNode(N node) { - if (containsNode(Objects.requireNonNull(node))) { - return false; - } - nodes.store(node); - return true; - } - - @Override - public boolean containsNode(N node) { - return node != null && findNodeId(node, false) >= 0; - } - - @Override - public Set> removeNode(N node) { - int id = findNodeId(Objects.requireNonNull(node), true); - LinkedHashSet> res = new LinkedHashSet<>(); - // 查找node为from的键 - arr.fullLine(id).forEach((toNodeId, relation) -> { - res.add(new OuterEntry<>(node, nodes.peek(toNodeId), relation)); - arr.remove(id, toNodeId); - }); - // 查找node为to的键 - arr.fullColumn(id).forEach((fromNodeId, relation) -> { - // 在上一次遍历中,fromNodeId为id, - if (fromNodeId == id) { - return; - } - res.add(new OuterEntry<>(nodes.peek(fromNodeId), node, relation)); - arr.remove(fromNodeId, id); - }); - nodes.takeOut(id); - return res; - } - - @Override - public R putRelation(N fromNode, R relation, N toNode) { - return arr.add( - findNodeId(Objects.requireNonNull(fromNode), true), - findNodeId(Objects.requireNonNull(toNode), true), - Objects.requireNonNull(relation) - ); - } - - @Override - public Set> getRelationFrom(N from) { - int id = findNodeId(Objects.requireNonNull(from), true); - LinkedHashSet> res = new LinkedHashSet<>(); - // 查找node为from的键 - arr.fullLine(id).forEach((toNodeId, relation) -> res.add(new OuterEntry<>(from, nodes.peek(toNodeId), relation))); - return res; - } - - @Override - public Set> getRelationTo(N to) { - int id = findNodeId(Objects.requireNonNull(to), true); - LinkedHashSet> res = new LinkedHashSet<>(); - // 查找node为to的键 - arr.fullColumn(id).forEach((fromNodeId, relation) -> - res.add(new OuterEntry<>(nodes.peek(fromNodeId), to, relation))); - return res; - } - - @Override - public Set nodesView() { - return new AbstractNodesView() { - @Override - public Iterator iterator() { - return nodes.stream().map(Map.Entry::getValue).iterator(); - } - - @Override - public int size() { - return nodes.size(); - } - }; - } - - @Override - public Set> getRelations() { - return arr.stream().map((Function, Graph.Entry>) rPoint -> new OuterEntry<>( - nodes.peek(rPoint.getLine()), - nodes.peek(rPoint.getColumn()), - rPoint.getElement() - )).collect(Collectors.toSet()); - } - - private int findNodeId(N node, boolean mustExistElseThrowEx) { - int id = nodes.findId(Objects.requireNonNull(node)); - if (mustExistElseThrowEx && id < 0) { - throw new IllegalArgumentException("No node exists : " + node); - } - return id; - } - - private static class OuterEntry extends AbstractDirectedGraph.AbstractEntry { - private final N from; - private final N to; - private final R relation; - - public OuterEntry(N from, N to, R relation) { - this.from = from; - this.to = to; - this.relation = relation; - } - - @Override - public N getFrom() { - return from; - } - - @Override - public N getTo() { - return to; - } - - @Override - public R getRelation() { - return relation; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonStoreArk.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonStoreArk.java deleted file mode 100644 index fec1dbe6..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/CommonStoreArk.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.*; - -/** - * 自动扩容的id储物柜,线程不安全。 - * - * @author create by TcSnZh on 2021/5/13-下午1:24 - */ -public class CommonStoreArk extends AbstractStoreArk { - private Object[] elements; - - /** - * 已经分配的下标数 - */ - private int allocSize = 0; - - /** - * 保存着最小空元素的队列 - */ - private final Queue emptyPoints = new PriorityQueue<>(Integer::compareTo); - - public CommonStoreArk(int initialCapacity) { - elements = new Object[initialCapacity]; - } - - public CommonStoreArk() { - this(10); - } - - @Override - public int store(E element) { - int id; - elements[id = pollId()] = element; - return id; - } - - @Override - public E peek(int id) { - if (id < 0) { - throw new IllegalArgumentException("id " + id + " can't be negative"); - } - if (id >= elements.length) { - return null; - } - //noinspection unchecked - return (E) elements[id]; - } - - @Override - public E takeOut(int id) { - if (id < 0) { - throw new IllegalArgumentException("id " + id + " can't be negative"); - } - if (id >= elements.length) { - return null; - } - //noinspection unchecked - E out = (E) elements[id]; - elements[id] = null; - if (id == allocSize - 1) { - allocSize--; - } else { - emptyPoints.add(id); - } - return out; - } - - @Override - public int size() { - return allocSize - emptyPoints.size(); - } - - @Override - public Iterator> iterator() { - return new Iterator>() { - private final Map.Entry[] items; - - private int idx = 0; - - { - //noinspection unchecked - items = new Map.Entry[size()]; - int itemsIdx = 0; - Iterator emptyPointItr = emptyPoints.iterator(); - for (int i = 0; i < allocSize; i++) { - Object element = elements[i]; - if (element == null) { - continue; - } - final int _i = i; - //noinspection unchecked - items[itemsIdx++] = new Map.Entry() { - private final int k = _i; - private E v = (E) element; - - @Override - public Integer getKey() { - return k; - } - - @Override - public E getValue() { - return v; - } - - @Override - public E setValue(E value) { - E _v = this.v; - this.v = value; - return _v; - } - - @Override - public String toString() { - return "{" + k + ':' + v + '}'; - } - }; - } - } - - - @Override - public boolean hasNext() { - return idx < items.length; - } - - @Override - public Map.Entry next() { - return items[idx++]; - } - }; - } - - @Override - public int findId(E element) { - int i = 0; - for (Object o : elements) { - if (Objects.equals(o, element)) { - return i; - } - i++; - } - return -1; - } - - private int pollId() { - if (!emptyPoints.isEmpty()) { - return emptyPoints.poll(); - } - int id = allocSize++; - int length = elements.length; - if (id >= length) { - // 扩容 - elements = Arrays.copyOf(elements, Math.max(length + 1, length + (length >> 1))); - } - return id; - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/DirectedGraph.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/DirectedGraph.java deleted file mode 100644 index eb066627..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/DirectedGraph.java +++ /dev/null @@ -1,185 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.AbstractSet; -import java.util.Collections; -import java.util.Iterator; -import java.util.Set; - -/** - * @author create by TcSnZh on 2021/5/16-下午11:27 - */ -public interface DirectedGraph extends Graph { - @Override - default boolean isDirected() { - return true; - } - - static DirectedGraph readOnlyDigraph(DirectedGraph source) { - return new ReadOnlyDirectedGraph<>(source); - } - - static DirectedGraph synchronizedDigraph(DirectedGraph source) { - return synchronizedDigraph(source, new Object()); - } - - static DirectedGraph synchronizedDigraph(DirectedGraph source, Object mutex) { - return new SyncDirectedGraph<>(source, mutex); - } - - class ReadOnlyDirectedGraph extends AbstractDirectedGraph { - private final DirectedGraph source; - - public ReadOnlyDirectedGraph(DirectedGraph source) { - this.source = source; - } - - private static UnsupportedOperationException readOnlyGraph() { - return new UnsupportedOperationException("readOnly graph"); - } - - @Override - public boolean addNode(N node) { - throw readOnlyGraph(); - } - - @Override - public boolean containsNode(N node) { - return source.containsNode(node); - } - - @Override - public Set> removeNode(N node) { - throw readOnlyGraph(); - } - - @Override - public R putRelation(N fromNode, R relation, N toNode) { - throw readOnlyGraph(); - } - - @Override - public Set> getRelationFrom(N from) { - return source.getRelationFrom(from); - } - - @Override - public Set> getRelationTo(N to) { - return source.getRelationTo(to); - } - - @Override - public Set nodesView() { - return new AbstractSet() { - private final Set nodesViewSource = source.nodesView(); - - @Override - public Iterator iterator() { - return new Iterator() { - private final Iterator iteratorSource = nodesViewSource.iterator(); - - @Override - public boolean hasNext() { - return iteratorSource.hasNext(); - } - - @Override - public N next() { - return iteratorSource.next(); - } - - @Override - public void remove() { - throw readOnlyGraph(); - } - }; - } - - @Override - public int size() { - return nodesViewSource.size(); - } - - @Override - public boolean add(N n) { - throw readOnlyGraph(); - } - - @Override - public boolean remove(Object o) { - throw readOnlyGraph(); - } - }; - } - - @Override - public Set> getRelations() { - return source.getRelations(); - } - } - - class SyncDirectedGraph extends AbstractDirectedGraph { - private final DirectedGraph source; - private final Object mutex; - - public SyncDirectedGraph(DirectedGraph source, Object mutex) { - this.source = source; - this.mutex = mutex; - } - - @Override - public boolean addNode(N node) { - synchronized (mutex) { - return source.addNode(node); - } - } - - @Override - public boolean containsNode(N node) { - synchronized (mutex) { - return source.containsNode(node); - } - } - - @Override - public Set> removeNode(N node) { - synchronized (mutex) { - return source.removeNode(node); - } - } - - @Override - public R putRelation(N fromNode, R relation, N toNode) { - synchronized (mutex) { - return source.putRelation(fromNode, relation, toNode); - } - } - - @Override - public Set> getRelationFrom(N from) { - synchronized (mutex) { - return source.getRelationFrom(from); - } - } - - @Override - public Set> getRelationTo(N to) { - synchronized (mutex) { - return source.getRelationTo(to); - } - } - - @Override - public Set nodesView() { - synchronized (mutex) { - return Collections.synchronizedSet(source.nodesView()); - } - } - - @Override - public Set> getRelations() { - synchronized (mutex) { - return source.getRelations(); - } - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Graph.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Graph.java deleted file mode 100644 index 4bcb98c7..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/Graph.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.Set; - -/** - * 图数据结构 - * - * @author create by TcSnZh on 2021/5/13-上午11:37 - */ -@SuppressWarnings("unused") -public interface Graph { - /** - * 添加节点。 - * 如果节点已经存在,则不会添加。 - * - * @param node 添加进图的节点 - * @return 添加成功返回true,如果节点已经存在返回false。 - */ - boolean addNode(N node); - - /** - * 添加一堆Node,任一成功返回true - */ - default boolean addNode(N... nodes) { - boolean success = false; - for (N node : nodes) { - if (addNode(node)) { - success = true; - } - } - return success; - } - - /** - * 是否存在节点 - * - * @param node 节点。 - * @return 存在返回true,否则返回false。 - */ - boolean containsNode(N node); - - /** - * 移除节点。 - * 返回与该节点有关系的,被一并移出的键。 - * - * @param node 节点 - * @return 返回值不会为null。 - * @throws IllegalArgumentException 如果两个节点任一不存在本图中,抛出异常。 - */ - Set> removeNode(N node); - - /** - * 添加关系 - * 在无向图中fromNode与toNode参数的位置调换没有影响。 - * - * @param fromNode 从这个节点开始 - * @param relation 关系 - * @param toNode 以那个节点为目标 - * @return 如果之前存在关系,则会替换之前的关系,返回出被替换的之前存在的关系。如果之前没有关系,返回null。 - * @throws IllegalArgumentException 如果两个节点任一不存在本图中,抛出该异常。 - */ - R putRelation(N fromNode, R relation, N toNode); - - /** - * 获取“从这个节点开始”的所有关系 - * - * @param from 关系开始的节点 - * @return 返回 {@link Entry}键。 - */ - Set> getRelationFrom(N from); - - /** - * 获取“以这个节点为目标”的所有关系 - * - * @param to 被关系的节点 - * @return 返回 {@link Entry}键。 - */ - Set> getRelationTo(N to); - - /** - * 返回全部节点视图 - * - * @return 视图 - */ - Set nodesView(); - - /** - * 返回全部关系,返回的是新Set - * - * @return 与本类无关的Set - */ - Set> getRelations(); - - /** - * 是否有向 - */ - boolean isDirected(); - - interface Entry { - N getFrom(); - - N getTo(); - - R getRelation(); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/SparseArray2D.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/SparseArray2D.java deleted file mode 100644 index 42a1b0b4..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/SparseArray2D.java +++ /dev/null @@ -1,229 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import com.zmops.iot.async.util.BiInt; - -import java.util.*; -import java.util.stream.Collectors; - -/** - * 稀疏二维数组。 - *

- * 可以设置是否允许存入null。 - * - * @author create by TcSnZh on 2021/5/14-下午9:45 - */ -public class SparseArray2D extends AbstractArray2D { - - // ========== properties ========== - - /** - * 限制长宽,默认为Integer.MAX_VALUE。稀疏数组不在乎这些。 - */ - private final int maxLineLength; - private final int maxColumnLength; - private final boolean allowNull; - - private final Map items = new HashMap<>(); - - // ========== index cache properties ========== - - /** - * 缓存行列索引 - */ - private final NavigableMap> indexOfLine2columns = new TreeMap<>(Integer::compareTo); - private final NavigableMap> indexOfColumn2lines = new TreeMap<>(Integer::compareTo); - - // ========== constructor ========== - - public SparseArray2D() { - this(Integer.MAX_VALUE, Integer.MAX_VALUE); - } - - public SparseArray2D(boolean allowNull) { - this(Integer.MAX_VALUE, Integer.MAX_VALUE, allowNull); - } - - public SparseArray2D(int maxLineCapacity, int maxColumnCapacity) { - this(maxLineCapacity, maxColumnCapacity, false); - } - - public SparseArray2D(int maxLineCapacity, int maxColumnCapacity, boolean allowNull) { - this.maxLineLength = maxLineCapacity; - this.maxColumnLength = maxColumnCapacity; - this.allowNull = allowNull; - } - - // ========== public methods ========== - @Override - public int lineLength() { - return maxLineLength; - } - - @Override - public int columnLength() { - return maxColumnLength; - } - - @Override - public E add(int line, int column, E element) { - if (!allowNull && element == null) { - throw new NullPointerException("null is not allowed"); - } - Object put = items.put(BiInt.of(checkLine(line), checkColumn(column)), element == null ? NULL : element); - addIndex(line, column); - //noinspection unchecked - return NULL.equals(put) ? null : (E) put; - } - - @Override - public E remove(int line, int column) { - BiInt idx = BiInt.of(checkLine(line), checkColumn(column)); - Object get = items.get(idx); - if (get == null) { - throw new IllegalArgumentException("There is no element in line " + line + " column " + column); - } - items.remove(idx); - removeIndex(line, column); - //noinspection unchecked - return NULL.equals(get) ? null : (E) get; - } - - /** - * 该方法如果返回null,则分不清 之前存入了null 还是 没有存入过 - *

- * {@inheritDoc} - */ - @Override - public E get(int line, int column) { - Object get = items.get(BiInt.of(checkLine(line), checkColumn(column))); - //noinspection unchecked - return NULL.equals(get) ? null : (E) get; - } - - @Override - public boolean containsElement(E element) { - if (NULL.equals(element)) { - if (!allowNull) { - return false; - } - return items.values().stream().anyMatch(v -> NULL.equals(element)); - } - return items.values().stream().anyMatch(element::equals); - } - - @Override - public Map fullLine(int line) { - return Optional.ofNullable(indexOfLine2columns.get(line)) - .map(set -> set.stream() - .collect(Collectors.toMap(column -> column, column -> { - //noinspection unchecked - return (E) items.get(BiInt.of(line, column)); - }))) - .orElse(Collections.emptyMap()); - } - - @Override - public Map fullColumn(int column) { - return Optional.ofNullable(indexOfColumn2lines.get(column)) - .map(set -> set.stream() - .collect(Collectors.toMap(line -> line, line -> { - //noinspection unchecked - return (E) items.get(BiInt.of(line, column)); - }))) - .orElse(Collections.emptyMap()); - } - - @Override - public Iterator> iterator(Comparator foreachOrder) { - return new Iterator>() { - private final Iterator> it; - private Point last = null; - private boolean removed = false; - - { - it = items.entrySet().stream() - .sorted((o1, o2) -> foreachOrder.compare(o1.getKey(), o2.getKey())) - .iterator(); - } - - @Override - public boolean hasNext() { - return it.hasNext(); - } - - @Override - public Point next() { - Map.Entry next = it.next(); - removed = false; - Object v = next.getValue(); - //noinspection unchecked - return last = new PointImpl<>(next.getKey(), NULL.equals(v) ? null : (E) v); - } - - @Override - public void remove() { - if (last == null || removed) { - throw new IllegalStateException(last == null - ? "Iterator has not yet been called .next() ." - : "Iterator item already removed : " + last); - } - BiInt idx = last.getIdx(); - SparseArray2D.this.remove(idx.getM(), idx.getN()); - } - }; - } - - // ========== private methods ========== - - private int checkLine(int line) { - int len = lineLength(); - if (line < 0 || line >= len) { - throw new IndexOutOfBoundsException("Line " + line + " out of bound [0," + (len - 1) + "]"); - } - return line; - } - - private int checkColumn(int column) { - int len = columnLength(); - if (column < 0 || column >= len) { - throw new IndexOutOfBoundsException("Column " + column + " out of bound [0," + (len - 1) + "]"); - } - return column; - } - - private void addIndex(int line, int column) { - indexOfLine2columns.computeIfAbsent(line, line1 -> new TreeSet<>(Integer::compareTo)).add(column); - indexOfColumn2lines.computeIfAbsent(column, column1 -> new TreeSet<>(Integer::compareTo)).add(line); - - } - - private void removeIndex(int line, int column) { - // remove line index - { - NavigableSet columns = indexOfLine2columns.get(line); - if (columns == null || !columns.contains(column)) { - throw new ConcurrentModificationException( - "线程不安全导致索引异常 : lines " + columns + " is null or not contain line " + line); - - } - if (columns.size() == 1) { - indexOfLine2columns.remove(line); - } else { - columns.remove(column); - } - } - // remove column index - { - NavigableSet lines = indexOfColumn2lines.get(column); - if (lines == null || !lines.contains(line)) { - throw new ConcurrentModificationException( - "线程不安全导致索引异常 : lines " + lines + " is null or not contain column " + column); - } - if (lines.size() == 1) { - indexOfColumn2lines.remove(column); - } else { - lines.remove(column); - } - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/StoreArk.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/StoreArk.java deleted file mode 100644 index 423ac083..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/collection/StoreArk.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.zmops.iot.async.util.collection; - -import java.util.Map; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -/** - * id存储柜。 - * 每个元素的id是固定的(除非取出后重新加入),且id是大于等于0,且分配到的id必须是未分配的id中最小的。 - *

- * 类似于我们去游泳馆,里面的存放个人物品的柜子。 - * 放进去元素后,会分配一个id。然后凭借该id取出元素。 - * 不过不同于这些现实中的柜子的是,这个存储柜必定会提供最小的id,并且必定>0。 - *

- * - * @author create by TcSnZh on 2021/5/14-上午2:29 - */ -public interface StoreArk extends Iterable> { - /** - * 存入元素 - * - * @param element 元素。 - * @return 返回最小的id。从0开始。 - */ - int store(E element); - - /** - * 查看元素 - * - * @param id id; - * @return 返回存在的元素。如果本id未被占用 或 原先存入null,返回null。 - * @throws IllegalArgumentException id为负数时抛出该异常 - */ - E peek(int id); - - /** - * 取出元素 - * - * @param id id - * @return 返回被取出的元素。如果本id未被占用 或 原先存入null,返回null。 - * @throws IllegalArgumentException id为负数时抛出该异常 - */ - E takeOut(int id); - - /** - * 元素个数 - */ - int size(); - - /** - * 是否为空 - */ - boolean isEmpty(); - - /** - * 查找元素的id - * - * @param element 元素 - * @return 如果存在,返回id。不存在返回-1 - */ - int findId(E element); - - /** - * 返回流 - */ - default Stream> stream() { - return StreamSupport.stream(spliterator(), false); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/AbstractWheelTimer.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/AbstractWheelTimer.java deleted file mode 100644 index 3886e879..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/AbstractWheelTimer.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.zmops.iot.async.util.timer; - -/** - * @author create by TcSnZh on 2021/5/12-下午6:36 - */ -public abstract class AbstractWheelTimer implements Timer, AutoCloseable { - public static final int WORKER_STATE_INIT = 0; - public static final int WORKER_STATE_STARTED = 1; - public static final int WORKER_STATE_SHUTDOWN = 2; - - public abstract void start(); - - @SuppressWarnings("RedundantThrows") - @Override - public void close() throws Exception { - stop(); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/HashedWheelTimer.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/HashedWheelTimer.java deleted file mode 100644 index 9d5b2840..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/HashedWheelTimer.java +++ /dev/null @@ -1,665 +0,0 @@ -package com.zmops.iot.async.util.timer; - -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 从netty里抄来的,删去了一些功能。 - *

- * - * 如果违反开源协议,请联系作者: zh.jobs@foxmail.com - * If violate the open source agreement, please contact the author : zh0u.he@qq.com - * - * - * @author create by TcSnZh on 2021/5/12-下午7:16 - */ -public class HashedWheelTimer extends AbstractWheelTimer { - - private static final long MILLISECOND_NANOS = TimeUnit.MILLISECONDS.toNanos(1); - - private final Worker worker = new Worker(); - private final Thread workerThread; - @SuppressWarnings({"unused", "FieldMayBeFinal"}) - private final AtomicInteger workerState = new AtomicInteger(WORKER_STATE_INIT); // 0 - init, 1 - started, 2 - shut down - - private final long tickDuration; - private final HashedWheelBucket[] wheel; - private final int mask; - private final CountDownLatch startTimeInitialized = new CountDownLatch(1); - private final Queue timeouts = new ConcurrentLinkedDeque<>(); - private final Queue cancelledTimeouts = new ConcurrentLinkedDeque<>(); - private final AtomicLong pendingTimeouts = new AtomicLong(0); - private final long maxPendingTimeouts; - - private volatile long startTime; - - /** - * Creates a new timer with the default thread factory - * ({@link Executors#defaultThreadFactory()}), default tick duration, and - * default number of ticks per wheel. - */ - @SuppressWarnings("unused") - public HashedWheelTimer() { - this(Executors.defaultThreadFactory()); - } - - /** - * Creates a new timer with the default thread factory - * ({@link Executors#defaultThreadFactory()}) and default number of ticks - * per wheel. - * - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @throws NullPointerException if {@code unit} is {@code null} - * @throws IllegalArgumentException if {@code tickDuration} is <= 0 - */ - @SuppressWarnings("unused") - public HashedWheelTimer(long tickDuration, TimeUnit unit) { - this(Executors.defaultThreadFactory(), tickDuration, unit); - } - - /** - * Creates a new timer with the default thread factory - * ({@link Executors#defaultThreadFactory()}). - * - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @param ticksPerWheel the size of the wheel - * @throws NullPointerException if {@code unit} is {@code null} - * @throws IllegalArgumentException if either of {@code tickDuration} and {@code ticksPerWheel} is <= 0 - */ - @SuppressWarnings("unused") - public HashedWheelTimer(long tickDuration, TimeUnit unit, int ticksPerWheel) { - this(Executors.defaultThreadFactory(), tickDuration, unit, ticksPerWheel); - } - - /** - * Creates a new timer with the default tick duration and default number of - * ticks per wheel. - * - * @param threadFactory a {@link ThreadFactory} that creates a - * background {@link Thread} which is dedicated to - * {@link TimerTask} execution. - * @throws NullPointerException if {@code threadFactory} is {@code null} - */ - public HashedWheelTimer(ThreadFactory threadFactory) { - this(threadFactory, 100, TimeUnit.MILLISECONDS); - } - - /** - * Creates a new timer with the default number of ticks per wheel. - * - * @param threadFactory a {@link ThreadFactory} that creates a - * background {@link Thread} which is dedicated to - * {@link TimerTask} execution. - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @throws NullPointerException if either of {@code threadFactory} and {@code unit} is {@code null} - * @throws IllegalArgumentException if {@code tickDuration} is <= 0 - */ - public HashedWheelTimer( - ThreadFactory threadFactory, long tickDuration, TimeUnit unit) { - this(threadFactory, tickDuration, unit, 512); - } - - /** - * Creates a new timer. - * - * @param threadFactory a {@link ThreadFactory} that creates a - * background {@link Thread} which is dedicated to - * {@link TimerTask} execution. - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @param ticksPerWheel the size of the wheel - * @throws NullPointerException if either of {@code threadFactory} and {@code unit} is {@code null} - * @throws IllegalArgumentException if either of {@code tickDuration} and {@code ticksPerWheel} is <= 0 - */ - public HashedWheelTimer( - ThreadFactory threadFactory, - long tickDuration, TimeUnit unit, int ticksPerWheel) { - this(threadFactory, tickDuration, unit, ticksPerWheel, -1); - } - - /** - * Creates a new timer. - * - * @param threadFactory a {@link ThreadFactory} that creates a - * background {@link Thread} which is dedicated to - * {@link TimerTask} execution. - * @param tickDuration the duration between tick - * @param unit the time unit of the {@code tickDuration} - * @param ticksPerWheel the size of the wheel - * @param maxPendingTimeouts The maximum number of pending timeouts after which call to - * {@code newTimeout} will result in - * {@link RejectedExecutionException} - * being thrown. No maximum pending timeouts limit is assumed if - * this value is 0 or negative. - * @throws NullPointerException if either of {@code threadFactory} and {@code unit} is {@code null} - * @throws IllegalArgumentException if either of {@code tickDuration} and {@code ticksPerWheel} is <= 0 - */ - public HashedWheelTimer(ThreadFactory threadFactory, - long tickDuration, - TimeUnit unit, - int ticksPerWheel, - long maxPendingTimeouts) { - - Objects.requireNonNull(threadFactory, "threadFactory must not null !"); - Objects.requireNonNull(threadFactory, "unit must not null !"); - if (tickDuration <= 0) { - throw new IllegalArgumentException("tickDuration should > 0 !"); - } - if (ticksPerWheel <= 0) { - throw new IllegalArgumentException("ticksPerWheel should > 0 !"); - } - - wheel = createWheel(ticksPerWheel); - mask = wheel.length - 1; - - long duration = unit.toNanos(tickDuration); - - // 检查一个周期是否比Long.MAX_VALUE还长 - if (duration >= Long.MAX_VALUE / wheel.length) { - throw new IllegalArgumentException(String.format( - "tickDuration: %d (expected: 0 < tickDuration in nanos < %d", - tickDuration, Long.MAX_VALUE / wheel.length)); - } - - this.tickDuration = Math.max(duration, MILLISECOND_NANOS); - workerThread = threadFactory.newThread(worker); - this.maxPendingTimeouts = maxPendingTimeouts; - } - - private static HashedWheelBucket[] createWheel(int ticksPerWheel) { - if (ticksPerWheel <= 0) { - throw new IllegalArgumentException( - "ticksPerWheel must be greater than 0: " + ticksPerWheel); - } - if (ticksPerWheel > 1073741824) { - throw new IllegalArgumentException( - "ticksPerWheel may not be greater than 2^30: " + ticksPerWheel); - } - - ticksPerWheel = normalizeTicksPerWheel(ticksPerWheel); - HashedWheelBucket[] wheel = new HashedWheelBucket[ticksPerWheel]; - for (int i = 0; i < wheel.length; i++) { - wheel[i] = new HashedWheelBucket(); - } - return wheel; - } - - private static int normalizeTicksPerWheel(int ticksPerWheel) { - int normalizedTicksPerWheel = 1; - while (normalizedTicksPerWheel < ticksPerWheel) { - normalizedTicksPerWheel <<= 1; - } - return normalizedTicksPerWheel; - } - - /** - * 显式启动后台线程。即使您没有调用此方法,后台线程也将根据需要自动启动。 - * - * @throws IllegalStateException 如果此计时器已停止{@link #stop()} - */ - @Override - public void start() { - switch (workerState.get()) { - case WORKER_STATE_INIT: - if (workerState.compareAndSet(WORKER_STATE_INIT, WORKER_STATE_STARTED)) { - workerThread.start(); - } - break; - case WORKER_STATE_STARTED: - break; - case WORKER_STATE_SHUTDOWN: - throw new IllegalStateException("cannot be started once stopped"); - default: - throw new Error("Invalid WorkerState"); - } - - // Wait until the startTime is initialized by the worker. - while (startTime == 0) { - try { - startTimeInitialized.await(); - } catch (InterruptedException ignore) { - // Ignore - it will be ready very soon. - } - } - } - - @Override - public Set stop() { - if (Thread.currentThread() == workerThread) { - throw new IllegalStateException( - HashedWheelTimer.class.getSimpleName() + - ".stop() cannot be called from " + - TimerTask.class.getSimpleName()); - } - - if (!workerState.compareAndSet(WORKER_STATE_STARTED, WORKER_STATE_SHUTDOWN)) { - // state is init or shutdown . - return Collections.emptySet(); - } - - - boolean interrupted = false; - while (workerThread.isAlive()) { - workerThread.interrupt(); - try { - workerThread.join(100); - } catch (InterruptedException ignored) { - interrupted = true; - } - } - - if (interrupted) { - Thread.currentThread().interrupt(); - } - - return worker.unprocessedTimeouts(); - } - - @Override - public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) { - Objects.requireNonNull(task, "task require not null !"); - Objects.requireNonNull(unit, "unit require not null !"); - - long pendingTimeoutsCount = pendingTimeouts.incrementAndGet(); - - if (maxPendingTimeouts > 0 && pendingTimeoutsCount > maxPendingTimeouts) { - pendingTimeouts.decrementAndGet(); - throw new RejectedExecutionException("Number of pending timeouts (" - + pendingTimeoutsCount + ") is greater than or equal to maximum allowed pending " - + "timeouts (" + maxPendingTimeouts + ")"); - } - - start(); - - // Add the timeout to the timeout queue which will be processed on the next tick. - // During processing all the queued HashedWheelTimeouts will be added to the correct HashedWheelBucket. - long deadline = System.nanoTime() + unit.toNanos(delay) - startTime; - - // Guard against overflow. - if (delay > 0 && deadline < 0) { - deadline = Long.MAX_VALUE; - } - HashedWheelTimeout timeout = new HashedWheelTimeout(this, task, deadline); - timeouts.add(timeout); - return timeout; - } - - /** - * Returns the number of pending timeouts of this {@link Timer}. - */ - public long pendingTimeouts() { - return pendingTimeouts.get(); - } - - private final class Worker implements Runnable { - private final Set unprocessedTimeouts = new HashSet(); - - private long tick; - - @Override - public void run() { - // Initialize the startTime. - startTime = System.nanoTime(); - if (startTime == 0) { - // We use 0 as an indicator for the uninitialized value here, so make sure it's not 0 when initialized. - startTime = 1; - } - - // Notify the other threads waiting for the initialization at start(). - startTimeInitialized.countDown(); - - do { - final long deadline = waitForNextTick(); - if (deadline > 0) { - int idx = (int) (tick & mask); - processCancelledTasks(); - HashedWheelBucket bucket = - wheel[idx]; - transferTimeoutsToBuckets(); - bucket.expireTimeouts(deadline); - tick++; - } - } while (workerState.get() == WORKER_STATE_STARTED); - - // Fill the unprocessedTimeouts so we can return them from stop() method. - for (HashedWheelBucket bucket : wheel) { - bucket.clearTimeouts(unprocessedTimeouts); - } - for (; ; ) { - HashedWheelTimeout timeout = timeouts.poll(); - if (timeout == null) { - break; - } - if (!timeout.isCancelled()) { - unprocessedTimeouts.add(timeout); - } - } - processCancelledTasks(); - } - - private void transferTimeoutsToBuckets() { - // transfer only max. 100000 timeouts per tick to prevent a thread to stale the workerThread when it just - // adds new timeouts in a loop. - for (int i = 0; i < 100000; i++) { - HashedWheelTimeout timeout = timeouts.poll(); - if (timeout == null) { - // all processed - break; - } - if (timeout.state() == HashedWheelTimeout.ST_CANCELLED) { - // Was cancelled in the meantime. - continue; - } - - long calculated = timeout.deadline / tickDuration; - timeout.remainingRounds = (calculated - tick) / wheel.length; - - final long ticks = Math.max(calculated, tick); // Ensure we don't schedule for past. - int stopIndex = (int) (ticks & mask); - - HashedWheelBucket bucket = wheel[stopIndex]; - bucket.addTimeout(timeout); - } - } - - private void processCancelledTasks() { - for (; ; ) { - HashedWheelTimeout timeout = cancelledTimeouts.poll(); - if (timeout == null) { - // all processed - break; - } - try { - timeout.remove(); - } catch (Throwable e) { - e.printStackTrace(); - } - } - } - - /** - * calculate goal nanoTime from startTime and current tick number, - * then wait until that goal has been reached. - * - * @return Long.MIN_VALUE if received a shutdown request, - * current time otherwise (with Long.MIN_VALUE changed by +1) - */ - private long waitForNextTick() { - long deadline = tickDuration * (tick + 1); - - for (; ; ) { - final long currentTime = System.nanoTime() - startTime; - long sleepTimeMs = (deadline - currentTime + 999999) / 1000000; - - if (sleepTimeMs <= 0) { - if (currentTime == Long.MIN_VALUE) { - return -Long.MAX_VALUE; - } else { - return currentTime; - } - } - - try { - //noinspection BusyWait - Thread.sleep(sleepTimeMs); - } catch (InterruptedException ignored) { - if (workerState.get() == WORKER_STATE_SHUTDOWN) { - return Long.MIN_VALUE; - } - } - } - } - - public Set unprocessedTimeouts() { - return Collections.unmodifiableSet(unprocessedTimeouts); - } - } - - private static final class HashedWheelTimeout implements Timeout { - - private static final int ST_INIT = 0; - private static final int ST_CANCELLED = 1; - private static final int ST_EXPIRED = 2; - private static final AtomicIntegerFieldUpdater STATE_UPDATER = - AtomicIntegerFieldUpdater.newUpdater(HashedWheelTimeout.class, "state"); - - private final HashedWheelTimer timer; - private final TimerTask task; - private final long deadline; - - @SuppressWarnings({"unused", "FieldMayBeFinal", "RedundantFieldInitialization"}) - private volatile int state = ST_INIT; - - // remainingRounds will be calculated and set by Worker.transferTimeoutsToBuckets() before the - // HashedWheelTimeout will be added to the correct HashedWheelBucket. - long remainingRounds; - - // This will be used to chain timeouts in HashedWheelTimerBucket via a double-linked-list. - // As only the workerThread will act on it there is no need for synchronization / volatile. - HashedWheelTimeout next; - HashedWheelTimeout prev; - - // The bucket to which the timeout was added - HashedWheelBucket bucket; - - HashedWheelTimeout(HashedWheelTimer timer, TimerTask task, long deadline) { - this.timer = timer; - this.task = task; - this.deadline = deadline; - } - - @Override - public Timer timer() { - return timer; - } - - @Override - public TimerTask task() { - return task; - } - - @Override - public boolean cancel() { - // only update the state it will be removed from HashedWheelBucket on next tick. - if (!compareAndSetState(ST_INIT, ST_CANCELLED)) { - return false; - } - // If a task should be canceled we put this to another queue which will be processed on each tick. - // So this means that we will have a GC latency of max. 1 tick duration which is good enough. This way - // we can make again use of our MpscLinkedQueue and so minimize the locking / overhead as much as possible. - timer.cancelledTimeouts.add(this); - return true; - } - - void remove() { - HashedWheelBucket bucket = this.bucket; - if (bucket != null) { - bucket.remove(this); - } else { - timer.pendingTimeouts.decrementAndGet(); - } - } - - public boolean compareAndSetState(int expected, int state) { - return STATE_UPDATER.compareAndSet(this, expected, state); - } - - public int state() { - return state; - } - - @Override - public boolean isCancelled() { - return state() == ST_CANCELLED; - } - - @Override - public boolean isExpired() { - return state() == ST_EXPIRED; - } - - public void expire() { - if (!compareAndSetState(ST_INIT, ST_EXPIRED)) { - return; - } - - try { - task.run(this); - } catch (Throwable t) { - t.printStackTrace(); - } - } - - @Override - public String toString() { - final long currentTime = System.nanoTime(); - long remaining = deadline - currentTime + timer.startTime; - - StringBuilder buf = new StringBuilder(192) - .append("HashedWheelTimer(deadline: "); - if (remaining > 0) { - buf.append(remaining) - .append(" ns later"); - } else if (remaining < 0) { - buf.append(-remaining) - .append(" ns ago"); - } else { - buf.append("now"); - } - - if (isCancelled()) { - buf.append(", cancelled"); - } - - return buf.append(", task: ") - .append(task()) - .append(')') - .toString(); - } - } - - /** - * Bucket that stores HashedWheelTimeouts. These are stored in a linked-list like datastructure to allow easy - * removal of HashedWheelTimeouts in the middle. Also the HashedWheelTimeout act as nodes themself and so no - * extra object creation is needed. - */ - private static final class HashedWheelBucket { - // Used for the linked-list datastructure - private HashedWheelTimeout head; - private HashedWheelTimeout tail; - - /** - * Add {@link HashedWheelTimeout} to this bucket. - */ - public void addTimeout(HashedWheelTimeout timeout) { - assert timeout.bucket == null; - timeout.bucket = this; - if (head == null) { - head = tail = timeout; - } else { - tail.next = timeout; - timeout.prev = tail; - tail = timeout; - } - } - - /** - * Expire all {@link HashedWheelTimeout}s for the given {@code deadline}. - */ - public void expireTimeouts(long deadline) { - HashedWheelTimeout timeout = head; - - // process all timeouts - while (timeout != null) { - HashedWheelTimeout next = timeout.next; - if (timeout.remainingRounds <= 0) { - next = remove(timeout); - if (timeout.deadline <= deadline) { - timeout.expire(); - } else { - // The timeout was placed into a wrong slot. This should never happen. - throw new IllegalStateException(String.format( - "timeout.deadline (%d) > deadline (%d)", timeout.deadline, deadline)); - } - } else if (timeout.isCancelled()) { - next = remove(timeout); - } else { - timeout.remainingRounds--; - } - timeout = next; - } - } - - public HashedWheelTimeout remove(HashedWheelTimeout timeout) { - HashedWheelTimeout next = timeout.next; - // remove timeout that was either processed or cancelled by updating the linked-list - if (timeout.prev != null) { - timeout.prev.next = next; - } - if (timeout.next != null) { - timeout.next.prev = timeout.prev; - } - - if (timeout == head) { - // if timeout is also the tail we need to adjust the entry too - if (timeout == tail) { - tail = null; - head = null; - } else { - head = next; - } - } else if (timeout == tail) { - // if the timeout is the tail modify the tail to be the prev node. - tail = timeout.prev; - } - // null out prev, next and bucket to allow for GC. - timeout.prev = null; - timeout.next = null; - timeout.bucket = null; - timeout.timer.pendingTimeouts.decrementAndGet(); - return next; - } - - /** - * Clear this bucket and return all not expired / cancelled {@link Timeout}s. - */ - public void clearTimeouts(Set set) { - for (; ; ) { - HashedWheelTimeout timeout = pollTimeout(); - if (timeout == null) { - return; - } - if (timeout.isExpired() || timeout.isCancelled()) { - continue; - } - set.add(timeout); - } - } - - private HashedWheelTimeout pollTimeout() { - HashedWheelTimeout head = this.head; - if (head == null) { - return null; - } - HashedWheelTimeout next = head.next; - if (next == null) { - tail = this.head = null; - } else { - this.head = next; - next.prev = null; - } - - // null out prev and next to allow for GC. - head.next = null; - head.prev = null; - head.bucket = null; - return head; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timeout.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timeout.java deleted file mode 100644 index 0812e5ba..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timeout.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.zmops.iot.async.util.timer; - -/** - * 借鉴netty。 - * 一个连接着{@link Timer}和{@link TimerTask},表示着任务状态的“关系类” - * - * @author create by TcSnZh on 2021/5/9-下午6:33 - */ -public interface Timeout { - /** - * 返回对应的{@link Timer}。 - */ - Timer timer(); - - /** - * 返回对应的{@link TimerTask} - */ - TimerTask task(); - - /** - * 当且仅当关联的{@link TimerTask}已超时时,才返回{@code true}。 - */ - boolean isExpired(); - - /** - * 当且仅当关联的{@link TimerTask}被取消时,才返回{@code true}。 - */ - boolean isCancelled(); - - /** - * 尝试取消关联的{@link TimerTask}。如果任务已经执行或已取消,它将无副作用地返回。 - * - * @return 如果取消成功完成,则为true,否则为false - */ - @SuppressWarnings("unused") - boolean cancel(); -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timer.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timer.java deleted file mode 100644 index e834ec62..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/Timer.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.zmops.iot.async.util.timer; - -import java.util.Set; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -/** - * 照抄netty - * 让{@link TimerTask}在后台线程中执行。 - * - * @author create by TcSnZh on 2021/5/9-下午6:33 - */ -public interface Timer { - - /** - * 使{@link TimerTask}在指定的延迟后执行一次。 - * - * @param delay 延时长度 - * @param unit 延时单位 - * @return 返回 {@link Timeout}关系类 - * @throws IllegalStateException 如果此计时器已经已停止 - * @throws RejectedExecutionException 如果挂起的超时太多,则创建新的超时会导致系统不稳定。 - */ - Timeout newTimeout(TimerTask task, long delay, TimeUnit unit); - - @SuppressWarnings("unused") - default Timeout newTimeout(Runnable runnable, long delay, TimeUnit unit) { - AtomicReference timeoutRef = new AtomicReference<>(); - newTimeout(timeout -> { - timeoutRef.set(timeout); - runnable.run(); - }, delay, unit); - return timeoutRef.get(); - } - - /** - * 释放此{@link Timer}所有资源(例如线程),并取消所有尚未执行的任务。 - * - * @return 与被该方法取消的任务相关联的 {@link Timeout} - */ - Set stop(); -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/TimerTask.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/TimerTask.java deleted file mode 100644 index a552ba2f..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/util/timer/TimerTask.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.zmops.iot.async.util.timer; - -/** - * 类似于netty的TimerTask。 - * - * @author create by TcSnZh on 2021/5/9-下午5:17 - */ -public interface TimerTask { - void run(Timeout timeout) throws Exception; -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/OnceWork.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/OnceWork.java deleted file mode 100644 index 56fb53ab..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/OnceWork.java +++ /dev/null @@ -1,386 +0,0 @@ -package com.zmops.iot.async.worker; - -import com.zmops.iot.async.executor.timer.SystemClock; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.async.wrapper.WorkerWrapperGroup; - -import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * 一次工作结果的总接口。 - * - * @author tcsnzh[zh.jobs@foxmail.com] create this in 2021/5/25-下午3:22 - */ -public interface OnceWork { - /** - * 返回唯一的workId - */ - String workId(); - - /** - * 判断是否结束。因超时而结束也算结束。 - */ - boolean isFinish(); - - /** - * 同步等待到结束。 - */ - void awaitFinish() throws InterruptedException; - - /** - * 判断是否超时 - * - * @return 如果尚未结束或已结束但未超时,返回false。已结束且已经超时返回true。 - */ - boolean hasTimeout(); - - /** - * 判断是否全部wrapper都处于 执行成功 或 跳过。 - * - * @return 如果已经结束,所有wrapper都成功或跳过返回true,否则返回false。如果尚未结束,返回false。 - */ - default boolean allSuccess() { - if (!isFinish()) { - return false; - } - return getWrappers().values().stream().allMatch(wrapper -> { - final ResultState state = wrapper.getWorkResult().getResultState(); - return state == ResultState.SUCCESS || state == ResultState.DEFAULT; - }); - } - - /** - * 获取全部参与到工作中的wrapper。 - */ - Map> getWrappers(); - - /** - * 获取{@link WorkResult#getResultState()}为{@link ResultState#SUCCESS}的wrapper。 - */ - default Map> getSuccessWrappers() { - return getWrappersOfState(ResultState.SUCCESS); - } - - /** - * 获取状态于这些state中的wrapper。 - * - * @param ofState 状态列表 - * @return 返回Map - */ - default Map> getWrappersOfState(ResultState... ofState) { - final HashSet states = new HashSet<>(Arrays.asList(ofState)); - if (states.isEmpty()) { - return new HashMap<>(1); - } - return getWrappers().entrySet().stream() - .filter(entry -> states.contains(entry.getValue().getWorkResult().getResultState())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } - - /** - * 获取启动时间 - */ - long getStartTime(); - - /** - * 获取结束时间 - * - * @return 如果超时,返回超时的时刻。如果尚未结束,则抛出异常。 - * @throws IllegalStateException 尚未结束,抛出异常。 - */ - long getFinishTime(); - - /** - * @return 已经取消完成 - */ - boolean isCancelled(); - - /** - * @return 是否正在取消中 - */ - boolean isWaitingCancel(); - - /** - * 请求异步取消。 - */ - void pleaseCancel(); - - /** - * 同步等待取消完成。 - */ - default void pleaseCancelAndAwaitFinish() throws InterruptedException { - if (!isCancelled() && !isWaitingCancel()) { - pleaseCancel(); - } - awaitFinish(); - } - - /** - * @return 返回 {@link AsFuture}封装对象。 - */ - default AsFuture asFuture() { - return new AsFuture(this, limitTime -> limitTime / 16); - } - - /** - * 返回{@link Future}视图。 - * - * @param sleepCheckInterval 为防止线程爆炸,在{@link Future#get(long, TimeUnit)}方法时使用隔一段时间检查一次。 - * 该Function的参数为总超时毫秒值,返回值为检查时间间隔。 - * @return 返回 {@link AsFuture}封装对象。 - */ - default AsFuture asFuture(Function sleepCheckInterval) { - return new AsFuture(this, sleepCheckInterval); - } - - // static - - /** - * 空任务 - */ - static OnceWork emptyWork(String workId) { - return new EmptyWork(workId); - } - - // class - - class AsFuture implements Future>> { - private final OnceWork onceWork; - private final Function sleepCheckInterval; - - private AsFuture(OnceWork onceWork, Function sleepCheckInterval) { - this.onceWork = onceWork; - this.sleepCheckInterval = sleepCheckInterval; - } - - /** - * 同步等待取消。 - * - * @param ignore 该参数将被无视。因为暂未实现“修改允许打断属性”功能。todo : await implement - */ - @Override - public boolean cancel(boolean ignore) { - try { - if (onceWork.isFinish()) { - return false; - } - onceWork.pleaseCancelAndAwaitFinish(); - } catch (InterruptedException e) { - throw new RuntimeException("interrupted when await finish in : " + this, e); - } - return true; - } - - @Override - public boolean isCancelled() { - return onceWork.isCancelled(); - } - - @Override - public boolean isDone() { - return onceWork.isFinish(); - } - - @Override - public Map> get() throws InterruptedException, ExecutionException { - if (!onceWork.isFinish()) { - onceWork.awaitFinish(); - } - return onceWork.getWrappers(); - } - - /** - * 避免线程爆炸,该方法不予单独开线程,而是单线程{@link Thread#sleep(long)}每睡一段时间检查一次。 - */ - @Override - public Map> get(long timeout, - TimeUnit unit) - throws InterruptedException, ExecutionException, TimeoutException { - final long millis = Objects.requireNonNull(unit).toMillis(timeout); - final long interval = Math.max(1, Math.min(millis, sleepCheckInterval.apply(millis))); - for (int i = 0; interval * i < millis; i++) { - if (onceWork.isFinish()) { - return onceWork.getWrappers(); - } - Thread.sleep(interval); - } - throw new TimeoutException( - "onceWork.asFuture.get(long,TimeUnit) out of time limit(" + - timeout + "," + unit + ") , this is " + this); - } - - @Override - public String toString() { - return "(asFuture from " + onceWork + ")@" + Integer.toHexString(this.hashCode()); - } - } - - abstract class AbstractOnceWork implements OnceWork { - protected final String workId; - - public AbstractOnceWork(String workId) { - this.workId = workId; - } - - @Override - public String workId() { - return workId; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof OnceWork)) { - return false; - } - OnceWork _o = (OnceWork) o; - return Objects.equals(_o.workId(), this.workId()); - } - - @Override - public int hashCode() { - return workId().hashCode(); - } - - @Override - public String toString() { - final boolean finish; - final StringBuilder sb = new StringBuilder(48) - .append(this.getClass().getSimpleName()) - .append("{isFinish=").append(finish = isFinish()) - .append(", hasTimeout=").append(hasTimeout()) - .append(", allSuccess=").append(allSuccess()) - .append(", getStartTime=").append(getStartTime()) - .append(", isCancelled=").append(isCancelled()) - .append(", isWaitingCancel=").append(isWaitingCancel()); - if (finish) { - sb.append(", getFinishTime=").append(getFinishTime()); - } - return sb - .append(", wrappers::getId=").append(getWrappers().keySet()) - .append('}').toString(); - } - } - - class Impl extends AbstractOnceWork { - protected final WorkerWrapperGroup group; - - public Impl(WorkerWrapperGroup group, String workId) { - super(workId); - this.group = group; - } - - @Override - public boolean isFinish() { - return group.getEndCDL().getCount() > 0; - } - - @Override - public void awaitFinish() throws InterruptedException { - group.getEndCDL().await(); - } - - @Override - public boolean hasTimeout() { - return group.getAnyTimeout().get(); - } - - @Override - public Map> getWrappers() { - return group.getForParamUseWrappers(); - } - - @Override - public long getStartTime() { - return group.getGroupStartTime(); - } - - @Override - public long getFinishTime() { - if (isFinish()) { - throw new IllegalStateException("work not finish."); - } - return group.getFinishTime(); - } - - @Override - public boolean isCancelled() { - return group.isCancelled(); - } - - @Override - public boolean isWaitingCancel() { - return group.isWaitingCancel(); - } - - @Override - public void pleaseCancel() { - group.pleaseCancel(); - } - } - - class EmptyWork extends AbstractOnceWork { - private final long initTime = SystemClock.now(); - - public EmptyWork(String workId) { - super(workId); - } - - @Override - public boolean isFinish() { - return true; - } - - @Override - public void awaitFinish() { - // do nothing - } - - @Override - public boolean hasTimeout() { - return false; - } - - @Override - public Map> getWrappers() { - return Collections.emptyMap(); - } - - @Override - public long getStartTime() { - return initTime; - } - - @Override - public long getFinishTime() { - return initTime; - } - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isWaitingCancel() { - return false; - } - - @Override - public void pleaseCancel() { - } - - @Override - public String toString() { - return "(it's empty work)"; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/ResultState.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/ResultState.java deleted file mode 100644 index dacde052..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/ResultState.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.zmops.iot.async.worker; - -/** - * 结果状态 - * - * @author wuweifeng wrote on 2019-11-19. - */ -public enum ResultState { - SUCCESS, - TIMEOUT, - EXCEPTION, - DEFAULT //默认状态 -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java deleted file mode 100644 index 48e5b5d7..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/worker/WorkResult.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.zmops.iot.async.worker; - -/** - * 执行结果 - */ -public class WorkResult { - /** - * 执行的结果 - */ - private final V result; - /** - * 结果状态 - */ - private final ResultState resultState; - private final Exception ex; - - public WorkResult(V result, ResultState resultState) { - this(result, resultState, null); - } - - public WorkResult(V result, ResultState resultState, Exception ex) { - this.result = result; - this.resultState = resultState; - this.ex = ex; - } - - /** - * 返回不可修改的DEFAULT单例。 - */ - public static WorkResult defaultResult() { - //noinspection unchecked - return (WorkResult) DEFAULT; - } - - private static final WorkResult DEFAULT = new WorkResult<>(null, ResultState.DEFAULT); - - @Override - public String toString() { - return "WorkResult{" + - "result=" + result + - ", resultState=" + resultState + - ", ex=" + ex + - '}'; - } - - public Exception getEx() { - return ex; - } - - public V getResult() { - return result; - } - - public ResultState getResultState() { - return resultState; - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/QuickBuildWorkerWrapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/QuickBuildWorkerWrapper.java deleted file mode 100644 index df21cb6c..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/QuickBuildWorkerWrapper.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.zmops.iot.async.wrapper; - -import com.zmops.iot.async.callback.ICallback; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.util.collection.DirectedGraph; -import com.zmops.iot.async.util.collection.Graph; -import com.zmops.iot.async.wrapper.strategy.WrapperStrategy; - -import java.util.Set; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * 快速构造{@link WorkerWrapper},少废话! - *

- * 直接设置属性,不用麻烦Builder设置来设置去, - * 请 注 意:构造方法不会检查参数合法性,请程序员自己保证参数合法。 - *

- * 将关系存储于有向图中{@link DirectedGraph}以节省每个wrapper都要保存节点数据的开销。 - *

- * - * @author create by TcSnZh on 2021/5/13-上午11:54 - */ -public class QuickBuildWorkerWrapper extends WorkerWrapper { - private final DirectedGraph, Object> graph; - - private volatile Set> nextWrappersCache; - private volatile Set> dependWrappersCache; - - /** - * 构造函数,传入所有属性 - * - * @param id {@link WorkerWrapper#id} - * @param param {@link WorkerWrapper#param} - * @param worker {@link WorkerWrapper#worker} - * @param callback {@link WorkerWrapper#callback} - * @param allowInterrupt {@link WorkerWrapper#allowInterrupt} - * @param enableTimeout {@link WorkerWrapper#enableTimeout} - * @param timeoutLength {@link WorkerWrapper#timeoutLength} - * @param timeoutUnit {@link WorkerWrapper#timeoutLength} - * @param wrapperStrategy {@link WorkerWrapper#timeoutUnit} - * @param wrapperGraph 将节点信息保存在图中,而不是如{@link StableWorkerWrapper}在每个wrapper中都保存节点信息。 - *

- * {@link WorkerWrapper#getDependWrappers()}与{@link WorkerWrapper#getNextWrappers()}方法 - * 将从本图中读取依赖顺序。除此之外,本类不会对本图进行任何修改操作。 - * 因此,传入的此图应当保证读取时的线程安全。 - *

- */ - public QuickBuildWorkerWrapper(String id, - T param, - IWorker worker, - ICallback callback, - boolean allowInterrupt, - boolean enableTimeout, - long timeoutLength, - TimeUnit timeoutUnit, - WrapperStrategy wrapperStrategy, - DirectedGraph, Object> wrapperGraph) { - super(id, worker, callback, allowInterrupt, enableTimeout, timeoutLength, timeoutUnit, wrapperStrategy); - graph = wrapperGraph; - super.param = param; - State.setState(state, State.BUILDING, State.INIT); - } - - @Override - public Set> getNextWrappers() { - if (nextWrappersCache == null) { - synchronized (this) { - if (nextWrappersCache == null) { - nextWrappersCache = graph.getRelationFrom(this).stream() - .map(Graph.Entry::getTo).collect(Collectors.toSet()); - } - } - } - return nextWrappersCache; - } - - @Override - public Set> getDependWrappers() { - if (dependWrappersCache == null) { - synchronized (this) { - if (dependWrappersCache == null) { - dependWrappersCache = graph.getRelationTo(this).stream() - .map(Graph.Entry::getFrom).collect(Collectors.toSet()); - } - } - } - return dependWrappersCache; - } - - @Override - void setNextWrappers(Set> nextWrappers) { - throw new UnsupportedOperationException(); - } - - @Override - void setDependWrappers(Set> dependWrappers) { - throw new UnsupportedOperationException(); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapper.java deleted file mode 100644 index 4622a4af..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapper.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.zmops.iot.async.wrapper; - -import com.zmops.iot.async.callback.ICallback; -import com.zmops.iot.async.callback.IWorker; - -import java.util.Set; -import java.util.concurrent.TimeUnit; - -/** - * {@link WorkerWrapper}默认实现类,将上下游Wrapper保存在自己的Set中。 - * - * @author create by TcSnZh on 2021/5/6-下午2:41 - */ -public class StableWorkerWrapper extends WorkerWrapper { - public StableWorkerWrapper(String id, - IWorker worker, - ICallback callback, - boolean allowInterrupt, - boolean enableTimeout, - long timeoutLength, - TimeUnit timeoutUnit) { - super(id, worker, callback, allowInterrupt, enableTimeout, timeoutLength, timeoutUnit); - } - - /** - * 依赖的wrappers,其dependType字段决定了依赖策略。 - * - *

- * v1.5时将其抽取到本子类。 - * 且修改List为Set,并默认使用LinkedHashSet,以提高id索引效率且保持有序(虽然有序也没什么用)。 - *

- */ - private Set> dependWrappers; - /** - * 在自己后面的wrapper,如果没有,自己就是末尾;如果有一个,就是串行;如果有多个,有几个就需要开几个线程

- * -------2 - * 1 - * -------3 - * 如1后面有2、3 - * - *

- * v1.5时将其抽取到本子类。 - * 且修改List为Set,并在{@link StableWorkerWrapperBuilder}中默认使用LinkedHashSet,以提高id索引效率且保持有序(虽然有序也没什么用)。 - *

- */ - private Set> nextWrappers; - - // ========== public impl ========== - - @Override - public Set> getNextWrappers() { - return nextWrappers; - } - - // ========== package impl ========== - - @Override - void setNextWrappers(Set> nextWrappers) { - this.nextWrappers = nextWrappers; - } - - @Override - public Set> getDependWrappers() { - return dependWrappers; - } - - @Override - void setDependWrappers(Set> dependWrappers) { - this.dependWrappers = dependWrappers; - } - -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapperBuilder.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapperBuilder.java deleted file mode 100644 index b6bd7b53..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/StableWorkerWrapperBuilder.java +++ /dev/null @@ -1,504 +0,0 @@ -package com.zmops.iot.async.wrapper; - -import com.zmops.iot.async.callback.ICallback; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.exception.SkippedException; -import com.zmops.iot.async.worker.WorkResult; -import com.zmops.iot.async.wrapper.strategy.depend.DependMustStrategyMapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependOnUpWrapperStrategy; -import com.zmops.iot.async.wrapper.strategy.depend.DependOnUpWrapperStrategyMapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependenceStrategy; -import com.zmops.iot.async.wrapper.strategy.skip.SkipStrategy; - -import java.util.*; -import java.util.concurrent.TimeUnit; - -/** - * 一个稳定的Builder,兼容1.4版本之前的代码。 - *

- * 效果等同于v1.4及之前的{@link WorkerWrapper.Builder}。 - *

- * 考虑到由于废弃了must方式编排、needCheckNextWrapperResult判断跳过,转用策略器方式,导致本类为了向上兼容保留了一些低效的功能。 - *

- * 权限修饰符为default,表示暂不对外开放。 - * - * @author create by TcSnZh on 2021/5/3-上午12:36 - */ -class StableWorkerWrapperBuilder> - implements WorkerWrapperBuilder { - /** - * 该wrapper的唯一标识。 - * 如果不设置则使用{@code UUID.randomUUID().toString()} - */ - private String id; - /** - * worker将来要处理的param - */ - private T param; - private IWorker worker; - private ICallback callback; - /** - * 自己后面的所有 - */ - private Set> nextWrappers; - /** - * 自己依赖的所有 - */ - private Set> dependWrappers; - /** - * 旧版本的检查是否跳过的开关 - */ - private Boolean needCheckNextWrapperResult = null; - /** - * 新版本的检查是否跳过的策略。 - */ - private SkipStrategy skipStrategy; - /** - * 基本依赖策略。 - *

- * 如果在{@link #build()}调用时,{@code dependenceStrategy==null}, - * 则会给WorkerWrapper设置默认策略{@link DependenceStrategy#ALL_DEPENDENCIES_ALL_SUCCESS}。 - */ - private DependenceStrategy dependenceStrategy; - /** - * 存储自己需要特殊对待的dependWrapper集合 - */ - private Map, DependOnUpWrapperStrategy> dependWrapperActionStrategyMap; - /** - * 存储需要特殊对待自己的nextWrapper集合。 - */ - private Map, DependOnUpWrapperStrategy> selfIsSpecialMap; - /** - * 一个保存以must=true方式传入的WorkerWrapper的集合。 - *

- * 该Set将会加入到{@link WorkerWrapper.StableWrapperStrategy#getDependMustStrategyMapper().mustDependSet}之中 - */ - private Set> mustDependSet; - /** - * 存储强依赖于自己的wrapper集合 - */ - private Set> selfIsMustSet; - /** - * 是否使用了旧的编排模式(Must开关) - *

- * 之所以需要以下两个属性,是为了隔离旧api与新api的策略不兼容的情况。建议早日替换旧方法 - * 例如旧代码里调用{@link WorkerWrapper.Builder#depend(WorkerWrapper, boolean)},参数传入了false。 - */ - private boolean useV15DeprecatedMustDependApi = false; - /** - * 是否使用了新的编排模式。 - *

- * {@link #useV15DeprecatedMustDependApi} - */ - private boolean useV15NewDependApi = false; - /** - * 单个Wrapper超时相关属性 - */ - private boolean enableTimeOut = false; - private long time = -1; - private TimeUnit unit = null; - /** - * 是否允许被打断 - */ - private boolean allowInterrupt = false; - - /** - * 标记自己正在building - */ - private boolean isBuilding = false; - - @Override - public BUILDER_SUB_CLASS worker(IWorker worker) { - this.worker = worker; - return returnThisBuilder(); - } - - @Override - public BUILDER_SUB_CLASS param(T t) { - this.param = t; - return returnThisBuilder(); - } - - @Override - public BUILDER_SUB_CLASS id(String id) { - if (id != null) { - this.id = id; - } - return returnThisBuilder(); - } - - @Override - public BUILDER_SUB_CLASS setSkipStrategy(SkipStrategy strategy) { - this.skipStrategy = strategy; - return returnThisBuilder(); - } - - @Override - public BUILDER_SUB_CLASS callback(ICallback callback) { - this.callback = callback; - return returnThisBuilder(); - } - - @Override - public SetDependImpl setDepend() { - useV15NewDependApi = true; - checkCanNotCompatibleDeprecateMustDependApi(false); - return new SetDependImpl(); - } - - public class SetDependImpl implements SetDepend { - @Override - public SetDependImpl wrapper(WorkerWrapper wrapper) { - if (wrapper == null) { - return this; - } - if (dependWrappers == null) { - dependWrappers = new LinkedHashSet<>(); - } - dependWrappers.add(wrapper); - return this; - } - - @Override - public SetDependImpl mustRequireWrapper(WorkerWrapper wrapper) { - if (wrapper == null) { - return this; - } - wrapper(wrapper); - if (mustDependSet == null) { - mustDependSet = new LinkedHashSet<>(); - } - mustDependSet.add(wrapper); - return this; - } - - @Override - public SetDependImpl specialDependWrapper(DependOnUpWrapperStrategy strategy, WorkerWrapper wrapper) { - if (strategy == null || wrapper == null) { - return this; - } - if (dependWrapperActionStrategyMap == null) { - dependWrapperActionStrategyMap = new LinkedHashMap<>(); - } - dependWrapperActionStrategyMap.put(wrapper, strategy); - return this; - } - - @Override - public SetDependImpl strategy(DependenceStrategy dependenceStrategy) { - if (dependenceStrategy == null) { - return this; - } - StableWorkerWrapperBuilder.this.dependenceStrategy = dependenceStrategy; - return this; - } - - @Override - public BUILDER_SUB_CLASS end() { - return returnThisBuilder(); - } - } - - @Override - public SetNextImpl setNext() { - useV15NewDependApi = true; - checkCanNotCompatibleDeprecateMustDependApi(false); - return new SetNextImpl(); - } - - public class SetNextImpl implements SetNext { - @Override - public SetNextImpl wrapper(WorkerWrapper wrapper) { - if (wrapper == null) { - return this; - } - if (nextWrappers == null) { - nextWrappers = new LinkedHashSet<>(); - } - nextWrappers.add(wrapper); - return this; - } - - @Override - public SetNextImpl mustToNextWrapper(WorkerWrapper wrapper) { - if (wrapper == null) { - return this; - } - wrapper(wrapper); - if (selfIsMustSet == null) { - selfIsMustSet = new LinkedHashSet<>(); - } - selfIsMustSet.add(wrapper); - return this; - } - - @Override - public SetNextImpl specialToNextWrapper(DependOnUpWrapperStrategy strategy, WorkerWrapper wrapper) { - if (strategy == null || wrapper == null) { - return this; - } - wrapper(wrapper); - if (selfIsSpecialMap == null) { - selfIsSpecialMap = new LinkedHashMap<>(); - } - selfIsSpecialMap.put(wrapper, strategy); - return this; - } - - @Override - public BUILDER_SUB_CLASS end() { - return returnThisBuilder(); - } - } - - @Override - public SetTimeOut setTimeOut() { - return new SetTimeOutImpl(); - } - - public class SetTimeOutImpl implements SetTimeOut { - @Override - public SetTimeOutImpl enableTimeOut(boolean enableElseDisable) { - StableWorkerWrapperBuilder.this.enableTimeOut = enableElseDisable; - return this; - } - - @Override - public SetTimeOutImpl setTime(long time, TimeUnit unit) { - if (time <= 0 || unit == null) { - throw new IllegalStateException("Illegal argument : time=" + time + " must > 0, unit=" + unit + " require not null"); - } - StableWorkerWrapperBuilder.this.time = time; - StableWorkerWrapperBuilder.this.unit = unit; - return this; - } - - @Override - public BUILDER_SUB_CLASS end() { - return returnThisBuilder(); - } - } - - @Override - public WorkerWrapperBuilder allowInterrupt(boolean allow) { - allowInterrupt = allow; - return returnThisBuilder(); - } - - @Override - public WorkerWrapper build() { - isBuilding = true; - // ========== 设置单wrapper超时检查 ========== - { - if (enableTimeOut) { - if (time <= 0) { - throw new IllegalArgumentException("timeout time " + time + " must > 0"); - } - if (unit == null) { - throw new IllegalArgumentException(new NullPointerException("timeout unit require not null")); - } - } - } - // ========== 构造wrapper ========== - WorkerWrapper wrapper = new StableWorkerWrapper<>( - id == null ? UUID.randomUUID().toString() : id, - worker, - callback, - allowInterrupt, - enableTimeOut, - time, - unit - ); - wrapper.setDependWrappers(new LinkedHashSet<>()); - wrapper.setNextWrappers(new LinkedHashSet<>()); - // ========== 设置依赖关系/策略 ========== - { - if (dependWrappers != null && dependWrappers.size() > 0) { - dependWrappers.forEach(dependWrapper -> { - wrapper.getDependWrappers().add(dependWrapper); - dependWrapper.getNextWrappers().add(wrapper); - }); - } - if (nextWrappers != null && nextWrappers.size() > 0) { - nextWrappers.forEach(next -> { - wrapper.getNextWrappers().add(next); - next.getDependWrappers().add(wrapper); - }); - } - if (useV15DeprecatedMustDependApi) { - // 适配旧api的must开关 - if (mustDependSet != null && mustDependSet.size() > 0) { - wrapper.getWrapperStrategy().setDependMustStrategyMapper(new DependMustStrategyMapper() - .addDependMust(mustDependSet)); - } - //noinspection deprecation - wrapper.getWrapperStrategy().setDependenceStrategy(DependenceStrategy.IF_MUST_SET_NOT_EMPTY_ALL_SUCCESS_ELSE_ANY); - } else { - if (mustDependSet != null && mustDependSet.size() > 0) { - wrapper.getWrapperStrategy().setDependMustStrategyMapper(new DependMustStrategyMapper().addDependMust(mustDependSet)); - } - if (dependenceStrategy == null) { - setDepend().defaultStrategy(); - } - wrapper.getWrapperStrategy().setDependenceStrategy(dependenceStrategy); - } - if (dependWrapperActionStrategyMap != null && dependWrapperActionStrategyMap.size() > 0) { - DependOnUpWrapperStrategyMapper mapper = new DependOnUpWrapperStrategyMapper(); - dependWrapperActionStrategyMap.forEach(mapper::putMapping); - wrapper.getWrapperStrategy().setDependWrapperStrategyMapper(mapper); - } - if (selfIsMustSet != null && selfIsMustSet.size() > 0) { - //noinspection deprecation - selfIsMustSet.forEach(next -> Optional.ofNullable(next.getWrapperStrategy().getDependMustStrategyMapper()) - .ifPresent(mustMapper -> mustMapper.addDependMust(wrapper))); - } - if (selfIsSpecialMap != null && selfIsSpecialMap.size() > 0) { - selfIsSpecialMap.forEach((next, strategy) -> { - DependOnUpWrapperStrategyMapper dependOnUpWrapperStrategyMapper = next.getWrapperStrategy().getDependWrapperStrategyMapper(); - if (dependOnUpWrapperStrategyMapper == null) { - next.getWrapperStrategy().setDependWrapperStrategyMapper( - dependOnUpWrapperStrategyMapper = new DependOnUpWrapperStrategyMapper()); - } - dependOnUpWrapperStrategyMapper.putMapping(wrapper, strategy); - }); - } - } - // ========== 设置检查是否跳过策略 ========== - { - if (skipStrategy == null) { - wrapper.getWrapperStrategy().setSkipStrategy(needCheckNextWrapperResult != null && !needCheckNextWrapperResult ? - SkipStrategy.NOT_SKIP - : SkipStrategy.CHECK_ONE_LEVEL - ); - } else { - wrapper.getWrapperStrategy().setSkipStrategy(skipStrategy); - } - } - // ========== end ========== - wrapper.state.set(WorkerWrapper.State.INIT.id); - wrapper.setParam(param); - return wrapper; - } - - // ========== deprecated methods ========== - - /** - * @deprecated 建议使用 {@link WorkerWrapperBuilder#depends(WorkerWrapper[])} - * 或{@link WorkerWrapperBuilder#setDepend()}设置更多选项,例如{@link SetDepend#wrapper(WorkerWrapper[])} - * 如果是想要“必须依赖”的功能,则使用{@link SetDepend#mustRequireWrapper(WorkerWrapper[])} - */ - @Deprecated - public BUILDER_SUB_CLASS depend(WorkerWrapper... wrappers) { - if (wrappers == null) { - return returnThisBuilder(); - } - for (WorkerWrapper wrapper : wrappers) { - depend(wrapper); - } - return returnThisBuilder(); - } - - /** - * @deprecated 建议使用 {@link WorkerWrapperBuilder#depends(WorkerWrapper[])}。 - * 或{@link WorkerWrapperBuilder#setDepend()}设置更多选项,例如{@link SetDepend#wrapper(WorkerWrapper)} - * 如果是想要“必须依赖”的功能,则使用{@link SetDepend#mustRequireWrapper(WorkerWrapper[])} - */ - @Deprecated - public BUILDER_SUB_CLASS depend(WorkerWrapper wrapper) { - return depend(wrapper, true); - } - - /** - * @deprecated 建议使用 {@link SetDepend#requireWrapper(WorkerWrapper, boolean)}} - */ - @Deprecated - public BUILDER_SUB_CLASS depend(WorkerWrapper wrapper, boolean isMust) { - if (wrapper == null) { - return returnThisBuilder(); - } - useV15DeprecatedMustDependApi = true; - checkCanNotCompatibleDeprecateMustDependApi(true); - if (dependWrappers == null) { - dependWrappers = new LinkedHashSet<>(); - } - dependWrappers.add(wrapper); - if (isMust) { - if (mustDependSet == null) { - mustDependSet = new LinkedHashSet<>(); - } - mustDependSet.add(wrapper); - } - return returnThisBuilder(); - } - - @Deprecated - public BUILDER_SUB_CLASS next(WorkerWrapper... wrappers) { - if (wrappers == null) { - return returnThisBuilder(); - } - for (WorkerWrapper wrapper : wrappers) { - next(wrapper); - } - return returnThisBuilder(); - } - - @Deprecated - public BUILDER_SUB_CLASS next(WorkerWrapper wrapper) { - return next(wrapper, true); - } - - /** - * 会将wrapper增加到{@link #nextWrappers}。 - * 如果selfIsMust为true,还会将wrapper额外增加到{@link #selfIsMustSet}。 - * - * @param wrapper WorkerWrapper instance - * @param selfIsMust 是否强依赖自己(“强依赖”是旧版本的叫法。即是否必须在自己执行后才能执行。) - * @return 返回Builder。 - * @deprecated 不推荐使用Must开关去设置之后的Wrapper。 - */ - @Deprecated - public BUILDER_SUB_CLASS next(WorkerWrapper wrapper, boolean selfIsMust) { - useV15DeprecatedMustDependApi = true; - checkCanNotCompatibleDeprecateMustDependApi(true); - if (nextWrappers == null) { - nextWrappers = new LinkedHashSet<>(); - } - nextWrappers.add(wrapper); - //强依赖自己 - if (selfIsMust) { - if (selfIsMustSet == null) { - selfIsMustSet = new LinkedHashSet<>(); - } - selfIsMustSet.add(wrapper); - } - return returnThisBuilder(); - } - - /** - * 设置是否要检查之后的Wrapper是否已经执行完毕。 - *

- * 默认为true。 - * - * @param needCheckNextWrapperResult 设为true后,如果之后的Wrapper已经执行完毕。 - * 则跳过本Wrapper并设置{@link WorkResult#getEx()}为{@link SkippedException}。 - * @deprecated v1.5中已经废弃。请使用 - */ - @Deprecated - public BUILDER_SUB_CLASS needCheckNextWrapperResult(boolean needCheckNextWrapperResult) { - this.needCheckNextWrapperResult = needCheckNextWrapperResult; - return returnThisBuilder(); - } - - // util method - - private BUILDER_SUB_CLASS returnThisBuilder() { - //noinspection unchecked - return (BUILDER_SUB_CLASS) this; - } - - private void checkCanNotCompatibleDeprecateMustDependApi(boolean isOld) { - if (!isBuilding && (!isOld && useV15DeprecatedMustDependApi || isOld && useV15NewDependApi)) { - throw new UnsupportedOperationException("新旧api之间不可兼容,请将v1.5之前废弃的方法升级为注释中建议的方法后再调用v1.5之后的新api"); - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java deleted file mode 100644 index 9b5c1fd4..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapper.java +++ /dev/null @@ -1,791 +0,0 @@ -package com.zmops.iot.async.wrapper; - -import com.zmops.iot.async.callback.DefaultCallback; -import com.zmops.iot.async.callback.ICallback; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.exception.CancelException; -import com.zmops.iot.async.exception.EndsNormallyException; -import com.zmops.iot.async.exception.SkippedException; -import com.zmops.iot.async.executor.PollingCenter; -import com.zmops.iot.async.executor.timer.SystemClock; -import com.zmops.iot.async.worker.ResultState; -import com.zmops.iot.async.worker.WorkResult; -import com.zmops.iot.async.wrapper.strategy.WrapperStrategy; -import com.zmops.iot.async.wrapper.strategy.depend.DependMustStrategyMapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependOnUpWrapperStrategyMapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependenceAction; -import com.zmops.iot.async.wrapper.strategy.depend.DependenceStrategy; -import com.zmops.iot.async.wrapper.strategy.skip.SkipStrategy; - -import java.util.*; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.AFTER_WORK; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.BUILDING; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.ERROR; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.INIT; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.SKIP; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.STARTED; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.SUCCESS; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.isState; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.of; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.setState; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.states_all; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.states_of_beforeWorkingEnd; -import static com.zmops.iot.async.wrapper.WorkerWrapper.State.states_of_notWorked; - -/** - * 对每个worker及callback进行包装,一对一 - *

- * v1.5时将其抽取为抽象类,以解耦并提高扩展性。 - * - * @author wuweifeng wrote on 2019-11-19. - */ -@SuppressWarnings("AlibabaAbstractClassShouldStartWithAbstractNaming") -public abstract class WorkerWrapper { - // ========== 固定属性 ========== - - /** - * 该wrapper的唯一标识 - */ - protected final String id; - protected final IWorker worker; - protected final ICallback callback; - /** - * 各种策略的封装类。 - */ - private final WrapperStrategy wrapperStrategy; - /** - * 是否允许被打断 - */ - protected final boolean allowInterrupt; - /** - * 是否启动超时检查 - */ - final boolean enableTimeout; - /** - * 超时时间长度 - */ - final long timeoutLength; - /** - * 超时时间单位 - */ - final TimeUnit timeoutUnit; - - // ========== 临时属性 ========== - - /** - * worker将来要处理的param - */ - protected volatile T param; - /** - * 原子设置wrapper的状态 - *

- * {@link State}此枚举类枚举了state值所代表的状态枚举。 - */ - protected final AtomicInteger state = new AtomicInteger(State.BUILDING.id); - /** - * 该值将在{@link IWorker#action(Object, Map)}进行时设为当前线程,在任务开始前或结束后都为null。 - */ - protected final AtomicReference doWorkingThread = new AtomicReference<>(); - /** - * 也是个钩子变量,用来存临时的结果 - */ - protected final AtomicReference> workResult = new AtomicReference<>(null); - - WorkerWrapper(String id, - IWorker worker, - ICallback callback, - boolean allowInterrupt, - boolean enableTimeout, - long timeoutLength, - TimeUnit timeoutUnit, - WrapperStrategy wrapperStrategy - ) { - if (worker == null) { - throw new NullPointerException("async.worker is null"); - } - this.worker = worker; - this.id = id; - //允许不设置回调 - if (callback == null) { - //noinspection unchecked - callback = (ICallback) DefaultCallback.getInstance(); - } - this.callback = callback; - this.allowInterrupt = allowInterrupt; - this.enableTimeout = enableTimeout; - this.timeoutLength = timeoutLength; - this.timeoutUnit = timeoutUnit; - this.wrapperStrategy = wrapperStrategy; - } - - WorkerWrapper(String id, - IWorker worker, - ICallback callback, - boolean allowInterrupt, - boolean enableTimeout, - long timeoutLength, - TimeUnit timeoutUnit) { - this(id, worker, callback, allowInterrupt, enableTimeout, timeoutLength, timeoutUnit, new StableWrapperStrategy()); - } - - // ========== public ========== - - /** - * 外部调用本线程运行此wrapper的入口方法。 - * 该方法将会确定这组wrapper所属的group。 - * - * @param executorService 该ExecutorService将成功运行后,在nextWrapper有多个时被使用于多线程调用。 - * @param remainTime 剩下的时间 - * @param group wrapper组 - * @throws IllegalStateException 当wrapper正在building状态时被启动,则会抛出该异常。 - */ - public void work(ExecutorService executorService, - long remainTime, - WorkerWrapperGroup group) { - work(executorService, null, remainTime, group); - } - - public String getId() { - return id; - } - - /** - * 返回{@link #workResult}的值。 - * 若调用此方法时workResult还未设置,将会返回{@link WorkResult#defaultResult()}。 - */ - public WorkResult getWorkResult() { - WorkResult res = workResult.get(); - return res == null ? WorkResult.defaultResult() : res; - } - - public void setParam(T param) { - this.param = param; - } - - public State getState() { - return of(state.get()); - } - - /** - * 获取下游Wrapper - */ - public abstract Set> getNextWrappers(); - - /** - * 获取上游wrapper - */ - public abstract Set> getDependWrappers(); - - /** - * 获取本wrapper的超时情况。如有必要还会修改wrapper状态。 - * - * @param withEndIt 如果为true,在检查出已经超时的时候,会将其快速结束。 - * @param startTime 起始时间 - * @param totalTimeLength 总任务时长 - * @return 超时返回-1L,结束但未超时返回0L,尚未结束且未超时返回与deadline的差值 - *

- * 当没有超时,若该wrapper已经结束但没有超时,返回 0L 。 - *

- * 如果该wrapper单独了设置超时策略并正在运行,返回距离超时策略限时相差的毫秒值。 - * 例如设置10ms超时,此时已经开始3ms,则返回 7L。 - * 如果此差值<1,则返回 1L。 - *

- * 如果已经超时,则返回 -1L。 - *

- */ - public long checkTimeout(boolean withEndIt, long startTime, long totalTimeLength) { - do { - WorkResult _workResult = workResult.get(); - // 如果已经有结果了,就根据结果值判断 - if (_workResult != null) { - return _workResult.getResultState() == ResultState.TIMEOUT ? -1L : 0L; - } - // 如果还没有出结果 - // 判断是否超时 - long now = SystemClock.now(); - if (totalTimeLength < now - startTime - || enableTimeout && timeoutUnit.toMillis(timeoutLength) < now - startTime) { - // 如果需要处理该wrapper的状态 - if (withEndIt) { - // CAS一个超时的结果 - if (!workResult.compareAndSet( - null, - new WorkResult<>(null, ResultState.TIMEOUT, null)) - ) { - // 就在想CAS的时候,出结果了,就采用新的结果重新判断一次 - continue; - } - fastFail(true, null, false); - } - return -1L; - } - // 正在运行,尚未超时 - else { - return Math.max(1, startTime + totalTimeLength - now); - } - } while (true); - } - - /** - * 直接取消wrapper运行。 - * 如果状态在 {@link State#states_of_beforeWorkingEnd}中,则调用 {@link #fastFail(boolean, Exception, boolean)}。 - */ - public void cancel() { - if (State.setState(state, State.states_of_beforeWorkingEnd, State.SKIP, null)) { - fastFail(false, new CancelException(), true); - } - } - - public WrapperStrategy getWrapperStrategy() { - return wrapperStrategy; - } - - // ========== protected ========== - - /** - * 工作的核心方法。 - * - * @param fromWrapper 代表这次work是由哪个上游wrapper发起的。如果是首个Wrapper则为null。 - * @param remainTime 剩余时间。 - * @throws IllegalStateException 当wrapper正在building状态时被启动,则会抛出该异常。 - */ - protected void work(ExecutorService executorService, - WorkerWrapper fromWrapper, - long remainTime, - WorkerWrapperGroup group - ) { - long now = SystemClock.now(); - // ================================================ - // 以下是一些lambda。 - // 因为抽取成方法反而不好传参、污染类方法,所以就这么干了 - final Consumer __function__callbackResult = - success -> { - WorkResult _workResult = getWorkResult(); - try { - callback.result(success, param, _workResult); - } catch (Exception e) { - if (setState(state, State.states_of_skipOrAfterWork, State.ERROR, null)) { - fastFail(false, e, _workResult.getEx() instanceof EndsNormallyException); - } - } - }; - final Runnable __function__callbackResultOfFalse_beginNext = - () -> { - __function__callbackResult.accept(false); - beginNext(executorService, now, remainTime, group); - }; - final BiConsumer __function__fastFail_callbackResult$false_beginNext = - (fastFail_isTimeout, fastFail_exception) -> { - boolean isEndsNormally = fastFail_exception instanceof EndsNormallyException; - fastFail(fastFail_isTimeout && !isEndsNormally, fastFail_exception, isEndsNormally); - __function__callbackResultOfFalse_beginNext.run(); - }; - final Runnable __function__doWork = - () -> { - if (setState(state, State.STARTED, State.WORKING)) { - try { - fire(group); - } catch (Exception e) { - if (setState(state, State.WORKING, State.ERROR)) { - __function__fastFail_callbackResult$false_beginNext.accept(false, e); - } - return; - } - } - if (setState(state, State.WORKING, State.AFTER_WORK)) { - __function__callbackResult.accept(true); - beginNext(executorService, now, remainTime, group); - } - }; - // ================================================ - // 开始执行 - try { - if (isState(state, BUILDING)) { - throw new IllegalStateException("wrapper can't work because state is BUILDING ! wrapper is " + this); - } - // 判断是否整组取消 - if (group.isWaitingCancel() || group.isCancelled()) { - cancel(); - return; - } - // 总的已经超时了,就快速失败,进行下一个 - if (remainTime <= 0) { - if (setState(state, states_of_beforeWorkingEnd, ERROR, null)) { - __function__fastFail_callbackResult$false_beginNext.accept(true, null); - } - return; - } - // 如果自己已经执行过了。 - // 可能有多个依赖,其中的一个依赖已经执行完了,并且自己也已开始执行或执行完毕。当另一个依赖执行完毕,又进来该方法时,就不重复处理了 - final AtomicReference oldStateRef = new AtomicReference<>(null); - if (!setState(state, states_of_notWorked, STARTED, oldStateRef::set)) { - return; - } - // 如果wrapper是第一次,要调用callback.begin - if (oldStateRef.get() == INIT) { - try { - callback.begin(); - } catch (Exception e) { - // callback.begin 发生异常 - if (setState(state, states_of_beforeWorkingEnd, ERROR, null)) { - __function__fastFail_callbackResult$false_beginNext.accept(false, e); - } - return; - } - } - - //如果fromWrapper为null,说明自己就是第一批要执行的 - if (fromWrapper == null) { - // 首当其冲,开始工作 - __function__doWork.run(); - return; - } - - // 每个线程都需要判断是否要跳过自己,该方法可能会跳过正在工作的自己。 - final WrapperStrategy wrapperStrategy = getWrapperStrategy(); - if (wrapperStrategy.shouldSkip(getNextWrappers(), this, fromWrapper)) { - if (setState(state, STARTED, SKIP)) { - __function__fastFail_callbackResult$false_beginNext.accept(false, new SkippedException()); - } - return; - } - - // 如果是由其他wrapper调用而运行至此,则使用策略器决定自己的行为 - DependenceAction.WithProperty judge = - wrapperStrategy.judgeAction(getDependWrappers(), this, fromWrapper); - switch (judge.getDependenceAction()) { - case TAKE_REST: - return; - case FAST_FAIL: - if (setState(state, STARTED, ERROR)) { - // 根据FAST_FAIL.fastFailException()设置的属性值来设置fastFail方法的参数 - ResultState resultState = judge.getResultState(); - __function__fastFail_callbackResult$false_beginNext.accept( - resultState == ResultState.TIMEOUT, - judge.getFastFailException() - ); - } - return; - case START_WORK: - __function__doWork.run(); - return; - case JUDGE_BY_AFTER: - default: - throw new IllegalStateException( - "策略配置错误,不应当在WorkerWrapper中返回JUDGE_BY_AFTER或其他无效值 : this=" + this + - ",fromWrapper=" + fromWrapper); - } - } catch (Exception e) { - // wrapper本身抛出了不该有的异常 - setState(state, states_all, ERROR, null); - NotExpectedException ex = new NotExpectedException(e, this); - workResult.set(new WorkResult<>(null, ResultState.EXCEPTION, ex)); - __function__fastFail_callbackResult$false_beginNext.accept(false, ex); - } - } - - - /** - * 本工作线程执行自己的job. - *

- * 本方法不负责校验状态。请在调用前自行检验 - */ - protected void fire(WorkerWrapperGroup group) { - try { - doWorkingThread.set(Thread.currentThread()); - //执行耗时操作 - V result = worker.action(param, group.getForParamUseWrappers()); - workResult.compareAndSet( - null, - new WorkResult<>(result, ResultState.SUCCESS) - ); - } finally { - doWorkingThread.set(null); - } - } - - /** - * 快速失败。 - * 该方法不负责检查状态,请自行控制。 - * - * @param isTimeout 是否是因为超时而快速失败 - * @param e 设置异常信息到{@link WorkResult#getEx()} - * @param isEndsNormally 是否是因正常情况正常而结束,例如跳过{@link SkippedException}、取消{@link CancelException}。 - */ - protected void fastFail(boolean isTimeout, Exception e, boolean isEndsNormally) { - // 试图打断正在执行{@link IWorker#action(Object, Map)}的线程 - Thread _doWorkingThread; - if ((_doWorkingThread = this.doWorkingThread.get()) != null - // 不会打断自己 - && !Objects.equals(Thread.currentThread(), _doWorkingThread)) { - _doWorkingThread.interrupt(); - } - // 尚未处理过结果则设置 - workResult.compareAndSet(null, new WorkResult<>( - worker.defaultValue(), - isTimeout ? ResultState.TIMEOUT : (isEndsNormally ? ResultState.DEFAULT : ResultState.EXCEPTION), - e - )); - } - - /** - * 进行下一个任务 - *

- * 本方法不负责校验状态。请在调用前自行检验 - */ - protected void beginNext(ExecutorService executorService, long now, long remainTime, WorkerWrapperGroup group) { - //花费的时间 - final long costTime = SystemClock.now() - now; - final long nextRemainTIme = remainTime - costTime; - Set> nextWrappers = getNextWrappers(); - if (nextWrappers == null) { - PollingCenter.getInstance().checkGroup(group.new CheckFinishTask()); - return; - } - // nextWrappers只有一个,就用本线程继续跑。 - if (nextWrappers.size() == 1) { - WorkerWrapper next = null; - try { - next = nextWrappers.stream().findFirst().get(); - group.addWrapper(next); - setState(state, AFTER_WORK, SUCCESS); - } finally { - PollingCenter.getInstance().checkGroup(group.new CheckFinishTask()); - if (next != null) { - next.work(executorService, this, nextRemainTIme, group); - } - } - } - // nextWrappers有多个 - else { - try { - group.addWrapper(nextWrappers); - nextWrappers.forEach(next -> executorService.submit(() -> - next.work(executorService, this, nextRemainTIme, group)) - ); - setState(state, AFTER_WORK, SUCCESS); - } finally { - PollingCenter.getInstance().checkGroup(group.new CheckFinishTask()); - } - } - - } - - // ========== hashcode and equals ========== - - @Override - public boolean equals(Object o) { - return super.equals(o); - } - - /** - * {@code return id.hashCode();}返回id值的hashcode - */ - @Override - public int hashCode() { - // final String id can use to .hashcode() . - return id.hashCode(); - } - - // ========== builder ========== - - public static WorkerWrapperBuilder builder() { - return new Builder<>(); - } - - /** - * 自v1.5,该类被抽取到{@link StableWorkerWrapperBuilder}抽象类,兼容之前的版本。 - */ - public static class Builder extends StableWorkerWrapperBuilder> { - /** - * @deprecated 建议使用 {@link #builder()}返回{@link WorkerWrapperBuilder}接口,以调用v1.5之后的规范api - */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - public Builder() { - } - } - - // ========== package access methods ========== - - abstract void setNextWrappers(Set> nextWrappers); - - abstract void setDependWrappers(Set> dependWrappers); - - // ========== toString ========== - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(256) - .append(this.getClass().getSimpleName()) - .append("{id=").append(id) - .append(", state=").append(of(state.get())) - .append(", param=").append(param) - .append(", workResult=").append(workResult) - .append(", allowInterrupt=").append(allowInterrupt) - .append(", enableTimeout=").append(enableTimeout) - .append(", timeoutLength=").append(timeoutLength) - .append(", timeoutUnit=").append(timeoutUnit) - // 防止循环引用,这里只输出相关Wrapper的id - .append(", dependWrappers::getId=["); - final Set> dependWrappers = getDependWrappers(); - dependWrappers.stream().map(WorkerWrapper::getId).forEach(wrapperId -> sb.append(wrapperId).append(", ")); - if (dependWrappers.size() > 0) { - sb.delete(sb.length() - 2, sb.length()); - } - sb - .append("], nextWrappers::getId=["); - final Set> nextWrappers = getNextWrappers(); - nextWrappers.stream().map(WorkerWrapper::getId).forEach(wrapperId -> sb.append(wrapperId).append(", ")); - if (nextWrappers.size() > 0) { - sb.delete(sb.length() - 2, sb.length()); - } - sb - .append("], doWorkingThread=").append(doWorkingThread.get()) - .append(", worker=").append(worker) - .append(", callback=").append(callback) - .append(", wrapperStrategy=").append(wrapperStrategy) - .append('}'); - return sb.toString(); - } - - /** - * 一个通用的策略器实现类,提供了修改的功能。并兼容之前的代码。 - */ - public static class StableWrapperStrategy extends WrapperStrategy.AbstractWrapperStrategy { - private DependOnUpWrapperStrategyMapper dependOnUpWrapperStrategyMapper; - private DependMustStrategyMapper dependMustStrategyMapper; - private DependenceStrategy dependenceStrategy; - private SkipStrategy skipStrategy; - - @Override - public DependOnUpWrapperStrategyMapper getDependWrapperStrategyMapper() { - return dependOnUpWrapperStrategyMapper; - } - - @Override - public void setDependWrapperStrategyMapper(DependOnUpWrapperStrategyMapper dependOnUpWrapperStrategyMapper) { - this.dependOnUpWrapperStrategyMapper = dependOnUpWrapperStrategyMapper; - } - - @SuppressWarnings("deprecation") - @Override - public DependMustStrategyMapper getDependMustStrategyMapper() { - return dependMustStrategyMapper; - } - - @Override - public void setDependMustStrategyMapper(DependMustStrategyMapper dependMustStrategyMapper) { - this.dependMustStrategyMapper = dependMustStrategyMapper; - } - - @Override - public DependenceStrategy getDependenceStrategy() { - return dependenceStrategy; - } - - @Override - public void setDependenceStrategy(DependenceStrategy dependenceStrategy) { - this.dependenceStrategy = dependenceStrategy; - } - - @Override - public SkipStrategy getSkipStrategy() { - return skipStrategy; - } - - @Override - public void setSkipStrategy(SkipStrategy skipStrategy) { - this.skipStrategy = skipStrategy; - } - } - - /** - * state状态枚举工具类 - */ - public enum State { - /** - * 初始化中,builder正在设置其数值 - */ - BUILDING(-1), - /** - * 初始化完成,但是还未执行过。 - */ - INIT(0), - /** - * 执行过。 - * 即至少进行了一次各种判定,例如判断 是否跳过/是否启动工作 - */ - STARTED(1), - /** - * 工作状态 - */ - WORKING(2), - /** - * 工作完成后的收尾工作,例如调用下游wrapper - */ - AFTER_WORK(3), - /** - * wrapper成功执行结束 - */ - SUCCESS(4), - /** - * wrapper失败了 - */ - ERROR(5), - /** - * wrapper被跳过 - */ - SKIP(6); - - // public - - public boolean finished() { - return this == SUCCESS || this == ERROR || this == SKIP; - } - - // package - - State(int id) { - this.id = id; - } - - final int id; - - // package-static - - static final State[] states_of_notWorked = new State[]{INIT, STARTED}; - - static final State[] states_of_skipOrAfterWork = new State[]{SKIP, AFTER_WORK}; - - static final State[] states_of_beforeWorkingEnd = new State[]{INIT, STARTED, WORKING}; - - static final State[] states_all = new State[]{BUILDING, INIT, STARTED, WORKING, AFTER_WORK, SUCCESS, ERROR, SKIP}; - - /** - * 自旋+CAS的设置状态,如果状态不在exceptValues返回内 或 没有设置成功,则返回false。 - * - * @param state {@link WorkerWrapper#state} 要被修改的AtomicInteger引用 - * @param exceptValues 期望的值数组,任何满足该值的state都会被修改 - * @param newValue 新值 - * @param withOperate 如果该参数不为null并且成功设置,该函数将会被执行,其参数为wrapper原子设置之前的旧状态。 - * 之所以需要这个参数,是因为当except值有多个时,无法确定是哪个值被原子修改了。 - * @return 返回是否成功设置。 - */ - static boolean setState(AtomicInteger state, - State[] exceptValues, - State newValue, - Consumer withOperate) { - int current; - boolean inExcepts; - while (true) { - // 判断当前值是否在exceptValues范围内 - current = state.get(); - inExcepts = false; - for (State exceptValue : exceptValues) { - if (inExcepts = current == exceptValue.id) { - break; - } - } - // 如果不在 exceptValues 范围内,直接返回false。 - if (!inExcepts) { - return false; - } - // 如果在 exceptValues 范围,cas成功返回true,失败(即当前值被修改)则自旋。 - if (state.compareAndSet(current, newValue.id)) { - if (withOperate != null) { - withOperate.accept(of(current)); - } - return true; - } - } - } - - /** - * 自旋+CAS的设置状态,如果状态不在exceptValues返回内 或 没有设置成功自旋后不在范围内,则返回false。 - * - * @param state {@link WorkerWrapper#state} 要被修改的AtomicInteger引用 - * @param exceptValue 期望的值 - * @param newValue 新值 - * @return 返回是否成功设置。 - */ - static boolean setState(AtomicInteger state, - State exceptValue, - State newValue) { - int current; - // 如果当前值与期望值相同 - while ((current = state.get()) == exceptValue.id) { - // 则尝试CAS设置新值 - if (state.compareAndSet(current, newValue.id)) { - return true; - } - // 如果当前值被改变,则尝试自旋 - } - // 如果当前值与期望值不相同了,就直接返回false - return false; - } - - /** - * 自旋+CAS的判断是否在这些excepts范围内 - * - * @param excepts 范围。 - */ - @SuppressWarnings("unused") - static boolean inStates(AtomicInteger state, State... excepts) { - int current; - boolean inExcepts; - while (true) { - current = state.get(); - inExcepts = false; - for (State except : excepts) { - if (current == except.id) { - inExcepts = true; - break; - } - } - if (state.get() == current) { - return inExcepts; - } - } - } - - /** - * CAS的判断是否是某个状态 - */ - static boolean isState(AtomicInteger state, @SuppressWarnings("SameParameterValue") State except) { - return state.compareAndSet(except.id, except.id); - } - - static State of(int id) { - return id2state.get(id); - } - - static final Map id2state; - - static { - HashMap map = new HashMap<>(); - for (State s : State.values()) { - map.put(s.id, s); - } - id2state = Collections.unmodifiableMap(map); - } - - - } - - /** - * 这是因未知错误而引发的异常 - */ - public static class NotExpectedException extends Exception { - public NotExpectedException(Throwable cause, WorkerWrapper wrapper) { - super("It's should not happened Exception . wrapper is " + wrapper, cause); - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperBuilder.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperBuilder.java deleted file mode 100644 index 424f766c..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperBuilder.java +++ /dev/null @@ -1,291 +0,0 @@ -package com.zmops.iot.async.wrapper; - -import com.zmops.iot.async.callback.ICallback; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.strategy.depend.DependOnUpWrapperStrategy; -import com.zmops.iot.async.wrapper.strategy.depend.DependenceStrategy; -import com.zmops.iot.async.wrapper.strategy.skip.SkipStrategy; - -import java.util.Collection; -import java.util.concurrent.TimeUnit; - -/** - * 作为优化编排依赖策略后,新增的Builder接口。 - *

- * 该接口中不再开放很多过时的api。 - * - * @author create by TcSnZh on 2021/5/4-下午1:26 - */ -@SuppressWarnings("unused") -public interface WorkerWrapperBuilder { - /** - * 设置唯一id。 - * 如果不设置,{@link StableWorkerWrapperBuilder}会使用UUID - */ - WorkerWrapperBuilder id(String id); - - /** - * 设置{@link IWorker}执行方法。 - * - * @param worker 传入接口实现类/lambda - */ - WorkerWrapperBuilder worker(IWorker worker); - - /** - * wrapper启动后的传入参数。 - * - * @param t 参数 - */ - WorkerWrapperBuilder param(T t); - - /** - * 设置{@link ICallback}回调方法。 - */ - WorkerWrapperBuilder callback(ICallback callback); - - /** - * 设置跳过策略。通常用于检查下游Wrapper是否已经完成。 - *

- * 允许不设置。{@link StableWorkerWrapperBuilder}将会默认设置为检查深度为1的下游Wrapper是否执行完成。 - * - * @param strategy 跳过策略函数。 - */ - WorkerWrapperBuilder setSkipStrategy(SkipStrategy strategy); - - /** - * 设置上游Wrapper依赖关系的选项。 - */ - SetDepend setDepend(); - - @SuppressWarnings({"UnusedReturnValue"}) - interface SetDepend { - /** - * 设置在本Wrapper之前的上游Wrapper。 - * - * @param wrapper 允许传入null。 - */ - SetDepend wrapper(WorkerWrapper wrapper); - - default SetDepend wrapper(WorkerWrapper... wrappers) { - if (wrappers == null) { - return this; - } - for (WorkerWrapper wrapper : wrappers) { - wrapper(wrapper); - } - return this; - } - - default SetDepend wrapper(Collection wrappers) { - if (wrappers == null) { - return this; - } - wrappers.forEach(this::wrapper); - return this; - } - - /** - * 设置必须要执行成功的Wrapper,当所有被该方法设为的上游Wrapper执行成功时,本Wrapper才能执行 - */ - SetDepend mustRequireWrapper(WorkerWrapper wrapper); - - default SetDepend mustRequireWrapper(WorkerWrapper... wrappers) { - if (wrappers == null) { - return this; - } - for (WorkerWrapper wrapper : wrappers) { - mustRequireWrapper(wrapper); - } - return this; - } - - /** - * 一个用于动态判断是否must的方法,与旧的{@code .depend(WorkerWrapper,boolean)}效果相同。 - * - * @param must 如果为true,则等同于{@link #mustRequireWrapper(WorkerWrapper)},否则等同于{@link #wrapper(WorkerWrapper)} - */ - default SetDepend requireWrapper(WorkerWrapper wrapper, boolean must) { - return must ? mustRequireWrapper(wrapper) : wrapper(wrapper); - } - - /** - * 对单个Wrapper设置特殊策略。 - * - * @param wrapper 需要设置特殊策略的Wrapper。 - * @param strategy 特殊策略。 - */ - SetDepend specialDependWrapper(DependOnUpWrapperStrategy strategy, WorkerWrapper wrapper); - - default SetDepend specialDependWrapper(DependOnUpWrapperStrategy strategy, WorkerWrapper... wrappers) { - if (strategy == null || wrappers == null) { - return this; - } - for (WorkerWrapper workerWrapper : wrappers) { - specialDependWrapper(strategy, workerWrapper); - } - return this; - } - - /** - * 设置基本策略并返回。 - *

- * 如果从未调用该方法,则在{@link #build()}时使用{@link #defaultStrategy()}作为默认策略。 - *

- * - * @param dependenceStrategy 根据上游Wrapper判断本Wrapper是否启动的最终策略。 - */ - SetDepend strategy(DependenceStrategy dependenceStrategy); - - /** - * 默认策略为{@link DependenceStrategy#ALL_DEPENDENCIES_ALL_SUCCESS} - */ - default SetDepend defaultStrategy() { - return strategy(DependenceStrategy.ALL_DEPENDENCIES_ALL_SUCCESS); - } - - /** - * 结束依赖关系设置。返回到所属的{@link WorkerWrapperBuilder} - */ - WorkerWrapperBuilder end(); - } - - /** - * 便捷式设置依赖的上游Wrapper。 - * - * @param wrappers 上游Wrapper - */ - default WorkerWrapperBuilder depends(WorkerWrapper... wrappers) { - return setDepend().wrapper(wrappers).end(); - } - - default WorkerWrapperBuilder depends(Collection wrappers) { - return setDepend().wrapper(wrappers).end(); - } - - default WorkerWrapperBuilder depends(DependenceStrategy strategy, WorkerWrapper... wrappers) { - return setDepend().wrapper(wrappers).strategy(strategy).end(); - } - - default WorkerWrapperBuilder depends(DependenceStrategy strategy, Collection wrappers) { - return setDepend().wrapper(wrappers).strategy(strategy).end(); - } - - /** - * 设置下游Wrapper依赖关系的选项。 - */ - SetNext setNext(); - - interface SetNext { - /** - * 设置在本Wrapper之后的下游Wrapper。 - */ - SetNext wrapper(WorkerWrapper wrapper); - - default SetNext wrapper(WorkerWrapper... wrappers) { - if (wrappers == null) { - return this; - } - for (WorkerWrapper wrapper : wrappers) { - wrapper(wrapper); - } - return this; - } - - default SetNext wrapper(Collection wrappers) { - if (wrappers == null) { - return this; - } - wrappers.forEach(this::wrapper); - return this; - } - - /** - * 调用该方法将会让传入的此下游workerWrappers对本Wrapper强依赖(must) - * - * @param wrapper 下游Wrapper - */ - SetNext mustToNextWrapper(WorkerWrapper wrapper); - - default SetNext requireToNextWrapper(WorkerWrapper wrapper, boolean must) { - return must ? mustToNextWrapper(wrapper) : wrapper(wrapper); - } - - /** - * 调用该方法将会让传入的此下游workerWrappers对本Wrapper进行特殊策略判断, - * - * @param strategy 对本Wrapper的特殊策略。 - * @param wrapper 依赖本Wrapper的下游Wrapper。 - * @return 返回Builder自身。 - */ - SetNext specialToNextWrapper(DependOnUpWrapperStrategy strategy, WorkerWrapper wrapper); - - WorkerWrapperBuilder end(); - } - - /** - * 便捷式设置本Wrapper被依赖的下游Wrapper。 - * - * @param wrappers 下游Wrapper - */ - default WorkerWrapperBuilder nextOf(WorkerWrapper... wrappers) { - return setNext().wrapper(wrappers).end(); - } - - default WorkerWrapperBuilder nextOf(Collection wrappers) { - return setNext().wrapper(wrappers).end(); - } - - /** - * 设置超时时间的具体属性 - */ - SetTimeOut setTimeOut(); - - interface SetTimeOut { - /** - * 是否启动超时判断。 - *

- * 默认为true - * - * @param enableElseDisable 是则true - */ - SetTimeOut enableTimeOut(boolean enableElseDisable); - - /** - * 设置单个WorkerWrapper的超时时间。若不设置则不进行超时判断 - * - * @param time 时间数值 - * @param unit 时间单位 - */ - SetTimeOut setTime(long time, TimeUnit unit); - - WorkerWrapperBuilder end(); - } - - /** - * 便携式设置单个WorkerWrapper的超时时间。若不设置则不进行超时判断 - * - * @param time 时间数值 - * @param unit 时间单位 - */ - default WorkerWrapperBuilder timeout(long time, TimeUnit unit) { - return timeout(true, time, unit); - } - - default WorkerWrapperBuilder timeout(boolean enableTimeOut, long time, TimeUnit unit) { - return setTimeOut().enableTimeOut(enableTimeOut).setTime(time, unit).end(); - } - - /** - * 是否允许被试图中断线程 - * - * @param allow 是则true - */ - WorkerWrapperBuilder allowInterrupt(boolean allow); - - /** - * 构建Wrapper。 - * - * @return 返回WorkerWrapper - */ - WorkerWrapper build(); -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperGroup.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperGroup.java deleted file mode 100644 index c77bc285..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/WorkerWrapperGroup.java +++ /dev/null @@ -1,211 +0,0 @@ -package com.zmops.iot.async.wrapper; - -import com.zmops.iot.async.executor.PollingCenter; -import com.zmops.iot.async.executor.timer.SystemClock; -import com.zmops.iot.async.util.timer.Timeout; -import com.zmops.iot.async.util.timer.TimerTask; - -import java.util.Collection; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.stream.Stream; - -/** - * @author create by TcSnZh on 2021/5/9-下午7:21 - */ -public class WorkerWrapperGroup { - /** - * 任务开始时间 - */ - private final long groupStartTime; - /** - * 任务限时 - */ - private final long timeoutLength; - /** - * 该map存放所有wrapper的id和wrapper映射 - *

- * 需要线程安全。 - */ - private final Map> forParamUseWrappers = new ConcurrentHashMap<>(); - /** - * 当全部wrapper都调用结束,它会countDown - */ - private final CountDownLatch endCDL = new CountDownLatch(1); - /** - * 检测到超时,此标记变量将为true。 - */ - private final AtomicBoolean anyTimeout = new AtomicBoolean(false); - /** - * 结束时间 - */ - private volatile long finishTime = -1L; - /** - * 取消任务状态 - * 0 - not cancel , 1 - waiting cancel , 2 - already cancel - */ - private final AtomicInteger cancelState = new AtomicInteger(); - - public static final int NOT_CANCEL = 0; - public static final int WAITING_CANCEL = 1; - public static final int ALREADY_CANCEL = 2; - - public WorkerWrapperGroup(long groupStartTime, long timeoutLength) { - this.groupStartTime = groupStartTime; - this.timeoutLength = timeoutLength; - } - - public void addWrapper(Collection> wrapper) { - Objects.requireNonNull(wrapper).forEach(this::addWrapper); - } - - public void addWrapper(WorkerWrapper... wrappers) { - for (WorkerWrapper wrapper : Objects.requireNonNull(wrappers)) { - addWrapper(wrapper); - } - } - - public void addWrapper(WorkerWrapper wrapper) { - if (wrapper != null) { - forParamUseWrappers.put(wrapper.id, wrapper); - } - } - - public Map> getForParamUseWrappers() { - return forParamUseWrappers; - } - - public CountDownLatch getEndCDL() { - return endCDL; - } - - public long getGroupStartTime() { - return groupStartTime; - } - - public AtomicBoolean getAnyTimeout() { - return anyTimeout; - } - - public long getFinishTime() { - return finishTime; - } - - public boolean isCancelled() { - return cancelState.get() == ALREADY_CANCEL; - } - - public boolean isWaitingCancel() { - return cancelState.get() == WAITING_CANCEL; - } - - @SuppressWarnings("UnusedReturnValue") - public boolean pleaseCancel() { - return cancelState.compareAndSet(NOT_CANCEL, WAITING_CANCEL); - } - - public class CheckFinishTask implements TimerTask { - - @SuppressWarnings("RedundantThrows") - @Override - public void run(Timeout timeout) throws Exception { - // 已经完成了 - if (endCDL.getCount() < 1) { - return; - } - AtomicBoolean hasTimeout = new AtomicBoolean(false); - // 记录正在运行中的wrapper里,最近的限时时间。 - final AtomicLong minDaley = new AtomicLong(Long.MAX_VALUE); - final Collection> values = forParamUseWrappers.values(); - final Stream> stream = values.size() > 128 ? values.parallelStream() : values.stream(); - final boolean needCancel = cancelState.get() == WAITING_CANCEL; - boolean allFinish_and_notNeedCancel = stream - // 需要取消的话就取消 - .peek(wrapper -> { - if (needCancel) { - wrapper.cancel(); - } - }) - // 检查超时并保存最近一次限时时间 - // 当需要取消时,才会不断遍历。如果不需要取消,则计算一次(或并行流中多次)就因allMatch不满足而退出了。 - .peek(wrapper -> { - // time_diff : - // -1 -> already timeout ; - // 0 -> finish but not timeout ; - // X>0 -> is running , may timeout in X seconds . - long time_diff = wrapper.checkTimeout(true, groupStartTime, timeoutLength); - if (time_diff < 0) { - hasTimeout.set(true); - } - if (time_diff == 0) { - return; - } - // use CAS and SPIN for thread safety in parallelStream . - do { - long getMinDaley = minDaley.get(); - // 需要设置最小时间,但是cas失败,则自旋 - if (getMinDaley <= time_diff && !minDaley.compareAndSet(getMinDaley, time_diff)) { - continue; - } - return; - } while (true); - }) - // 判断是否不需要取消且全部结束 - // 在不需要取消时,这里如果还有未结束的wrapper则会提前结束流并返回false - // 在需要取消时,会全部遍历一遍并取消掉已经进入链路的wrapper - .allMatch(wrapper -> !needCancel && wrapper.getState().finished()); - long getMinDaley = minDaley.get(); - // 如果本次取消掉了任务,或是所有wrapper都已经完成 - // ( ps : 前后两条件在这里是必定 一真一假 或 两者全假 ) - if (needCancel || allFinish_and_notNeedCancel) { - // 如果这次进行了取消,则设置取消状态为已完成 - if (needCancel) { - cancelState.set(ALREADY_CANCEL); - } - anyTimeout.set(hasTimeout.get()); - finishTime = SystemClock.now(); - endCDL.countDown(); - } - // 如果有正在运行的wrapper - else { - // 如果有正在WORKING的wrapper,则计算一下限时时间,限时完成后轮询它。 - if (getMinDaley != Long.MAX_VALUE) { - PollingCenter.getInstance().checkGroup(this, getMinDaley); - } - } - } - - // hashCode and equals will called WorkerWrapperGroup.this - - /** - * 将会调用{@link WorkerWrapperGroup#hashCode()} - */ - @Override - public int hashCode() { - return WorkerWrapperGroup.this.hashCode(); - } - - /** - * 将会调用{@link WorkerWrapperGroup#equals(Object)} - */ - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof CheckFinishTask)) { - return false; - } - return Objects.equals(WorkerWrapperGroup.this, ((CheckFinishTask) obj).getParent()); - } - - private WorkerWrapperGroup getParent() { - return WorkerWrapperGroup.this; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/WrapperStrategy.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/WrapperStrategy.java deleted file mode 100644 index d94a076b..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/WrapperStrategy.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy; - - -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependMustStrategyMapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependOnUpWrapperStrategyMapper; -import com.zmops.iot.async.wrapper.strategy.depend.DependenceAction; -import com.zmops.iot.async.wrapper.strategy.depend.DependenceStrategy; -import com.zmops.iot.async.wrapper.strategy.skip.SkipStrategy; - -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * @author create by TcSnZh on 2021/5/17-下午6:23 - */ -public interface WrapperStrategy extends DependenceStrategy, SkipStrategy { - // ========== 这三个策略器用于链式判断是否要开始工作 ========== - - // 从前往后依次判断的顺序为 dependWrapperStrategyMapper -> dependMustStrategyMapper -> dependenceStrategy - - /** - * 设置对特殊Wrapper专用的依赖响应策略。 - * - * @return 该值允许为null - */ - DependOnUpWrapperStrategyMapper getDependWrapperStrategyMapper(); - - /** - * 对必须完成的(must的)Wrapper的依赖响应策略。 - * 这是一个不得不向历史妥协的属性。用于适配must开关方式。 - * - * @return 该值允许为null - * @deprecated 不推荐使用,很有可能被遗弃 - */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - default DependMustStrategyMapper getDependMustStrategyMapper() { - return null; - } - - /** - * 底层全局策略。 - * - * @return 该值不允许为null - */ - DependenceStrategy getDependenceStrategy(); - - // ========== 这是跳过策略 ========== - - /** - * 跳过策略 - * - * @return 不允许为null - */ - SkipStrategy getSkipStrategy(); - - @Override - default DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - // 如果存在依赖,则调用三层依赖响应策略进行判断 - - DependenceStrategy strategy = getDependWrapperStrategyMapper(); - if (getDependMustStrategyMapper() != null) { - strategy = strategy == null ? getDependMustStrategyMapper() : strategy.thenJudge(getDependenceStrategy()); - } - if (getDependenceStrategy() != null) { - strategy = strategy == null ? getDependenceStrategy() : strategy.thenJudge(getDependenceStrategy()); - } - if (strategy == null) { - throw new IllegalStateException("配置无效,三层判断策略均为null,请开发者检查自己的Builder是否逻辑错误!"); - } - return strategy.judgeAction(dependWrappers, thisWrapper, fromWrapper); - } - - @Override - default boolean shouldSkip(Set> nextWrappers, WorkerWrapper thisWrapper, WorkerWrapper fromWrapper) { - return getSkipStrategy() != null && getSkipStrategy().shouldSkip(nextWrappers, thisWrapper, fromWrapper); - } - - default void setDependWrapperStrategyMapper(DependOnUpWrapperStrategyMapper dependOnUpWrapperStrategyMapper) { - throw new UnsupportedOperationException(); - } - - default void setDependMustStrategyMapper(DependMustStrategyMapper dependMustStrategyMapper) { - throw new UnsupportedOperationException(); - } - - default void setDependenceStrategy(DependenceStrategy dependenceStrategy) { - throw new UnsupportedOperationException(); - } - - default void setSkipStrategy(SkipStrategy skipStrategy) { - throw new UnsupportedOperationException(); - } - - /** - * 抽象策略器,实现了toString - */ - abstract class AbstractWrapperStrategy implements WrapperStrategy { - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(128) - .append(this.getClass().getSimpleName()).append('{'); - final AtomicBoolean needAppendSplit = new AtomicBoolean(); - appendNotNullProperty(sb, "dependWrapperStrategyMapper=", - getDependWrapperStrategyMapper(), needAppendSplit, ", "); - appendNotNullProperty(sb, "dependMustStrategyMapper=", - getDependMustStrategyMapper(), needAppendSplit, ", "); - appendNotNullProperty(sb, "dependenceStrategy=", - getDependenceStrategy(), needAppendSplit, ", "); - appendNotNullProperty(sb, "skipStrategy=", - getSkipStrategy(), needAppendSplit, ", "); - return sb.append('}').toString(); - } - - private static void appendNotNullProperty(StringBuilder sb, - String propPrefix, - Object prop, - AtomicBoolean needAppendSplit, - @SuppressWarnings("SameParameterValue") String split) { - if (prop == null) { - return; - } - if (needAppendSplit.get()) { - sb.append(split); - } - sb.append(propPrefix).append(prop); - needAppendSplit.set(true); - } - } - - /** - * 默认策略器,用默认值实现了所有属性。 - */ - class DefaultWrapperStrategy extends AbstractWrapperStrategy { - @Override - public DependOnUpWrapperStrategyMapper getDependWrapperStrategyMapper() { - return null; - } - - @SuppressWarnings("deprecation") - @Override - public DependMustStrategyMapper getDependMustStrategyMapper() { - return null; - } - - @Override - public DependenceStrategy getDependenceStrategy() { - return DependenceStrategy.ALL_DEPENDENCIES_ALL_SUCCESS; - } - - @Override - public SkipStrategy getSkipStrategy() { - return SkipStrategy.CHECK_ONE_LEVEL; - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependMustStrategyMapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependMustStrategyMapper.java deleted file mode 100644 index 3eb19deb..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependMustStrategyMapper.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy.depend; - -import com.zmops.iot.async.worker.ResultState; -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * 这是一个“向历史妥协”的策略器。以兼容must开关模式。 - * - * @author create by TcSnZh on 2021/5/4-下午1:24 - */ -@SuppressWarnings("UnusedReturnValue") -public class DependMustStrategyMapper implements DependenceStrategy { - - private final Set> mustDependSet = new LinkedHashSet<>(); - - /** - * 在{@link #mustDependSet} 中的must依赖。 - *

- * 如果{@code mustDependSet == null || mustDependSet.size() < 1},返回{@link DependenceAction#JUDGE_BY_AFTER} - *

- * 如果所有的Wrapper已经完成,本Wrapper将会开始工作。 - *

- * 如果任一{@link #mustDependSet}中的Wrapper失败,则返回{@link DependenceAction#FAST_FAIL}。 - * 具体超时/异常则根据{@link ResultState}的值进行判断。 - *

- * 如果存在Wrapper未完成 且 所有的Wrapper都未失败,则返回{@link DependenceAction#JUDGE_BY_AFTER}。 - *

- */ - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - if (mustDependSet.size() < 1) { - return DependenceAction.JUDGE_BY_AFTER.emptyProperty(); - } - boolean allSuccess = true; - for (WorkerWrapper wrapper : mustDependSet) { - switch (wrapper.getWorkResult().getResultState()) { - case TIMEOUT: - return DependenceAction.FAST_FAIL.fastFailException(ResultState.TIMEOUT, null); - case EXCEPTION: - return DependenceAction.FAST_FAIL.fastFailException(ResultState.EXCEPTION, wrapper.getWorkResult().getEx()); - case DEFAULT: - allSuccess = false; - case SUCCESS: - default: - } - } - if (allSuccess) { - return DependenceAction.START_WORK.emptyProperty(); - } - return DependenceAction.JUDGE_BY_AFTER.emptyProperty(); - } - - /** - * 新增must依赖。 - * - * @param mustDependWrapper WorkerWrapper - * @return 返回自身 - */ - public DependMustStrategyMapper addDependMust(WorkerWrapper mustDependWrapper) { - if (mustDependWrapper == null) { - return this; - } - mustDependSet.add(mustDependWrapper); - return this; - } - - public DependMustStrategyMapper addDependMust(Collection> wrappers) { - if (wrappers == null) { - return this; - } - mustDependSet.addAll(wrappers); - return this; - } - - public DependMustStrategyMapper addDependMust(WorkerWrapper... wrappers) { - if (wrappers == null) { - return this; - } - return addDependMust(Arrays.asList(wrappers)); - } - - public Set> getMustDependSet() { - return mustDependSet; - } - - @Override - public String toString() { - return "DependMustStrategyMapper{" + - "mustDependSet::getId=" + mustDependSet.stream().map(WorkerWrapper::getId).collect(Collectors.toList()) + - '}'; - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategy.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategy.java deleted file mode 100644 index fc6e4703..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategy.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy.depend; - -import com.zmops.iot.async.wrapper.WorkerWrapper; - -/** - * 由上游wrapper决定本wrapper行为的单参数策略。 - * - * @author create by TcSnZh on 2021/5/1-下午11:16 - */ -@FunctionalInterface -public interface DependOnUpWrapperStrategy { - /** - * 仅使用一个参数(即调用自身的上游wrapper)的判断方法 - * - * @param fromWrapper 调用本Wrapper的上游Wrapper - * @return 返回 {@link DependenceAction.WithProperty} - */ - DependenceAction.WithProperty judge(WorkerWrapper fromWrapper); - - // ========== 送几个供链式调用的默认值 ========== - - /** - * 成功时,交给下一个策略器判断。 - * 未运行时,休息。 - * 失败时,失败。 - */ - DependOnUpWrapperStrategy SUCCESS_CONTINUE = new DependOnUpWrapperStrategy() { - @Override - public DependenceAction.WithProperty judge(WorkerWrapper ww) { - switch (ww.getWorkResult().getResultState()) { - case SUCCESS: - return DependenceAction.JUDGE_BY_AFTER.emptyProperty(); - case DEFAULT: - return DependenceAction.TAKE_REST.emptyProperty(); - case EXCEPTION: - case TIMEOUT: - return DependenceAction.FAST_FAIL.fastFailException(ww.getWorkResult().getResultState(), ww.getWorkResult().getEx()); - default: - } - throw new RuntimeException("不该执行到的代码 workResult.getResultState()=" + ww.getWorkResult().getResultState()); - } - - @Override - public String toString() { - return "SUCCESS_CONTINUE"; - } - }; - /** - * 成功时,开始工作。 - * 未运行时,交给下一个策略器判断。 - * 失败时,失败。 - */ - DependOnUpWrapperStrategy SUCCESS_START_INIT_CONTINUE = new DependOnUpWrapperStrategy() { - @Override - public DependenceAction.WithProperty judge(WorkerWrapper ww) { - switch (ww.getWorkResult().getResultState()) { - case SUCCESS: - return DependenceAction.START_WORK.emptyProperty(); - case DEFAULT: - return DependenceAction.JUDGE_BY_AFTER.emptyProperty(); - case EXCEPTION: - case TIMEOUT: - return DependenceAction.FAST_FAIL.fastFailException(ww.getWorkResult().getResultState(), ww.getWorkResult().getEx()); - default: - } - throw new RuntimeException("不该执行到的代码 workResult.getResultState()=" + ww.getWorkResult().getResultState()); - } - - @Override - public String toString() { - return "SUCCESS_START_INIT_CONTINUE"; - } - }; -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategyMapper.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategyMapper.java deleted file mode 100644 index 2b0740f0..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependOnUpWrapperStrategyMapper.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy.depend; - - -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 对不同的{@link WorkerWrapper}调用者实行个性化依赖响应策略。 - *

- * 使用{@link DependOnUpWrapperStrategyMapper}本实现类对{@link DependenceStrategy}进行增强, - * - * @author create by TcSnZh on 2021/5/1-下午11:12 - */ -public class DependOnUpWrapperStrategyMapper implements DependenceStrategy { - private final Map, DependOnUpWrapperStrategy> mapper = new ConcurrentHashMap<>(4); - - /** - * 设置对应策略 - * - * @param targetWrapper 要设置策略的WorkerWrapper - * @param strategy 要设置的策略 - * @return 返回this,链式调用。 - */ - @SuppressWarnings("UnusedReturnValue") - public DependOnUpWrapperStrategyMapper putMapping(WorkerWrapper targetWrapper, DependOnUpWrapperStrategy strategy) { - mapper.put(targetWrapper, strategy); - return this; - } - - /** - * 判断方法。 - *

- * 如果fromWrapper在{@link #mapper}中,则返回{@link DependOnUpWrapperStrategy}的判断返回值。否则返回{@link DependenceAction#JUDGE_BY_AFTER} - * - * @param dependWrappers (这里不会使用该值)thisWrapper.dependWrappers的属性值。 - * @param thisWrapper (这里不会使用该值)thisWrapper,即为“被催促”的WorkerWrapper - * @param fromWrapper 调用来源Wrapper。 - * @return 如果在mapper中有对fromWrapper的处理策略,则使用其进行判断。否则返回JUDGE_BY_AFTER交给下一个进行判断。 - */ - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - DependOnUpWrapperStrategy strategy = mapper.get(fromWrapper); - if (strategy == null) { - return DependenceAction.JUDGE_BY_AFTER.emptyProperty(); - } - return strategy.judge(fromWrapper); - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(64) - .append(this.getClass().getSimpleName()).append("{mapper="); - final Set, DependOnUpWrapperStrategy>> entrySet = mapper.entrySet(); - entrySet.forEach(entry -> { - sb.append(entry.getKey().getId()).append(':').append(entry.getValue()).append(", "); - }); - if (entrySet.size() > 0) { - final int length = sb.length(); - sb.delete(length - 2, length); - } - return sb.append('}').toString(); - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceAction.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceAction.java deleted file mode 100644 index dd4fb70d..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceAction.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy.depend; - -import com.zmops.iot.async.worker.ResultState; - -/** - * 返回执行工作类型的枚举。 - * - * @author create by TcSnZh on 2021/5/1-下午10:47 - */ -public enum DependenceAction { - /** - * 开始工作。WorkerWrapper会执行工作方法。 - */ - START_WORK, - /** - * 还没轮到,休息一下。WorkerWrapper中的调用栈会返回,以等待其他上游wrapper调用它,或是会一生无缘被调用。 - */ - TAKE_REST, - /** - * 立即失败。WorkerWrapper会去执行快速失败的方法。 - */ - FAST_FAIL, - /** - * 交给下层{@link DependenceStrategy}进行判断。 - * 由于{@link DependenceStrategy#thenJudge(DependenceStrategy)}的责任链设计模式,该返回值的意义就是调用责任链上下一个策略。 - *

- * 在WorkerWrapper中不需要考虑此值,因为配置正常的情况下不会返回这个值。 - */ - JUDGE_BY_AFTER; - - // 空值单例 - - public WithProperty emptyProperty() { - if (this == FAST_FAIL) { - throw new UnsupportedOperationException( - "配置错误: FAST_FAIL 不能使用该方法,请使用fastFailException(ResultState, Exception)具体设置fastFail的参数。"); - } - return empty; - } - - private final WithProperty empty = new WithProperty() { - @Override - public void setResultState(ResultState resultState) { - throw new UnsupportedOperationException("empty not support modify"); - } - - @Override - public void setFastFailException(Exception fastFailException) { - throw new UnsupportedOperationException("empty not support modify"); - } - - private final String toString = getDependenceAction() + ".empty"; - - @Override - public String toString() { - return toString; - } - }; - - // 携带异常信息、ResultState的返回值 - - public WithProperty fastFailException(ResultState resultState, Exception e) { - WithProperty withProperty = this.new WithProperty(); - withProperty.setResultState(resultState); - withProperty.setFastFailException(e); - return withProperty; - } - - /** - * 有时需要封装一些参数来返回,则使用本内部类进行返回。 - *

- * 所有的构造方法权限均为private,请在父枚举类{@link DependenceAction}的方法中选择合适的模板生成内部类WithProperty。 - */ - public class WithProperty { - /** - * 以下两个属性用于设置fastFail的属性 - */ - private ResultState resultState; - private Exception fastFailException; - - // getter setter - - public ResultState getResultState() { - return resultState; - } - - public void setResultState(ResultState resultState) { - this.resultState = resultState; - } - - public Exception getFastFailException() { - return fastFailException; - } - - public void setFastFailException(Exception fastFailException) { - this.fastFailException = fastFailException; - } - - public DependenceAction getDependenceAction() { - return DependenceAction.this; - } - - // constructor always private. - - private WithProperty() { - } - } -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceStrategy.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceStrategy.java deleted file mode 100644 index 06350337..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/depend/DependenceStrategy.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy.depend; - -import com.zmops.iot.async.worker.ResultState; -import com.zmops.iot.async.worker.WorkResult; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.async.wrapper.WorkerWrapperGroup; - -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.stream.Collectors; - -/** - * 依赖策略接口。 - *

- * 提供了多个默认值可以作为单例模式使用。 - *

- * 工作原理示例: - *

- * ==== 一个简单示例 ==== - * 现有三个WorkerWrapper:A、B、C,其中 {@code A{dependWrappers=[B,C],} } - * 当B执行完成后调用A时,根据依赖关系ALL_DEPENDENCIES_ALL_SUCCESS,还需等待C的结果。 - * 然后,当C执行完成后调用A时,根据依赖关系ALL_DEPENDENCIES_ALL_SUCCESS: 此时如果C成功了,A就开工,此时如果C失败了,A就失败。 - * ==== 简单示例2 ==== - * - *

- * - * @author create by TcSnZh on 2021/5/1-下午10:48 - */ -@FunctionalInterface -public interface DependenceStrategy { - /** - * 核心判断策略 - * - * @param dependWrappers thisWrapper.dependWrappers的属性值。 - * @param thisWrapper thisWrapper,即为“被催促”的WorkerWrapper - * @param fromWrapper 调用来源Wrapper。 - *

- * 该参数不会为null。 - * 因为在{@link WorkerWrapper#work(ExecutorService, long, WorkerWrapperGroup)}方法中传入的的第一批无依赖的Wrapper, - * 不会被该策略器所判断,而是不论如何直接执行。 - *

- * @return 返回枚举值内部类,WorkerWrapper将会根据其值来决定自己如何响应这次调用。 {@link DependenceAction.WithProperty} - */ - DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper); - - /** - * 如果本策略器的judge方法返回了JUDGE_BY_AFTER,则交给下一个策略器来判断。 - * - * @param after 下层策略器 - * @return 返回一个“封装的多层策略器” - */ - default DependenceStrategy thenJudge(DependenceStrategy after) { - DependenceStrategy that = this; - return new DependenceStrategy() { - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - DependenceAction.WithProperty judge = that.judgeAction(dependWrappers, thisWrapper, fromWrapper); - if (judge.getDependenceAction() == DependenceAction.JUDGE_BY_AFTER) { - return after.judgeAction(dependWrappers, thisWrapper, fromWrapper); - } - return judge; - } - - @Override - public String toString() { - return that + " ----> " + after; - } - }; - } - - // ========== 以下是一些默认实现 ========== - - /** - * 被依赖的所有Wrapper都必须成功才能开始工作。 - * 如果其中任一Wrapper还没有执行且不存在失败,则休息。 - * 如果其中任一Wrapper失败则立即失败。 - */ - DependenceStrategy ALL_DEPENDENCIES_ALL_SUCCESS = new DependenceStrategy() { - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - boolean hasWaiting = false; - for (final WorkerWrapper dependWrapper : dependWrappers) { - WorkResult workResult = dependWrapper.getWorkResult(); - switch (workResult.getResultState()) { - case DEFAULT: - hasWaiting = true; - break; - case SUCCESS: - break; - case TIMEOUT: - case EXCEPTION: - return DependenceAction.FAST_FAIL.fastFailException(workResult.getResultState(), workResult.getEx()); - default: - throw new RuntimeException("不该执行到的代码 workResult.getResultState()=" + workResult.getResultState()); - } - } - if (hasWaiting) { - return DependenceAction.TAKE_REST.emptyProperty(); - } - return DependenceAction.START_WORK.emptyProperty(); - } - - @Override - public String toString() { - return "ALL_DEPENDENCIES_ALL_SUCCESS"; - } - }; - - /** - * 被依赖的Wrapper中任意一个成功了就可以开始工作。 - * 如果其中所有Wrapper还没有执行,则休息。 - * 如果其中一个Wrapper失败且不存在成功则立即失败。 - */ - DependenceStrategy ALL_DEPENDENCIES_ANY_SUCCESS = new DependenceStrategy() { - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - boolean hasFailed = false; - Exception fastFailException = null; - ResultState resultState = null; - for (final WorkerWrapper dependWrapper : dependWrappers) { - WorkResult workResult = dependWrapper.getWorkResult(); - switch (workResult.getResultState()) { - case DEFAULT: - break; - case SUCCESS: - return DependenceAction.START_WORK.emptyProperty(); - case TIMEOUT: - case EXCEPTION: - resultState = !hasFailed ? workResult.getResultState() : resultState; - fastFailException = !hasFailed ? workResult.getEx() : fastFailException; - // 跳过不算失败 - hasFailed = true; - break; - default: - throw new RuntimeException("不该执行到的代码 workResult.getResultState()=" + workResult.getResultState()); - } - } - if (hasFailed) { - return DependenceAction.FAST_FAIL.fastFailException(resultState, fastFailException); - } - return DependenceAction.TAKE_REST.emptyProperty(); - } - - @Override - public String toString() { - return "ALL_DEPENDENCIES_ANY_SUCCESS"; - } - }; - - /** - * 如果被依赖的工作中任一失败,则立即失败。 - * 否则就开始工作(不论之前的工作有没有开始)。 - */ - @SuppressWarnings("unused") - DependenceStrategy ALL_DEPENDENCIES_NONE_FAILED = new DependenceStrategy() { - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - for (WorkerWrapper dependWrapper : dependWrappers) { - WorkResult workResult = dependWrapper.getWorkResult(); - switch (workResult.getResultState()) { - case TIMEOUT: - case EXCEPTION: - return DependenceAction.FAST_FAIL.fastFailException(workResult.getResultState(), workResult.getEx()); - default: - } - } - return DependenceAction.START_WORK.emptyProperty(); - } - - @Override - public String toString() { - return "ALL_DEPENDENCIES_NONE_FAILED"; - } - }; - - /** - * 只有当指定的这些Wrapper都成功时,才会开始工作。 - * 任一失败会快速失败。 - * 任一还没有执行且不存在失败,则休息。 - * - * @param theseWrapper 该方法唯一有效参数。 - * @return 返回生成的 {@link DependenceAction.WithProperty) - */ - @SuppressWarnings("unused") - static DependenceStrategy theseWrapperAllSuccess(Set> theseWrapper) { - return new DependenceStrategy() { - private final Set> theseWrappers; - private final String toString; - - { - theseWrappers = Collections.unmodifiableSet(theseWrapper); - toString = "THESE_WRAPPER_MUST_SUCCESS:" + theseWrappers.stream().map(WorkerWrapper::getId).collect(Collectors.toList()); - } - - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - boolean hasWaiting = false; - for (WorkerWrapper wrapper : theseWrappers) { - ResultState resultState = wrapper.getWorkResult().getResultState(); - switch (resultState) { - case DEFAULT: - hasWaiting = true; - break; - case SUCCESS: - break; - case TIMEOUT: - case EXCEPTION: - return DependenceAction.FAST_FAIL.fastFailException(resultState, wrapper.getWorkResult().getEx()); - default: - throw new RuntimeException("不该执行到的代码 workResult.getResultState()=" + resultState); - } - } - if (hasWaiting) { - return DependenceAction.TAKE_REST.emptyProperty(); - } - return DependenceAction.START_WORK.emptyProperty(); - } - - - @Override - public String toString() { - return toString; - } - }; - } - - /** - * 此值用于适配v1.4及之前的must开关模式, - * 当`wrapperStrategy`的`dependMustStrategyMapper`的`mustDependSet`不为空时, - * 则休息(因为能判断到这个责任链说明set中存在不满足的值L)。 - * 为空时,则任一成功则执行。 - * - * @deprecated 不推荐使用must开关 - */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - DependenceStrategy IF_MUST_SET_NOT_EMPTY_ALL_SUCCESS_ELSE_ANY = new DependenceStrategy() { - @Override - public DependenceAction.WithProperty judgeAction(Set> dependWrappers, - WorkerWrapper thisWrapper, - WorkerWrapper fromWrapper) { - DependMustStrategyMapper mustMapper = thisWrapper.getWrapperStrategy().getDependMustStrategyMapper(); - if (mustMapper != null && !mustMapper.getMustDependSet().isEmpty()) { - // 至少有一个must,则因为must未完全完成而等待。 - return DependenceAction.TAKE_REST.emptyProperty(); - } - // 如果一个must也没有,则认为应该是ANY模式。 - return DependenceStrategy.ALL_DEPENDENCIES_ANY_SUCCESS.judgeAction(dependWrappers, thisWrapper, fromWrapper); - } - - @Override - public String toString() { - return "IF_MUST_SET_NOT_EMPTY_ALL_SUCCESS_ELSE_ANY"; - } - }; - -} diff --git a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/skip/SkipStrategy.java b/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/skip/SkipStrategy.java deleted file mode 100644 index 72fef2cf..00000000 --- a/zeus-application-toolkit/toolkit-async/src/main/java/com/zmops/iot/async/wrapper/strategy/skip/SkipStrategy.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.zmops.iot.async.wrapper.strategy.skip; - - -import com.zmops.iot.async.wrapper.WorkerWrapper; - -import java.util.Set; - -/** - * @author create by TcSnZh on 2021/5/6-下午3:02 - */ -@FunctionalInterface -public interface SkipStrategy { - /** - * 跳过策略函数。返回true将会使WorkerWrapper跳过执行。 - * - * @param nextWrappers 下游WrapperSet - * @param thisWrapper 本WorkerWrapper - * @param fromWrapper 呼叫本Wrapper的上游Wrapper - * @return 返回true将会使WorkerWrapper跳过执行。 - */ - boolean shouldSkip(Set> nextWrappers, WorkerWrapper thisWrapper, WorkerWrapper fromWrapper); - - /** - * 不跳过 - */ - SkipStrategy NOT_SKIP = new SkipStrategy() { - @Override - public boolean shouldSkip(Set> nextWrappers, WorkerWrapper thisWrapper, WorkerWrapper fromWrapper) { - return false; - } - - @Override - public String toString() { - return "NOT_SKIP"; - } - }; - - /** - * 距离为1的wrapper都不在初始化状态 - */ - SkipStrategy CHECK_ONE_LEVEL = new SkipStrategy() { - - @Override - public boolean shouldSkip(Set> nextWrappers, WorkerWrapper thisWrapper, WorkerWrapper fromWrapper) { - return nextWrappers != null && !nextWrappers.isEmpty() - && nextWrappers.stream().allMatch(workerWrapper -> workerWrapper.getState().finished()); - } - - @Override - public String toString() { - return "CHECK_ONE_LEVEL"; - } - }; -} diff --git a/zeus-application-toolkit/toolkit-eventbus/pom.xml b/zeus-application-toolkit/toolkit-eventbus/pom.xml deleted file mode 100644 index 2c2fcb98..00000000 --- a/zeus-application-toolkit/toolkit-eventbus/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - zeus-application-toolkit - com.zmops - 1.0-beta - - 4.0.0 - - toolkit-eventbus - - - 8 - 8 - - - \ No newline at end of file diff --git a/zeus-common/pom.xml b/zeus-common/pom.xml index 541d3c59..772384f4 100644 --- a/zeus-common/pom.xml +++ b/zeus-common/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 @@ -30,7 +31,7 @@ io.ebean querybean-generator - 12.9.3 + 12.13.1 com.google.guava @@ -49,7 +50,7 @@ true - io.ebean.tile:enhancement:12.9.3 + io.ebean.tile:enhancement:12.11.3 diff --git a/zeus-common/src/main/java/com/zmops/iot/constant/Constants.java b/zeus-common/src/main/java/com/zmops/iot/constant/Constants.java new file mode 100644 index 00000000..c28b4a42 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/constant/Constants.java @@ -0,0 +1,19 @@ +package com.zmops.iot.constant; + +public class Constants { + + public static final int SEC_PER_MIN = 60; + public static final int SEC_PER_HOUR = 3600; + public static final int SEC_PER_DAY = 86400; + public static final int SEC_PER_WEEK = 604800; + public static final int SEC_PER_MONTH = 2592000; + public static final int SEC_PER_YEAR = 31536000; + + public static final String DATE_TIME_FORMAT_SECONDS = "yyyy-MM-dd HH:mm:ss"; + + public static final Integer ARGUS_UNITS_ROUNDOFF_UPPER_LIMIT = 2; + + + public static final Integer ITEM_CONVERT_WITH_UNITS = 0; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/constant/ConstantsContext.java b/zeus-common/src/main/java/com/zmops/iot/constant/ConstantsContext.java index 4c5aeb7d..d809174c 100644 --- a/zeus-common/src/main/java/com/zmops/iot/constant/ConstantsContext.java +++ b/zeus-common/src/main/java/com/zmops/iot/constant/ConstantsContext.java @@ -199,7 +199,7 @@ public static String getJwtSecret() { * 获取系统地密钥过期时间(单位:秒) */ public static Long getJwtSecretExpireSec() { - Long defaultSecs = 86400L; + Long defaultSecs = 86400L; String systemReleaseVersion = (String) CONSTNTS_HOLDER.get("ZEUS_JWT_SECRET_EXPIRE"); if (ToolUtil.isEmpty(systemReleaseVersion)) { log.error("jwt密钥存在空值!常量名称:ZEUS_JWT_SECRET_EXPIRE,采用默认值:1天" + TIPS_END); diff --git a/zeus-common/src/main/java/com/zmops/iot/dict/AbstractDictMap.java b/zeus-common/src/main/java/com/zmops/iot/dict/AbstractDictMap.java index b24252e9..e6ce667a 100644 --- a/zeus-common/src/main/java/com/zmops/iot/dict/AbstractDictMap.java +++ b/zeus-common/src/main/java/com/zmops/iot/dict/AbstractDictMap.java @@ -24,7 +24,7 @@ */ public abstract class AbstractDictMap { - protected HashMap dictory = new HashMap<>(); + protected HashMap dictory = new HashMap<>(); protected HashMap fieldWarpperDictory = new HashMap<>(); public AbstractDictMap() { diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/BaseDto.java b/zeus-common/src/main/java/com/zmops/iot/domain/BaseDto.java deleted file mode 100644 index 779887ca..00000000 --- a/zeus-common/src/main/java/com/zmops/iot/domain/BaseDto.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.zmops.iot.domain; - -public interface BaseDto { - - -} \ No newline at end of file diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/BaseEntity.java b/zeus-common/src/main/java/com/zmops/iot/domain/BaseEntity.java index edf0bc0c..dcd82267 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/BaseEntity.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/BaseEntity.java @@ -5,6 +5,7 @@ import io.ebean.annotation.WhenModified; import io.ebean.annotation.WhoCreated; import io.ebean.annotation.WhoModified; +import lombok.Data; import javax.persistence.MappedSuperclass; import java.time.LocalDateTime; @@ -13,6 +14,7 @@ * @author nantian created at 2021/7/30 20:37 */ @MappedSuperclass +@Data public abstract class BaseEntity extends Model { @WhenCreated @@ -63,4 +65,9 @@ public interface Get { public interface MassRemove { } + /** + * 数据校验组:状态 + */ + public interface Status { + } } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/alarm/AlarmMessage.java b/zeus-common/src/main/java/com/zmops/iot/domain/alarm/AlarmMessage.java index fcb1d01e..b75ebacb 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/alarm/AlarmMessage.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/alarm/AlarmMessage.java @@ -1,4 +1,3 @@ - package com.zmops.iot.domain.alarm; import lombok.AllArgsConstructor; @@ -14,14 +13,14 @@ @NoArgsConstructor @AllArgsConstructor public class AlarmMessage { - private int scopeId; - private String scope; - private String name; - private String id0; - private String id1; - private String ruleName; - private String alarmMessage; - private long startTime; - private transient int period; + private int scopeId; + private String scope; + private String name; + private String id0; + private String id1; + private String ruleName; + private String alarmMessage; + private long startTime; + private transient int period; private transient boolean onlyAsCondition; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/alarm/MediaTypeSetting.java b/zeus-common/src/main/java/com/zmops/iot/domain/alarm/MediaTypeSetting.java index 27fb053f..6e6ebcb1 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/alarm/MediaTypeSetting.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/alarm/MediaTypeSetting.java @@ -23,4 +23,6 @@ public class MediaTypeSetting { private String template; private String webhooks; + + private Long tenantId; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/alarm/Problem.java b/zeus-common/src/main/java/com/zmops/iot/domain/alarm/Problem.java new file mode 100644 index 00000000..fa86ffa5 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/alarm/Problem.java @@ -0,0 +1,37 @@ +package com.zmops.iot.domain.alarm; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Table(name = "problem") +@Entity +public class Problem { + + @Id + private Long eventId; + + private Long objectId; + + private LocalDateTime clock; + + private LocalDateTime rClock; + + private String name; + + private Integer acknowledged; + + private Integer severity; + + private String deviceId; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/ApiParam.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/ApiParam.java new file mode 100644 index 00000000..d4c96cf7 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/ApiParam.java @@ -0,0 +1,28 @@ +package com.zmops.iot.domain.device; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class ApiParam { + + @NotNull + private List params; + @NotBlank + private String deviceId; + + @Data + public static class Params{ + + @NotBlank + private String deviceAttrKey; + @NotBlank + private String deviceAttrValue; + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java index 23aed28f..f16ed9d6 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/Device.java @@ -1,15 +1,16 @@ package com.zmops.iot.domain.device; -import com.zmops.iot.constant.IdTypeConsts; import com.zmops.iot.domain.BaseEntity; import io.ebean.annotation.Aggregation; +import io.ebean.annotation.TenantId; +import io.ebean.annotation.WhoCreated; import lombok.Data; import lombok.EqualsAndHashCode; import javax.persistence.Entity; -import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; +import java.time.LocalDateTime; /** * @author yefei @@ -21,8 +22,7 @@ public class Device extends BaseEntity { @Id - @GeneratedValue(generator = IdTypeConsts.ID_SNOW) - private Long deviceId; + private String deviceId; private String name; @@ -36,6 +36,18 @@ public class Device extends BaseEntity { private String zbxId; + private String addr; + + private String position; + + private Integer online; + + private Long tenantId; + + private Long proxyId; + + private LocalDateTime latestOnline; + @Aggregation("count(*)") Long totalCount; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceGroup.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceGroup.java index 94a49b48..43d2de86 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceGroup.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceGroup.java @@ -27,4 +27,5 @@ public class DeviceGroup extends BaseEntity { String remark; + private Long tenantId; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java new file mode 100644 index 00000000..e1de7321 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceOnlineReport.java @@ -0,0 +1,33 @@ +package com.zmops.iot.domain.device; + +import lombok.*; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode +@Data +@Table(name = "device_online_report") +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeviceOnlineReport { + + @Id + private Long id; + + private String createTime; + + private Long online; + + private Long offline; + + private Integer type; + + private Long tenantId; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceServiceMethod.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceServiceMethod.java new file mode 100644 index 00000000..e6cdfb8d --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/DeviceServiceMethod.java @@ -0,0 +1,26 @@ +package com.zmops.iot.domain.device; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@Data +@Entity +@Table(name = "device_service_method") +public class DeviceServiceMethod { + private String deviceId; + + private String url; + + private String method; + + private String ip; + + private Integer port; + + private String topic; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/DevicesGroups.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/DevicesGroups.java index 5a8e32e0..0073135e 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/DevicesGroups.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/DevicesGroups.java @@ -20,7 +20,7 @@ public class DevicesGroups { @Id private Long id; - private Long deviceId; + private String deviceId; private Long deviceGroupId; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java new file mode 100644 index 00000000..338b8c76 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/EventTriggerRecord.java @@ -0,0 +1,32 @@ +package com.zmops.iot.domain.device; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@Data +@Table(name = "event_trigger_record") +@Entity +public class EventTriggerRecord { + @Id + private Long id; + + private LocalDateTime createTime; + + private String eventName; + + private String eventValue; + + private String deviceId; + + private Long tenantId; + + private String key; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java new file mode 100644 index 00000000..ed036573 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/ScenesTriggerRecord.java @@ -0,0 +1,32 @@ +package com.zmops.iot.domain.device; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@Data +@Table(name = "scenes_trigger_record") +@Entity +public class ScenesTriggerRecord { + @Id + private Long id; + + private LocalDateTime createTime; + + private String ruleName; + + private Long ruleId; + + private Long tenantId; + + private String triggerType; + + private Long triggerUser; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java new file mode 100644 index 00000000..69cd584b --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/ServiceExecuteRecord.java @@ -0,0 +1,39 @@ +package com.zmops.iot.domain.device; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Table(name = "service_execute_record") +@Entity +public class ServiceExecuteRecord { + + @Id + private Long id; + + private LocalDateTime createTime; + + private String serviceName; + + private String deviceId; + + private String param; + + private Long tenantId; + + private String executeType; + + private Long executeUser; + + private Long executeRuleId; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/device/Tag.java b/zeus-common/src/main/java/com/zmops/iot/domain/device/Tag.java index 013e391f..c2aac102 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/device/Tag.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/device/Tag.java @@ -1,14 +1,11 @@ package com.zmops.iot.domain.device; -import com.zmops.iot.constant.IdTypeConsts; import com.zmops.iot.domain.BaseEntity; import lombok.*; import javax.persistence.Entity; -import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; -import java.sql.PreparedStatement; /** * @author yefei @@ -25,7 +22,7 @@ public class Tag extends BaseEntity { @Id private Long id; - private Long sid; + private String sid; private String tag; diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/MailParam.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MailParam.java new file mode 100644 index 00000000..9cc60950 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MailParam.java @@ -0,0 +1,50 @@ +package com.zmops.iot.domain.messages; + + +import com.zmops.iot.domain.messages.MailSetting; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +/** + * @author yefei + **/ +@Data +public class MailParam { + @NotNull + private String host; + @NotNull + private Integer port; + @NotNull + private String account; + @NotNull + private String password; + @NotNull + private String sender; + private Integer ssl; + private Integer tls; + @NotNull(groups = Test.class) + private String receiver; + @NotNull + private String severity; + @NotNull + private Integer silent; + + public interface Test { + } + + + public MailSetting getSettings() { + return MailSetting.builder() + .host(host) + .password(password) + .port(port) + .account(account) + .sender(sender) + .ssl(ssl) + .tls(tls) + .severity(severity) + .silent(silent) + .build(); + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/MailSetting.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MailSetting.java new file mode 100644 index 00000000..359c80b6 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MailSetting.java @@ -0,0 +1,41 @@ +package com.zmops.iot.domain.messages; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "mail_setting") +public class MailSetting { + + @Id + private Integer id; + private String host; + private Integer port; + private String account; + private String password; + private String sender; + private Integer ssl; + private Integer tls; + private String severity; + private Integer silent; + private Long tenantId; + + + public boolean sslAvailable() { + return ssl != null && ssl == 1; + } + + public boolean tlsAvailable() { + return tls != null && tls == 1; + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/MessageBody.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MessageBody.java new file mode 100644 index 00000000..0574c523 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/MessageBody.java @@ -0,0 +1,33 @@ +package com.zmops.iot.domain.messages; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author: yefei + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MessageBody { + private String msg; + private String type; + private List to; + private Map body; + private boolean persist = false; + + + public void addBody(String k, Object v) { + if (this.body == null) { + this.body = new HashMap<>(); + } + this.body.put(k, v); + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java new file mode 100644 index 00000000..964e531b --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/Messages.java @@ -0,0 +1,29 @@ +package com.zmops.iot.domain.messages; + + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + */ + +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "messages") +public class Messages { + @Id + private Integer id; + private Integer classify; + private String title; + private String content; + private Long clock; + private String module; + private Integer readed; + private Long userId; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeRecord.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeRecord.java new file mode 100644 index 00000000..4be249bb --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeRecord.java @@ -0,0 +1,34 @@ +package com.zmops.iot.domain.messages; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; +import java.time.LocalDateTime; + +/** + * @author yefei + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "notice_record") +public class NoticeRecord { + @Id + private Integer recordId; + private Long userId; + private String problemId; + private Integer noticeType; + private String noticeStatus; + private String noticeMsg; + private LocalDateTime creatTime; + private String alarmInfo; + private String receiveAccount; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeResult.java b/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeResult.java new file mode 100644 index 00000000..0d4e24bf --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/messages/NoticeResult.java @@ -0,0 +1,63 @@ +package com.zmops.iot.domain.messages; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author yefei + **/ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class NoticeResult { + private NoticeStatus status; + private String msg; + + /** + * 告警信息 + */ + private String alarmInfo; + /** + * 接收账号 + */ + private String receiveAccount; + + + public static NoticeResult skipped() { + return NoticeResult.builder() + .status(NoticeStatus.skipped).build(); + } + + public static NoticeResult success() { + return NoticeResult.builder() + .status(NoticeStatus.success).build(); + } + + public static NoticeResult success(String alarmInfo, String receiveAccount) { + return NoticeResult.builder() + .status(NoticeStatus.success). + alarmInfo(alarmInfo). + receiveAccount(receiveAccount).build(); + } + + public static NoticeResult failed(String error) { + return NoticeResult.builder() + .status(NoticeStatus.failed) + .msg(error).build(); + } + + public static NoticeResult failed(String error, String alarmInfo, String receiveAccount) { + return NoticeResult.builder() + .status(NoticeStatus.failed). + alarmInfo(alarmInfo). + receiveAccount(receiveAccount) + .msg(error).build(); + } + + public enum NoticeStatus { + skipped, success, failed; + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/Product.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/Product.java index 7f793713..ab347c69 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/Product.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/Product.java @@ -4,7 +4,9 @@ import lombok.Data; import lombok.EqualsAndHashCode; -import javax.persistence.*; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; /** * @author nantian created at 2021/8/3 20:08 @@ -37,4 +39,8 @@ public class Product extends BaseEntity { private String zbxId; + private Long tenantId; + + private String icon; + } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java index ee5acdbc..53efd83d 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttribute.java @@ -1,5 +1,6 @@ package com.zmops.iot.domain.product; +import com.fasterxml.jackson.annotation.JsonProperty; import com.zmops.iot.domain.BaseEntity; import lombok.Data; import lombok.EqualsAndHashCode; @@ -7,11 +8,11 @@ import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; +import java.util.Objects; /** * @author nantian created at 2021/8/5 13:03 */ - @EqualsAndHashCode(callSuper = false) @Data @Entity @@ -21,6 +22,7 @@ public class ProductAttribute extends BaseEntity { @Id private Long attrId; //属性ID + @JsonProperty("attrName") private String name; // 属性名称 private String key; // 属性唯一Key @@ -35,9 +37,15 @@ public class ProductAttribute extends BaseEntity { private Long depAttrId; - private Long productId; // 产品ID + private String productId; // 产品ID private String zbxId; // Zabbix itemId private Long templateId;//继承的ID + + private Integer delay; + + private String unit; + + private String valuemapid; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java new file mode 100644 index 00000000..2ecfc4aa --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductAttributeEvent.java @@ -0,0 +1,54 @@ +package com.zmops.iot.domain.product; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author nantian created at 2021/8/5 13:03 + */ + +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "product_attribute_event") +public class ProductAttributeEvent extends BaseEntity { + + @Id + private Long attrId; //属性ID + + @JsonProperty("attrName") + private String name; // 属性名称 + + private String key; // 属性唯一Key + + private String units; // 单位 0 3 才有 + + private Byte eventLevel; + + private String remark; // 备注 + + private String valueType; + + private String productId; // 产品ID + + private String zbxId; // Zabbix itemId + + private Long templateId;//继承的ID + + private String source; // 来源 + + private Integer delay; + + private String unit; + + private String valuemapid; + + private Long depAttrId; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java new file mode 100644 index 00000000..0600ecc9 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEvent.java @@ -0,0 +1,34 @@ +package com.zmops.iot.domain.product; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author nantian created at 2021/9/15 1:02 + */ + +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "product_event") +public class ProductEvent extends BaseEntity { + + @Id + private Long eventRuleId; + private String eventRuleName; + private String eventLevel; + private String expLogic; + private String classify; + private String eventNotify; + private Long tenantId; + private String status; + private String remark; + private Integer taskId; + private Integer triggerType; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java new file mode 100644 index 00000000..fbf61f7c --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventExpression.java @@ -0,0 +1,39 @@ +package com.zmops.iot.domain.product; + +import com.zmops.iot.constant.IdTypeConsts; +import io.ebean.Model; +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author nantian created at 2021/9/15 16:50 + *

+ * 触发器 表达式 函数 + */ + +@Data +@Entity +@Table(name = "product_event_expression") +public class ProductEventExpression extends Model { + + @Id + @GeneratedValue(generator = IdTypeConsts.ID_SNOW) + private Long eventExpId; + + private Long eventRuleId; + private String function; + private String scope; + private String condition; + private String value; + private String deviceId; + private String productAttrKey; + private String unit; + private Long productAttrId; + private String productAttrType; + private String period; + private String attrValueType; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java new file mode 100644 index 00000000..9ec8a1e1 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventRelation.java @@ -0,0 +1,32 @@ +package com.zmops.iot.domain.product; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author nantian created at 2021/8/11 17:02 + */ + +@Getter +@Setter +@Entity +@Table(name = "product_event_relation") +public class ProductEventRelation { + + @Id + private Long id; + + private Long eventRuleId; + + private String relationId; + + private String zbxId; + + private String inherit; + private String status; + private String remark; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventService.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventService.java new file mode 100644 index 00000000..79468965 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventService.java @@ -0,0 +1,22 @@ +package com.zmops.iot.domain.product; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "product_event_service") +public class ProductEventService { + + private Long eventRuleId; + private Long serviceId; + private String deviceId; + private String executeDeviceId; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventTimeInterval.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventTimeInterval.java new file mode 100644 index 00000000..799ff527 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductEventTimeInterval.java @@ -0,0 +1,30 @@ +package com.zmops.iot.domain.product; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + *

+ * 触发器 时间 表达式 函数 + */ + +@Data +@Entity +@Table(name = "product_event_time_interval") +public class ProductEventTimeInterval { + + @Id + private Long eventTimeId; + + private Long eventRuleId; + + private String startTime; + + private String endTime; + + private String dayOfWeeks; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java new file mode 100644 index 00000000..e5c62ae0 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductService.java @@ -0,0 +1,25 @@ +package com.zmops.iot.domain.product; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "product_service") +public class ProductService { + @Id + private Long id; + + private String name; + private String mark; + private String remark; + private String async; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java new file mode 100644 index 00000000..857bd45d --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceParam.java @@ -0,0 +1,27 @@ +package com.zmops.iot.domain.product; + +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "product_service_param") +public class ProductServiceParam { + + @Id + private Long id; + private Long serviceId; + private String name; + private String key; + private String remark; + private String value; + private String deviceId; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java new file mode 100644 index 00000000..ca4f60c8 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductServiceRelation.java @@ -0,0 +1,29 @@ +package com.zmops.iot.domain.product; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author nantian created at 2021/8/11 17:02 + */ + +@Getter +@Setter +@Entity +@Table(name = "product_service_relation") +public class ProductServiceRelation { + + @Id + private Long id; + + private Long serviceId; + + private String relationId; + + private String inherit; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java index dcebc208..f66daf44 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunction.java @@ -19,15 +19,24 @@ public class ProductStatusFunction extends BaseEntity { @Id - private Long triggerId; + private Long ruleId; - private Integer zbxId; + private String ruleFunction; - private String ruleType; + private Long attrId; - private String fuleFunction; - - private String ruleValue; + private String ruleCondition; private Integer ruleStatus; + + private String ruleFunctionRecovery; + + private String ruleConditionRecovery; + + private Long attrIdRecovery; + + private String unit; + + private String unitRecovery; + } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java new file mode 100644 index 00000000..6ff7f206 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductStatusFunctionRelation.java @@ -0,0 +1,35 @@ +package com.zmops.iot.domain.product; + +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author nantian created at 2021/8/11 17:02 + */ + +@Getter +@Setter +@Entity +@Table(name = "product_status_function_relation") +public class ProductStatusFunctionRelation { + + @Id + private Long id; + + private Long ruleId; + + private String relationId; + + private String inherit; + + // 离线触发器ID + private String zbxId; + + // 上线触发器ID + private String zbxIdRecovery; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductType.java b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductType.java index a21abeaa..2b2d3756 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductType.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/product/ProductType.java @@ -1,5 +1,6 @@ package com.zmops.iot.domain.product; +import com.zmops.iot.domain.BaseEntity; import lombok.Data; import lombok.EqualsAndHashCode; @@ -14,7 +15,7 @@ @Data @Entity @Table(name = "product_type") -public class ProductType { +public class ProductType extends BaseEntity { @Id private Long id; @@ -25,4 +26,6 @@ public class ProductType { private String name; private String remark; + + private Long tenantId; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolComponent.java b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolComponent.java new file mode 100644 index 00000000..593e843d --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolComponent.java @@ -0,0 +1,30 @@ +package com.zmops.iot.domain.protocol; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "protocol_component") +public class ProtocolComponent extends BaseEntity { + + @Id + private Long protocolComponentId; + + private String name; + private String effectProxy; + private String status; + private String remark; + private Long tenantId; + private String fileName; + private String uniqueId; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGateway.java b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGateway.java new file mode 100644 index 00000000..7f198383 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGateway.java @@ -0,0 +1,31 @@ +package com.zmops.iot.domain.protocol; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "protocol_gateway") +public class ProtocolGateway extends BaseEntity { + + @Id + private Long protocolGatewayId; + + private String name; + private String protocolType; + private Long protocolServiceId; + private Long protocolComponentId; + private String status; + private String remark; + private Long tenantId; + private Integer qos; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGatewayMqtt.java b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGatewayMqtt.java new file mode 100644 index 00000000..e79e6e52 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolGatewayMqtt.java @@ -0,0 +1,27 @@ +package com.zmops.iot.domain.protocol; + +import com.zmops.iot.domain.BaseEntity; +import lombok.*; + +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "protocol_gateway_mqtt") +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProtocolGatewayMqtt { + + private Long protocolGatewayId; + + private Long protocolComponentId; + + private String topic; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolService.java b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolService.java new file mode 100644 index 00000000..809654a1 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/protocol/ProtocolService.java @@ -0,0 +1,33 @@ +package com.zmops.iot.domain.protocol; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "protocol_service") +public class ProtocolService extends BaseEntity { + + @Id + private Long protocolServiceId; + + private String name; + private String effectProxy; + private String protocolType; + private String remark; + private Long tenantId; + private String url; + private String ip; + private Integer port; + private Integer msgLength; + private String clientId; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/proxy/Proxy.java b/zeus-common/src/main/java/com/zmops/iot/domain/proxy/Proxy.java new file mode 100644 index 00000000..f9535cbe --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/proxy/Proxy.java @@ -0,0 +1,30 @@ +package com.zmops.iot.domain.proxy; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@EqualsAndHashCode(callSuper = false) +@Data +@Entity +@Table(name = "proxy") +public class Proxy extends BaseEntity { + + @Id + private Long id; + + private String name; + private String mode = "1"; + private String address; + private String remark; + private Integer tlsAccept = 1; + private String zbxId; + private Long tenantId; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/schedule/Task.java b/zeus-common/src/main/java/com/zmops/iot/domain/schedule/Task.java new file mode 100644 index 00000000..05cac402 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/schedule/Task.java @@ -0,0 +1,43 @@ +package com.zmops.iot.domain.schedule; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Getter; +import lombok.Setter; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author nantian created at 2021/11/13 11:23 + */ + +@Getter +@Setter +@Table(name = "task_info") +@Entity +public class Task extends BaseEntity { + + + @Id + @Column(name = "id", nullable = false) + private Integer id; + + + private String scheduleType; // 调度类型 + private String scheduleConf; // 调度配置,值含义取决于调度类型 + private String misfireStrategy; // 调度过期策略 + + private Integer taskTimeout; + + private Integer taskFailRetryCount; + + private String triggerStatus; // 调度状态:DISABLE-停止,ENABLE-运行 + private Long triggerLastTime; // 上次调度时间 + private Long triggerNextTime; + + private String remark; + + private String executorParam; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/Session.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/Session.java new file mode 100644 index 00000000..2f7ffb23 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/Session.java @@ -0,0 +1,30 @@ +package com.zmops.iot.domain.sys; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@Data +@Table(name = "session") +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Session { + + @Id + private Integer id; + + private String key; + + private String value; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysConfig.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysConfig.java index 2c887528..6bd2bfc2 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysConfig.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysConfig.java @@ -56,4 +56,9 @@ public class SysConfig extends BaseEntity implements Serializable { */ private String remark; + /** + * 是否可修改 ENABLE DISABLE + */ + private String status; + } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysDict.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysDict.java index 197199ca..d6635b17 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysDict.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysDict.java @@ -1,6 +1,5 @@ package com.zmops.iot.domain.sys; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.zmops.iot.constant.IdTypeConsts; import com.zmops.iot.domain.BaseEntity; import lombok.Data; diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysLoginLog.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysLoginLog.java index 9146b575..ac1f9a3b 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysLoginLog.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysLoginLog.java @@ -33,4 +33,6 @@ public class SysLoginLog { String message; String ipAddress; + + private Long tenantId; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysMenu.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysMenu.java index 4778e3eb..45ba9964 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysMenu.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysMenu.java @@ -77,4 +77,9 @@ public class SysMenu extends BaseEntity { * 菜单状态(字典) */ private String status; + + /** + * 是否超级管理员菜单 + */ + private String adminFlag; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysOperationLog.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysOperationLog.java index 7de7793b..e927a25f 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysOperationLog.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysOperationLog.java @@ -37,4 +37,6 @@ public class SysOperationLog { private String message; private LocalDateTime createTime; + + private Long tenantId; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysUser.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysUser.java index e28b4728..3ae56645 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysUser.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysUser.java @@ -42,4 +42,9 @@ public class SysUser extends BaseEntity { String zbxToken; String zbxId; + + private Long tenantId; + + String remark; + } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysUserGroup.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysUserGroup.java index 533b183d..da23b534 100644 --- a/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysUserGroup.java +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/SysUserGroup.java @@ -29,4 +29,5 @@ public class SysUserGroup extends BaseEntity { String remark; + private Long tenantId; } diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/sys/Token.java b/zeus-common/src/main/java/com/zmops/iot/domain/sys/Token.java new file mode 100644 index 00000000..d2400e21 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/sys/Token.java @@ -0,0 +1,39 @@ +package com.zmops.iot.domain.sys; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +/** + * @author yefei + **/ +@Data +@Table(name = "token") +@Entity +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Token { + + @Id + private Integer tokenId; + + private String name; + + private String description; + + private Long userId; + + private String token; + + private String status; + + private Long expiresAt; + + private String account; +} diff --git a/zeus-common/src/main/java/com/zmops/iot/domain/tenant/TenantInfo.java b/zeus-common/src/main/java/com/zmops/iot/domain/tenant/TenantInfo.java new file mode 100644 index 00000000..ce154ef6 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/domain/tenant/TenantInfo.java @@ -0,0 +1,56 @@ +package com.zmops.iot.domain.tenant; + + +import com.zmops.iot.constant.IdTypeConsts; +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + + +@EqualsAndHashCode(callSuper = false) +@Data +@Table(name = "tenant_info") +@Entity +public class TenantInfo extends BaseEntity { + + + /** + * 主键id + */ + @Id + @GeneratedValue(generator = IdTypeConsts.ID_SNOW) + private Long tenantId; + + /** + * 租户名称 + */ + private String name; + + /** + * 备注 + */ + private String remark; + + /** + * 租户管理员账号 + */ + private String account; + + /** + * 租户联系人 + */ + private String contact; + + /** + * 租户联系人电话 + */ + private String phone; + + private String status; + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/enums/CommonTimeUnit.java b/zeus-common/src/main/java/com/zmops/iot/enums/CommonTimeUnit.java new file mode 100644 index 00000000..1bbff6fe --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/enums/CommonTimeUnit.java @@ -0,0 +1,54 @@ +/** + * Copyright 2018-2020 stylefeng & fengshuonan (https://gitee.com/stylefeng) + *

+ * 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 + *

+ * http://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.zmops.iot.enums; + +import lombok.Getter; + +/** + * 公共状态 + * + * @author fengshuonan + */ +public enum CommonTimeUnit { + + S("s", "秒"), + M("m", "分"), + H("h", "小时"), + D("d", "天"); + + @Getter + String code; + @Getter + String message; + + CommonTimeUnit(String code, String message) { + this.code = code; + this.message = message; + } + + public static String getDescription(String status) { + if (status == null) { + return ""; + } else { + for (CommonTimeUnit s : CommonTimeUnit.values()) { + if (s.getCode().equals(status)) { + return s.getMessage(); + } + } + return ""; + } + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/enums/InheritStatus.java b/zeus-common/src/main/java/com/zmops/iot/enums/InheritStatus.java new file mode 100644 index 00000000..e8029f42 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/enums/InheritStatus.java @@ -0,0 +1,52 @@ +/** + * Copyright 2018-2020 stylefeng & fengshuonan (https://gitee.com/stylefeng) + *

+ * 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 + *

+ * http://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.zmops.iot.enums; + +import lombok.Getter; + +/** + * 是否来自产品 状态 + * + * @author yefei + */ +public enum InheritStatus { + + NO("0", "否"), + YES("1", "是"); + + @Getter + String code; + @Getter + String message; + + InheritStatus(String code, String message) { + this.code = code; + this.message = message; + } + + public static String getDescription(String status) { + if (status == null) { + return ""; + } else { + for (InheritStatus s : InheritStatus.values()) { + if (s.getCode().equals(status)) { + return s.getMessage(); + } + } + return ""; + } + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/enums/SeverityEnum.java b/zeus-common/src/main/java/com/zmops/iot/enums/SeverityEnum.java new file mode 100644 index 00000000..76b2da41 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/enums/SeverityEnum.java @@ -0,0 +1,37 @@ +package com.zmops.iot.enums; + +import lombok.Getter; + +/** + * @author yefei + **/ +@Getter +public enum SeverityEnum { + + INFO("信息", "1"), + WARN("低级", "2"), + ALARM("中级", "3"), + HIGH("高级", "4"), + DISASTER("紧急", "5"); + + String code; + String value; + + SeverityEnum(String code, String value) { + this.code = code; + this.value = value; + } + + public static String getVal(String status) { + if (status == null) { + return ""; + } else { + for (SeverityEnum s : SeverityEnum.values()) { + if (s.getCode().equals(status)) { + return s.getValue(); + } + } + return "0"; + } + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/enums/ValueType.java b/zeus-common/src/main/java/com/zmops/iot/enums/ValueType.java new file mode 100644 index 00000000..0e469e40 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/enums/ValueType.java @@ -0,0 +1,39 @@ +package com.zmops.iot.enums; + +import lombok.Getter; + +/** + * @author yefei + **/ +@Getter +public enum ValueType { + + CHARACTER("character", "字符型"), + NOTSUPPORT("not supported", "不支持的类型"), + LOG("log", "日志型"), + FLOAT("numeric (float)", "单精度型"), + NUMERIC("numeric (unsigned)", "数值型"), + TEXT("text", "文本型"), + AVG("avg", "平均值"); + + String code; + String value; + + ValueType(String code, String value) { + this.code = code; + this.value = value; + } + + public static String getVal(String status) { + if (status == null) { + return ""; + } else { + for (ValueType s : ValueType.values()) { + if (s.getCode().equals(status)) { + return s.getValue(); + } + } + return ""; + } + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/AbstractCache.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/AbstractCache.java index 1e7eda51..9fcb9782 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/AbstractCache.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/AbstractCache.java @@ -4,6 +4,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -66,7 +67,7 @@ public void update(Map values) { try { cache.clear(); cache.putAll(values); - view = Collections.unmodifiableMap(cache); + view = new ConcurrentHashMap<>(cache); } finally { writeLock.unlock(); } diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/DeviceCache.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/DeviceCache.java new file mode 100644 index 00000000..fe27d503 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/DeviceCache.java @@ -0,0 +1,24 @@ +package com.zmops.iot.model.cache; + + +import java.util.Map; +import java.util.Optional; + +/** + * @author yefei + **/ +public class DeviceCache extends AbstractCache { + + public DeviceCache() { + super(); + } + + public void updateDeviceName(Map map) { + update(map); + } + + public String getDeviceName(String id) { + return Optional.ofNullable(get(id)).orElse(null); + } + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductEventCache.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductEventCache.java new file mode 100644 index 00000000..68e087fb --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductEventCache.java @@ -0,0 +1,24 @@ +package com.zmops.iot.model.cache; + + +import java.util.Map; +import java.util.Optional; + +/** + * @author yefei + **/ +public class ProductEventCache extends AbstractCache { + + public ProductEventCache() { + super(); + } + + public void updateTriggerName(Map map) { + update(map); + } + + public String getTriggerName(Long id) { + return Optional.ofNullable(get(id)).orElse(null); + } + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceCache.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceCache.java new file mode 100644 index 00000000..0c7fd827 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceCache.java @@ -0,0 +1,24 @@ +package com.zmops.iot.model.cache; + + +import java.util.Map; +import java.util.Optional; + +/** + * @author yefei + **/ +public class ProductServiceCache extends AbstractCache { + + public ProductServiceCache() { + super(); + } + + public void updateProductService(Map map) { + update(map); + } + + public String getServiceName(Long id) { + return Optional.ofNullable(get(id)).orElse(null); + } + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceParamCache.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceParamCache.java new file mode 100644 index 00000000..5ef6c053 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProductServiceParamCache.java @@ -0,0 +1,27 @@ +package com.zmops.iot.model.cache; + + +import com.zmops.iot.domain.product.ProductServiceParam; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * @author yefei + **/ +public class ProductServiceParamCache extends AbstractCache> { + + public ProductServiceParamCache() { + super(); + } + + public void updateProductServiceParam(Map> map) { + update(map); + } + + public List getServiceParam(Long id) { + return Optional.ofNullable(get(id)).orElse(null); + } + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/ProtocolServiceCache.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProtocolServiceCache.java new file mode 100644 index 00000000..5ceec310 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/ProtocolServiceCache.java @@ -0,0 +1,24 @@ +package com.zmops.iot.model.cache; + + +import java.util.Map; +import java.util.Optional; + +/** + * @author yefei + **/ +public class ProtocolServiceCache extends AbstractCache { + + public ProtocolServiceCache() { + super(); + } + + public void updateName(Map map) { + update(map); + } + + public String getName(Long id) { + return Optional.ofNullable(get(id)).orElse(null); + } + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/TenantNameCache.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/TenantNameCache.java new file mode 100644 index 00000000..4f2b2523 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/TenantNameCache.java @@ -0,0 +1,21 @@ +package com.zmops.iot.model.cache; + +import java.util.Map; +import java.util.Optional; + +/** + * @author yefei + **/ +public class TenantNameCache extends AbstractCache{ + public TenantNameCache() { + super(); + } + + public void updateTenantName(Map map) { + update(map); + } + + public String getTenantName(Long id) { + return Optional.ofNullable(get(id)).orElse(null); + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValue.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValue.java index 1ed0e4ff..31db0d96 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValue.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValue.java @@ -7,6 +7,7 @@ /** * 字典翻译注解 @Repeatable + * @author yefei */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @@ -21,11 +22,11 @@ /** - * 添加的后缀名 + * 翻译后的字段名 * * @return */ - String suffix() default "Name"; + String fieldName(); /** diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java index dd48d22f..e0ce4e41 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/CachedValueFilter.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; -import com.zmops.iot.domain.BaseDto; import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.LocalDateTimeUtils; @@ -21,14 +20,8 @@ */ public class CachedValueFilter extends JsonSerializer { - public final static String SUFFIX = "Name"; - @Override public void serialize(Object object, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { - if (!(object instanceof BaseDto)) { - return; - } - jsonGenerator.writeStartObject(); for (Field field : getAllFields(object.getClass())) { @@ -43,17 +36,19 @@ public void serialize(Object object, JsonGenerator jsonGenerator, SerializerProv if (value == null) { continue; } - CachedValue[] cachedValues = field.getAnnotationsByType(CachedValue.class); - JsonProperty jsonProperties = field.getDeclaredAnnotation(JsonProperty.class); - String fieldName = field.getName(); + CachedValue[] cachedValues = field.getAnnotationsByType(CachedValue.class); + JsonProperty jsonProperties = field.getDeclaredAnnotation(JsonProperty.class); + String fieldName = field.getName(); if (null != jsonProperties) { fieldName = jsonProperties.value(); } if (value instanceof LocalDateTime) { jsonGenerator.writeStringField(fieldName, LocalDateTimeUtils.dateToStr(value.toString())); - } else { + } else if (value instanceof String) { jsonGenerator.writeStringField(fieldName, value.toString()); + } else { + jsonGenerator.writeObjectField(fieldName, value); } if (cachedValues.length == 0) { @@ -65,7 +60,7 @@ public void serialize(Object object, JsonGenerator jsonGenerator, SerializerProv String res = getCachedValue(cachedValue, value); if (res != null) { exists = true; - jsonGenerator.writeStringField(fieldName + Optional.of(cachedValue.suffix()).orElse(SUFFIX), res); + jsonGenerator.writeStringField(cachedValue.fieldName(), res); } else { exists = exists || cachedValue.type().isNullable(); } @@ -110,6 +105,21 @@ private String getCachedValue(CachedValue cachedValue, Object value) { return DefinitionsUtil.getTypeName((long) value); } break; + case Tenant: + if (value instanceof Long) { + return DefinitionsUtil.getTenantName((long) value); + } + break; + case Device: + if (value instanceof String) { + return DefinitionsUtil.getDeviceName((String) value); + } + break; + case ProtocolService: + if (value instanceof Long) { + return DefinitionsUtil.getProtocolServiceName((long) value); + } + break; default: return null; } diff --git a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java index df0f08ae..065c3bf2 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/cache/filter/DicType.java @@ -10,17 +10,20 @@ public enum DicType { SysUserName(false), SysRole, ProdType, + Tenant, + Device, + ProtocolService, Dictionary; @Getter private boolean nullable; - DicType(){ + DicType() { this.nullable = true; } - DicType(boolean nullable){ + DicType(boolean nullable) { this.nullable = nullable; } } diff --git a/zeus-common/src/main/java/com/zmops/iot/model/exception/enums/CoreExceptionEnum.java b/zeus-common/src/main/java/com/zmops/iot/model/exception/enums/CoreExceptionEnum.java index 94290a10..9590d84d 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/exception/enums/CoreExceptionEnum.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/exception/enums/CoreExceptionEnum.java @@ -42,7 +42,8 @@ public enum CoreExceptionEnum implements AbstractBaseExceptionEnum { IO_ERROR(500, "流读取异常"), SERVICE_ERROR(500, "服务器异常"), REMOTE_SERVICE_NULL(404, "远程服务不存在"), - ASYNC_ERROR(5000, "数据在被别人修改,请稍后重试"); + ASYNC_ERROR(5000, "数据在被别人修改,请稍后重试"), + REPEATED_SUBMIT(500,"请勿重复请求"); CoreExceptionEnum(int code, String message) { this.code = code; diff --git a/zeus-common/src/main/java/com/zmops/iot/model/node/TreeNode.java b/zeus-common/src/main/java/com/zmops/iot/model/node/TreeNode.java index 4795f6f6..307f953d 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/node/TreeNode.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/node/TreeNode.java @@ -3,6 +3,7 @@ import com.zmops.iot.util.ToolUtil; import lombok.Data; +import java.time.LocalDateTime; import java.util.List; /** @@ -31,6 +32,8 @@ public class TreeNode implements Tree { */ private String name; + private String tenantName; + /** * URL */ @@ -46,6 +49,10 @@ public class TreeNode implements Tree { */ private Boolean isChecked; + private LocalDateTime createTime; + + private String createUserName; + /** * 子节点 */ diff --git a/zeus-common/src/main/java/com/zmops/iot/model/page/Pager.java b/zeus-common/src/main/java/com/zmops/iot/model/page/Pager.java index d48c7f0d..d740e13d 100644 --- a/zeus-common/src/main/java/com/zmops/iot/model/page/Pager.java +++ b/zeus-common/src/main/java/com/zmops/iot/model/page/Pager.java @@ -16,7 +16,7 @@ @Data public class Pager { - private Integer code = 200; + private Integer code = 200; /** * 请求是否成功 */ diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ArgusMap.java b/zeus-common/src/main/java/com/zmops/iot/util/ArgusMap.java new file mode 100644 index 00000000..835b6365 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/util/ArgusMap.java @@ -0,0 +1,62 @@ +package com.zmops.iot.util; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * HashMap Builder + * + * @author yefei + * @param + * @param + */ +public abstract class ArgusMap implements Serializable { + + private static final long serialVersionUID = 1L; + + public static HashMapBuilder builder() { + return new HashMapBuilder(); + } + + public static LinkedHashMapBuilder linkedHashMapBuilder() { + return new LinkedHashMapBuilder(); + } + + public static class HashMapBuilder { + + private Map t; + + public HashMapBuilder(){ + this.t = new HashMap<>(); + } + + public HashMapBuilder put(K key, V value) { + this.t.put(key, value); + return this; + } + + public Map build() { + return this.t; + } + } + + public static class LinkedHashMapBuilder { + + private Map t; + + public LinkedHashMapBuilder(){ + this.t = new LinkedHashMap<>(); + } + + public LinkedHashMapBuilder put(K key, V value) { + this.t.put(key, value); + return this; + } + + public Map build() { + return this.t; + } + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/util/CommonRegexpResolver.java b/zeus-common/src/main/java/com/zmops/iot/util/CommonRegexpResolver.java new file mode 100644 index 00000000..c5716749 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/util/CommonRegexpResolver.java @@ -0,0 +1,88 @@ +package com.zmops.iot.util; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 通用正则解析器 + * + * @author yefei + */ +public class CommonRegexpResolver { + + /** + * @param regexp 正则表达式 + * @param input 待匹配的字符串 + * @param groupNames 分组名 + * @return + */ + public static Map> resolve(String regexp, String input, List groupNames) { + if (input == null) { + return new HashMap<>(); + } + Multimap res = ArrayListMultimap.create(); + Pattern pattern = Pattern.compile(regexp); + Matcher matcher = pattern.matcher(input); + if (Pattern.matches(regexp, input)) { + while (matcher.find()) { + groupNames.forEach(o -> { + if (matcher.group(o) != null) { + res.put(o, matcher.group(o)); + } + for (int i = 0; i <= matcher.groupCount(); i++) { + res.put(String.valueOf(i), matcher.group(i)); + } + }); + } + } else { + int i = 0; + while (matcher.find()) { + res.put(String.valueOf(i++), matcher.group()); + } + } + return res.asMap(); + } + + public static Map> resolve(String regexp, String input) { + if (input == null) { + return new HashMap>(); + } + Multimap res = ArrayListMultimap.create(); + Pattern pattern = Pattern.compile(regexp); + Matcher matcher = pattern.matcher(input); + if (Pattern.matches(regexp, input)) { + while (matcher.find()) { + for (int i = 0; i <= matcher.groupCount(); i++) { + res.put(i, matcher.group(i)); + } + } + } else { + int i = 0; + while (matcher.find()) { + res.put(i++, matcher.group()); + } + } + return res.asMap(); + } + + + // public static void main(String[] args) { + // final String regexp = + // "^(?[\\-+])?(?(\\d)+)(?[smhdw])?$"; + // Map> matches = + // CommonRegexpResolver.resolve(regexp, "-5m", + // Arrays.asList("sign","number","suffix")); + // matches.entrySet().forEach(o->{ + // System.out.println(o.getKey()+"->"+o.getValue()); + // }); + // } + + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java index 9c41a73a..e71797ca 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/DefinitionsUtil.java @@ -1,12 +1,9 @@ package com.zmops.iot.util; import com.google.common.collect.Table; -import com.zmops.iot.domain.product.ProductType; +import com.zmops.iot.domain.product.ProductServiceParam; import com.zmops.iot.domain.sys.SysUser; -import com.zmops.iot.model.cache.DictionaryCache; -import com.zmops.iot.model.cache.ProductTypeCache; -import com.zmops.iot.model.cache.SysRoleCache; -import com.zmops.iot.model.cache.SysUserCache; +import com.zmops.iot.model.cache.*; import lombok.Getter; import lombok.Setter; @@ -36,6 +33,30 @@ public class DefinitionsUtil { @Setter private static ProductTypeCache productTypeCache = new ProductTypeCache(); + @Getter + @Setter + private static TenantNameCache tenantNameCache = new TenantNameCache(); + + @Getter + @Setter + private static ProductServiceCache productServiceCache = new ProductServiceCache(); + + @Getter + @Setter + private static ProductServiceParamCache productServiceParamCache = new ProductServiceParamCache(); + + @Getter + @Setter + private static DeviceCache deviceCache = new DeviceCache(); + + @Getter + @Setter + private static ProductEventCache productEventCache = new ProductEventCache(); + + @Getter + @Setter + private static ProtocolServiceCache protocolServiceCache = new ProtocolServiceCache(); + public static void updateDictionaries(Table dictionarys) { dictionaryCache.updateDictionaries(dictionarys); } @@ -57,11 +78,59 @@ public static SysUser getSysUser(Long sysUserId) { return sysUserCache.getSysUser(sysUserId); } - public static void updateProductType(Map map) { + public static void updateProductType(Map map) { productTypeCache.updateProductType(map); } public static String getTypeName(long value) { return productTypeCache.getTypeName(value); } + + public static void updateTenantName(Map map) { + tenantNameCache.updateTenantName(map); + } + + public static String getTenantName(long value) { + return tenantNameCache.getTenantName(value); + } + + public static void updateServiceCache(Map map) { + productServiceCache.updateProductService(map); + } + + public static String getServiceName(long value) { + return productServiceCache.getServiceName(value); + } + + public static void updateServiceParamCache(Map> paramMap) { + productServiceParamCache.updateProductServiceParam(paramMap); + } + + public static List getServiceParam(long value) { + return productServiceParamCache.getServiceParam(value); + } + + public static void updateDeviceCache(Map map) { + deviceCache.updateDeviceName(map); + } + + public static String getDeviceName(String value) { + return deviceCache.getDeviceName(value); + } + + public static void updateProductEventCache(Map map) { + productEventCache.updateTriggerName(map); + } + + public static String getTriggerName(Long value) { + return productEventCache.getTriggerName(value); + } + + public static void updateProtocolServiceCache(Map map) { + protocolServiceCache.updateName(map); + } + + public static String getProtocolServiceName(Long value) { + return protocolServiceCache.getName(value); + } } diff --git a/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java b/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java index 05052388..91b8ad14 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/LocalDateTimeUtils.java @@ -43,6 +43,11 @@ public static Long getSecondsByTime(LocalDateTime time) { return time.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond(); } + // 获取指定日期的秒 + public static Long getSecondsByStr(String date) { + return getSecondsByTime(dateToStamp(date)); + } + /** * 根据秒获取时间 * @@ -108,7 +113,7 @@ public static long betweenTwoTime(LocalDateTime startTime, LocalDateTime endTime // 获取一天的开始时间,2017,7,22 00:00 public static LocalDateTime getDayStart(LocalDateTime time) { - return time.withHour(0).withMinute(0).withSecond(0).withNano(0); + return time.withHour(0).withMinute(0).withSecond(1).withNano(0); } // 获取一天的结束时间,2017,7,22 23:59:59.999999999 @@ -119,7 +124,7 @@ public static LocalDateTime getDayEnd(LocalDateTime time) { /* * 时间戳转 LocalDateTime */ - public static LocalDateTime convertDateToLocalDateTime(Long time) { + public static LocalDateTime convertDateToLocalDateTime(Integer time) { if (time == null) { return null; } @@ -136,6 +141,16 @@ public static String convertTimeToString(Long time, String pattern) { return LocalDateTimeUtils.formatTime(LocalDateTimeUtils.getLDTByMilliSeconds(time), pattern); } + /* + * 秒转 String + */ + public static String convertTimeToString(Integer time, String pattern) { + if (time == null) { + return null; + } + return LocalDateTimeUtils.formatTime(LocalDateTimeUtils.getLDTBySeconds(time), pattern); + } + public static LocalDateTime dateToStamp(String str) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { @@ -178,6 +193,6 @@ public static LocalDateTime getThisWeekMonday() { } public static void main(String[] args) { - System.out.println(formatTime(dateToStamp("2021-08-18T14:25:38.059"))); + System.out.println(formatTime(getDayStart(LocalDateTime.now()))); } } diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ObjectUtils.java b/zeus-common/src/main/java/com/zmops/iot/util/ObjectUtils.java new file mode 100644 index 00000000..2a5d37bc --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/util/ObjectUtils.java @@ -0,0 +1,679 @@ +package com.zmops.iot.util; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import com.zmops.iot.constant.Constants; +import org.springframework.util.StringUtils; + +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; +import java.io.*; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.sql.Date; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.util.*; +import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ObjectUtils { + + public static List> digitUnits = new ArrayList<>(); + + /** + * 获取指定实体对象中字段的值 + * + * @param o 实体对象 + * @param c 实体类 + * @param fieldName 字段名称 + * @return + */ + public static Object getFieldValue(Object o, Class c, String fieldName) { + // 获取类中的全部定义字段 + Field[] fields = c.getDeclaredFields(); + // 循环遍历字段,获取字段相应的属性值 + for (Field field : fields) { + // 设置字段可见,就可以用get方法获取属性值。 + field.setAccessible(true); + try { + if (fieldName.equals(field.getName())) { + return field.get(o); + } + } catch (Exception e) { + return null; + } + } + return null; + } + + public static Object getFieldValue(Object o, String fieldName) { + return getFieldValue(o, o.getClass(), fieldName); + } + + public static void setFieldValue(Object o, Class c, String fieldName, Object value) { + Field[] fields = c.getDeclaredFields(); + for (Field field : fields) { + field.setAccessible(true); + if (field.getName().equals(fieldName)) { + try { + PropertyDescriptor pd = new PropertyDescriptor(fieldName, c); + Method wM = pd.getWriteMethod(); + wM.invoke(o, value); + } catch (IntrospectionException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException e) { + e.printStackTrace(); + } + + } + } + } + + public static void setFieldValue(Object o, String fieldName, Object value) { + setFieldValue(o, o.getClass(), fieldName, value); + } + + /** + * 实体对象转成Map       + * + * @param obj 实体对象     + * @return       + */ + public static Map object2Map(Object obj) { + Map map = new HashMap<>(); + if (obj == null) { + return map; + } + Field[] fields = obj.getClass().getDeclaredFields(); + try { + for (Field field : fields) { + field.setAccessible(true); + map.put(field.getName(), field.get(obj)); + } + } catch (Exception e) { + e.printStackTrace(); + } + return map; + } + + /** + * 检查IP地址是否合法 + * + * @param ipAddress + * @return + */ + public static boolean isIpv4(String ipAddress) { + + String ip = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\." + + "(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + + "(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + + "(00?\\d|1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$"; + + Pattern pattern = Pattern.compile(ip); + Matcher matcher = pattern.matcher(ipAddress); + return matcher.matches(); + + } + + /** + * 检查秘钥是否合法 + * + * @param psk + * @return + */ + public static boolean validatePSK(String psk) { + String pskpatern = "^([0-9a-f]{2})+$"; + Pattern pattern = Pattern.compile(pskpatern); + Matcher matcher = pattern.matcher(psk); + return matcher.matches(); + } + + /** + * 检查字符串是不是数字 + * + * @param str + * @return + */ + public static boolean isInteger(String str) { + Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$"); + return pattern.matcher(str).matches(); + } + + /** + * 根据数字生成字母 + * + * @param + * @return + */ + public static String num2letter(int number) { + int start = 65; + int base = 26; + String str = ""; + int level = 0; + do { + if (level++ > 0) { + number--; + } + int remainder = number % base; + number = (number - remainder) / base; + str = (char) (start + remainder) + str; + } while (0 != number); + return str; + } + + /** + * 返回两个list的去重并集 + * + * @param output + * @param extend + * @return + */ + public static List outputExtend(List output, List extend) { + + if (output.size() == 1 && output.get(0).equals("extend")) { + return output; + } + Set result = new HashSet<>(); + for (R o : output) { + result.add(o); + } + for (R e : extend) { + result.add(e); + } + return new ArrayList<>(result); + } + + /** + * 返回两个list的交集 + * + * @param array1 + * @param array2 + * @return + */ + public static List arrayIntersectKey(List array1, List array2) { + array1.retainAll(array2); + return array1; + } + + /** + * Convert timestamp to string representation. Return 'Never' if 0. + * + * @return + */ + public static String date2str(String format, String seconds) { + if (seconds == null || seconds.isEmpty() || seconds.equals("null")) { + return ""; + } + if (format == null || format.isEmpty()) { + format = "yyyy-MM-dd HH:mm:ss"; + } + SimpleDateFormat sdf = new SimpleDateFormat(format); + return sdf.format(new Date(Long.valueOf(seconds + "000"))); + } + + public static String convertUnits(String value, String units) { + int convert = Constants.ITEM_CONVERT_WITH_UNITS; + @SuppressWarnings("unused") + boolean byteStep = false, pow = false, ignoreMillisec = false, length = false; + if ("unixtime".equals(units)) { + return date2str(Constants.DATE_TIME_FORMAT_SECONDS, value); + } + // special processing of uptime + if ("uptime".equals(units)) { + return convertUnitsUptime(value); + } + + if ("s".equals(units)) { + return convertUnitsS(value, false); + } + // black list of units that should have no multiplier prefix (K, M, G + // etc) applied + List blackList = Lists.newArrayList("%", "ms", "rpm", "RPM"); + + // add to the blacklist if unit is prefixed with '!' + if (units != null && units.startsWith("!")) { + units = units.substring(1); + blackList.add(units); + } + if (blackList.contains(units) || !StringUtils.hasText(units)) { + if (!CommonRegexpResolver.resolve("\\.\\d+$", "0.01").isEmpty()) { + BigDecimal decimal = new BigDecimal(value); + value = decimal + .setScale(decimal.abs().compareTo(new BigDecimal(0.01)) == 1 ? 2 : 6, RoundingMode.HALF_UP) + .toString(); + } + value = value.replaceAll("^([\\-0-9]+)(\\.)([0-9]*?)[0]+$", "$1$2$3"); + if (value.endsWith(".")) { + value = value.substring(0, value.length() - 1); + } + return value + " " + units; + } + int step; + // if one or more items is B or Bps, then Y-scale use base 8 and + // calculated in bytes + if (byteStep) { + step = 1024; + } else { + switch (units) { + case "Bps": + case "B": + step = 1024; + convert = convert != 0 ? convert : 1; + break; + case "b": + case "bps": + convert = convert != 0 ? convert : 1; + default: + step = 1000; + break; + } + } + + BigDecimal abs = new BigDecimal(value).abs(); + if (abs.compareTo(new BigDecimal(1)) == -1) { + value = new BigDecimal(value).setScale(2, RoundingMode.HALF_UP).toString(); + if (length && abs.compareTo(new BigDecimal(0)) != 0) { + + } + return (value + " " + units).trim(); + } + + List steps = Arrays.asList("", "K", "M", "G", "T", "P", "E", "Z", "Y"); + BigDecimal values = new BigDecimal(value); + int i = 0; + while (values.divide(new BigDecimal(step)).longValue() > 1 && i < steps.size()) { + values = values.divide(new BigDecimal(step)); + i++; + } + if (values.intValue() == step) { + values = values.divide(new BigDecimal(step)); + i++; + } + value = values.setScale(10, RoundingMode.HALF_UP).toString().replaceAll("^([\\-0-9]+)(\\.)([0-9]*?)[0]+$", + "$1$2$3"); + if (value.endsWith(".")) { + value = value.substring(0, value.length() - 1); + } + if (value.contains(".")) { + int idx = value.lastIndexOf('.') + 3; + if (idx < value.length()) { + value = value.substring(0, idx); + } + } + return value + " " + steps.get(i) + units; + + } + + // @SuppressWarnings("unused") + // String step = ""; + // int convert = Constants.ITEM_CONVERT_WITH_UNITS; + // // special processing for unix timestamps + // if ("unixtime".equals(units)) { + // return date2str(Constants.DATE_TIME_FORMAT_SECONDS, value); + // } + // // special processing of uptime + // if ("uptime".equals(units)) { + // return convertUnitsUptime(value); + // } + // + // if ("s".equals(units)) { + // return convertUnitsS(value, false); + // } + // // black list of units that should have no multiplier prefix (K, M, G + // // etc) applied + // List blackList = Arrays.asList("% ", "ms ", "rpm ", "RPM "); + // // add to the blacklist if unit is prefixed with '!' + // if (!StringUtils.isBlank(units) && units.startsWith("!")) { + // blackList.add(units.substring(0, 1)); + // } + // // any other unit + // if (blackList.contains(units) || StringUtils.isBlank(units)) { + // if (CommonRegexpResolver.resolve("\\.\\d*$", value).size() > 0) { + // String format = Math.abs(Double.parseDouble( + // value)) >= Constants.ARGUS_UNITS_ROUNDOFF_THRESHOLD ? "%." + // + Constants.ARGUS_UNITS_ROUNDOFF_UPPER_LIMIT + // + "f" : "%." + // + Constants.ARGUS_UNITS_ROUNDOFF_LOWER_LIMIT + // + "f"; + // value = formt(format, value); + // } + // value = value.replaceAll("^([\\-0-9]+)(\\.)([0-9]*)[0]+$", "$1$2$3"); + // value = value.split("\\.")[0]; + // return value.trim(); + // } + // switch (units) { + // case "Bps": + // case "B": + // step = Constants.ARGUS_KIBIBYTE; + // break; + // case "b": + // case "bps": + // default: + // step = "1000"; + // } + // double abs = 0.0; + // if (Double.parseDouble(value) < 0) { + // abs = Math.abs(Double.parseDouble(value)); + // } else { + // abs = Double.parseDouble(value); + // } + // if (abs < 1) { + // value = String.valueOf(round(value, + // Constants.ARGUS_UNITS_ROUNDOFF_MIDDLE_LIMIT)); + // return value + " " + units; + // } + // + // if (isEmpty(digitUnits)) { + // initDigitUnits(); + // for (Map map : digitUnits) { + // map.put("value", String.valueOf((long) Math.pow(1024, (int) + // map.get("pow")))); + // } + // } + // Map valUnit = new HashMap<>(); + // valUnit.put("pow", 0); + // valUnit.put("short", ""); + // valUnit.put("value", value); + // if (Double.parseDouble(value) == 0) { + // for (Map map : digitUnits) { + // if (abs >= Double.parseDouble(value)) { + // valUnit = map; + // } else { + // break; + // } + // } + // } + // if (round(value, Constants.ARGUS_UNITS_ROUNDOFF_MIDDLE_LIMIT).intValue() + // > 0) { + // double newVal = new BigDecimal(formt("%.10f", value)) + // .divide(new BigDecimal(formt("%.10f", + // String.valueOf(valUnit.get("value")))), + // Constants.ARGUS_PRECISION_10, + // BigDecimal.ROUND_HALF_UP) + // .doubleValue(); + // valUnit.put("value", newVal); + // } else { + // valUnit.put("value", 0); + // } + // String desc = ""; + // switch (convert) { + // case 0: + // units = units.trim(); + // case 1: + // desc = String.valueOf(valUnit.get("short")); + // break; + // } + // value = String.valueOf(round(String.valueOf(valUnit.get("value")), + // Constants.ARGUS_UNITS_ROUNDOFF_UPPER_LIMIT)) + // .replaceAll("^([\\-0-9]+)(\\.)([0-9]*)[0]+$", "$1$2$3"); + // + // value = value.split("\\.")[0]; + // + // if (Double.parseDouble(value) == 0) { + // value = "0"; + // } + // return value + " " + desc + units; + // } + + @SuppressWarnings("unused") + private static void initDigitUnits() { + Map obj = new HashMap<>(); + obj.put("pow", 0); + obj.put("short", ""); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 1); + obj.put("short", "K"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 2); + obj.put("short", "M"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 3); + obj.put("short", "G"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 4); + obj.put("short", "T"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 5); + obj.put("short", "P"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 6); + obj.put("short", "E"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 7); + obj.put("short", "Z"); + digitUnits.add(obj); + obj = new HashMap<>(); + obj.put("pow", 8); + obj.put("short", "Y"); + digitUnits.add(obj); + } + + + /** + * 将时间段转换为可读格式。 使用以下单位:年、月、日、小时、分钟、秒和毫秒。 仅显示三个最高单位:y m d,m d h,d h mm等等。 + * 如果某个值等于零,则忽略该值。例如,如果周期为1y0m4d,它将显示为 1Y 4D,非1Y 0M 4D或1Y 4D H。 + * + * @param value + * @param ignore_millisec + * @return + */ + private static String convertUnitsS(String value, boolean ignore_millisec) { + BigDecimal secs = round(new BigDecimal(value).multiply(BigDecimal.valueOf(1000)), + Constants.ARGUS_UNITS_ROUNDOFF_UPPER_LIMIT).divide(BigDecimal.valueOf(1000)); + long sec = secs.longValue(); + String str = ""; + if (sec < 0) { + sec = -sec; + str = "-"; + } + int[] steps = new int[]{ + Constants.SEC_PER_YEAR, Constants.SEC_PER_MONTH, + Constants.SEC_PER_DAY, Constants.SEC_PER_HOUR, + Constants.SEC_PER_MIN + }; + List unitsEn = new ArrayList<>(units.keySet()); + Map values = new LinkedHashMap<>(); + for (int s = 0; s < steps.length; s++) { + int v = steps[s]; + if (sec < v) { + continue; + } + long n = sec / v; + sec %= v; + values.put(unitsEn.get(s), n); + } + if (sec != 0) { + values.put("s", sec); + } + if (!ignore_millisec) { + values.put("ms", secs.subtract(BigDecimal.valueOf(secs.longValue())).multiply(BigDecimal.valueOf(1000)).longValue()); + } + int size = 0; + for (Entry ent : values.entrySet()) { + str += " " + ent.getValue() + units.get(ent.getKey()); + if (++size == 3) { + break; + } + } + return !StringUtils.hasText(str) ? "0" : str.trim(); + } + + public static void main(String[] args) { + System.out.println(convertUnitsS("86411.1", false)); + } + + private final static Map units = ArgusMap.linkedHashMapBuilder().put("y", "年").put("m", "月") + .put("d", "天").put("h", "小时").put("mm", "分").put("s", "秒").put("ms", "毫秒").build(); + + private static String convertUnitsUptime(String value) { + int secs = round(value, 0).intValue(); + if (secs < 0) { + value = "-"; + secs = -secs; + } else { + value = ""; + } + int days = new BigDecimal(secs).divide(new BigDecimal(Constants.SEC_PER_DAY), RoundingMode.DOWN).intValue(); + secs -= days * Constants.SEC_PER_DAY; + + int hours = new BigDecimal(secs).divide(new BigDecimal(Constants.SEC_PER_HOUR), RoundingMode.DOWN).intValue(); + secs -= hours * Constants.SEC_PER_HOUR; + + int mins = new BigDecimal(secs).divide(new BigDecimal(Constants.SEC_PER_MIN), RoundingMode.DOWN).intValue(); + secs -= mins * Constants.SEC_PER_MIN; + + if (days != 0) { + value += days + "天,"; + } + value += LocalDateTimeUtils.formatTime(LocalDateTime.now().withHour(hours).withMinute(mins).withSecond(secs), + "HH:mm:ss"); + return value; + } + + /** + * 计算差值 并保留digits位小数 + * + * @param last + * @param prev + * @param digits + * @return + */ + public static double bcsub(String last, String prev, int digits) { + double lastVal = Double.parseDouble(last); + double prevVal = Double.parseDouble(prev); + + double res = lastVal - prevVal; + if (digits == 0) { + return res; + } else { + BigDecimal bg = new BigDecimal(res); + double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); + return f1; + } + } + + /** + * 格式化value 保留r位小数并四舍五入 + * + * @param value + * @param r + * @return + */ + public static BigDecimal round(String value, int r) { + if (!StringUtils.hasText(value)) { + return new BigDecimal("0"); + } + BigDecimal bvalue = new BigDecimal(value); + return round(bvalue, r); + } + + public static BigDecimal round(BigDecimal value, int r) { + return value.divide(new BigDecimal("1"), r, BigDecimal.ROUND_HALF_UP); + } + + /** + * 根据format 格式化value 小数点位数 + * + * @param format + * @param value + * @return + */ + public static String formt(String format, String value) { + Formatter fmt = new Formatter(); + value = fmt.format(format, Double.parseDouble(value)).toString(); + fmt.close(); + return value; + } + + public static List deepCopy(List src) throws IOException, ClassNotFoundException { + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(byteOut); + out.writeObject(src); + ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); + ObjectInputStream in = new ObjectInputStream(byteIn); + @SuppressWarnings("unchecked") + List dest = (List) in.readObject(); + return dest; + } + + public static Map deepCopy(Map src) throws IOException, ClassNotFoundException { + ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); + ObjectOutputStream out = new ObjectOutputStream(byteOut); + out.writeObject(src); + ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); + ObjectInputStream in = new ObjectInputStream(byteIn); + @SuppressWarnings("unchecked") + Map dest = (Map) in.readObject(); + return dest; + } + + /** + * 根据map键值的交集 返回map1中的值 + * + * @param map + * @param map2 + * @return + */ + public static Map mapIntersectKey(Map map, Map map2) { + Set bigMapKey = map.keySet(); + Set smallMapKey = map2.keySet(); + Set differenceSet = Sets.intersection(bigMapKey, smallMapKey); + Map result = Maps.newHashMap(); + for (Key key : differenceSet) { + result.put(key, map.get(key)); + } + return result; + } + + /** + * 根据map键值的差集 返回map1中的值 + * + * @param map + * @param map2 + * @return + */ + public static Map mapDiffKey(Map map, Map map2) { + Set bigMapKey = map.keySet(); + Set smallMapKey = map2.keySet(); + Set differenceSet = Sets.difference(bigMapKey, smallMapKey); + Map result = Maps.newHashMap(); + for (Key key : differenceSet) { + result.put(key, map.get(key)); + } + return result; + } + + public static String substr_replace(String source, String replacement, int start, Integer length) { + if (length == null) { + return new StringBuilder(source.substring(0, start)).append(replacement).toString(); + } + // 如果start <0 表示从source结尾处n个开始替换 + if (start < 0) { + start = source.length() + start; + } + if (length >= 0) { + return new StringBuilder(source.substring(0, start)).append(replacement) + .append(source.substring(start + length)).toString(); + } + return new StringBuilder(source.substring(0, start)).append(replacement) + .append(source.substring(source.length() + length)).toString(); + + } + + public static String substr_replace(String source, String replacement, int start) { + return substr_replace(source, replacement, start, null); + } + +} diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ParseUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/ParseUtil.java new file mode 100644 index 00000000..e9123c89 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/util/ParseUtil.java @@ -0,0 +1,68 @@ +package com.zmops.iot.util; + +import java.math.BigDecimal; +import java.text.CharacterIterator; +import java.text.DecimalFormat; +import java.text.StringCharacterIterator; + +/** + * @author yefei + **/ +public class ParseUtil { + + + public static void main(String[] args) { + System.out.println(getCommaFormat("2097180.19677")); + } + + //每3位中间添加逗号的格式化显示 + public static String getCommaFormat(String value) { + if (ToolUtil.isEmpty(value)) { + return "0"; + } + return getFormat(",###.##", new BigDecimal(value)); + } + + //自定义数字格式方法 + public static String getFormat(String style, BigDecimal value) { + DecimalFormat df = new DecimalFormat(); + df.applyPattern(style); + return df.format(value.doubleValue()); + } + + public static String getFormatFloat(String value) { + if (!isFloat(value)) { + return value; + } + return String.format("%1.2f", Float.parseFloat(value)); + } + + public static boolean isFloat(String value) { + try { + Float.parseFloat(value); + + if (!value.contains(".")) { + return false; + } + } catch (Exception e) { + return false; + } + return true; + } + + public static String formatLagSize(String size) { + if (ToolUtil.isEmpty(size)) { + return "0"; + } + long bytes = Long.parseLong(size); + if (-1000 < bytes && bytes < 1000) { + return bytes + " B"; + } + CharacterIterator ci = new StringCharacterIterator("kMGTPE"); + while (bytes <= -999_950 || bytes >= 999_950) { + bytes /= 1000; + ci.next(); + } + return String.format("%.1f %cB", bytes / 1000.0, ci.current()); + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/util/SpringUtils.java b/zeus-common/src/main/java/com/zmops/iot/util/SpringUtils.java new file mode 100644 index 00000000..034243b3 --- /dev/null +++ b/zeus-common/src/main/java/com/zmops/iot/util/SpringUtils.java @@ -0,0 +1,72 @@ +package com.zmops.iot.util; + + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.stereotype.Component; + +/** + * @Author nantian + * @Date 2/20/2020 0020 11:09 AM + * @Email nantian@zmops.com + * @Version 1.0 + */ +@Component +public class SpringUtils implements BeanFactoryPostProcessor { + + private static ConfigurableListableBeanFactory beanFactory; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + SpringUtils.beanFactory = beanFactory; + } + + /** + * 获取对象 + */ + public static Object getBean(String name) { + return beanFactory.getBean(name); + } + + /** + * 获取对象 + */ + @SuppressWarnings("unchecked") + public static T getBean(String name, Class clz) { + T result = (T) beanFactory.getBean(name); + return result; + } + + /** + * 获取对象 + */ + public static T getBean(Class clz) { + T result = (T) beanFactory.getBean(clz); + return result; + } + + /** + * 判断是否包含对象 + */ + public static boolean containsBean(String name) { + return beanFactory.containsBean(name); + } + + /** + * 创建对象到spring context + */ + @SuppressWarnings("unchecked") + public static T createBean(Class clz) { + T result = (T) beanFactory.createBean(clz, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true); + return result; + } + + /** + * 删除对象 + */ + public static void destroyBean(String beanName) { + beanFactory.destroyScopedBean(beanName); + } +} diff --git a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java index 321313be..bf4ca33e 100644 --- a/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java +++ b/zeus-common/src/main/java/com/zmops/iot/util/ToolUtil.java @@ -5,8 +5,10 @@ import cn.hutool.core.date.DateUtil; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.exception.enums.CoreExceptionEnum; +import org.apache.logging.log4j.core.util.CronExpression; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; import org.springframework.core.env.Environment; import java.io.IOException; @@ -17,12 +19,25 @@ import java.security.MessageDigest; import java.text.SimpleDateFormat; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.function.Predicate; /** * @author nantian created at 2021/7/29 17:03 */ public class ToolUtil { + /** + * 如果对象不是数字类型 就加上双引号返回 + */ + public static String addQuotes(String value) { + if (isNum(value)) { + return value; + } + return "\\\\\"" + value + "\\\\\""; + } + /** * 默认密码盐长度 */ @@ -34,9 +49,9 @@ public class ToolUtil { * @author fengshuonan */ public static String getRandomString(int length) { - String base = "abcdefghijklmnopqrstuvwxyz0123456789"; - Random random = new Random(); - StringBuffer sb = new StringBuffer(); + String base = "abcdefghijklmnopqrstuvwxyz0123456789"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); for (int i = 0; i < length; i++) { int number = random.nextInt(base.length()); sb.append(base.charAt(number)); @@ -60,9 +75,9 @@ public static String md5Hex(String password, String salt) { */ public static String md5Hex(String str) { try { - MessageDigest md5 = MessageDigest.getInstance("MD5"); - byte[] bs = md5.digest(str.getBytes()); - StringBuffer md5StrBuff = new StringBuffer(); + MessageDigest md5 = MessageDigest.getInstance("MD5"); + byte[] bs = md5.digest(str.getBytes()); + StringBuffer md5StrBuff = new StringBuffer(); for (int i = 0; i < bs.length; i++) { if (Integer.toHexString(0xFF & bs[i]).length() == 1) md5StrBuff.append("0").append(Integer.toHexString(0xFF & bs[i])); @@ -94,9 +109,9 @@ public static String removeWhiteSpace(String value) { * @author stylefeng */ public static String getCreateTimeBefore(int seconds) { - long currentTimeInMillis = Calendar.getInstance().getTimeInMillis(); - Date date = new Date(currentTimeInMillis - seconds * 1000); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + long currentTimeInMillis = Calendar.getInstance().getTimeInMillis(); + Date date = new Date(currentTimeInMillis - seconds * 1000); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return sdf.format(date); } @@ -127,7 +142,7 @@ public static String getExceptionMsg(Throwable e) { public static String getApplicationName() { try { Environment environment = SpringContextHolder.getApplicationContext().getEnvironment(); - String property = environment.getProperty("spring.application.name"); + String property = environment.getProperty("spring.application.name"); if (ToolUtil.isNotEmpty(property)) { return property; } else { @@ -225,9 +240,14 @@ public static Integer toInt(Object val) { */ public static boolean isNum(Object obj) { try { - Integer.parseInt(obj.toString()); + Long.parseLong(obj.toString()); } catch (Exception e) { - return false; + try { + Double.parseDouble(obj.toString()); + }catch (Exception el){ + return false; + } + return true; } return true; } @@ -397,5 +417,53 @@ public static boolean isAllEmpty(Object... os) { } return true; } + + /** + * 将一个对象转换为另一个对象 + * + * @param 要转换的对象 + * @param 转换后的类 + * @param oriList 要转换的对象 + * @param castClass 转换后的对象 + * @return 转换后的对象 + */ + public static List convertBean(List oriList, Class castClass) { + if (isEmpty(oriList)) { + return Collections.emptyList(); + } + List resList = new ArrayList<>(); + oriList.forEach(orimodel -> { + try { + T2 returnModel = castClass.newInstance(); + BeanUtils.copyProperties(orimodel, returnModel); + resList.add(returnModel); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + }); + return resList; + } + + public static boolean validCron(String cron){ + //String regEx = "(((^([0-9]|[0-5][0-9])(\\,|\\-|\\/){1}([0-9]|[0-5][0-9]))|^([0-9]|[0-5][0-9])|^(\\* ))((([0-9]|[0-5][0-9])(\\,|\\-|\\/){1}([0-9]|[0-5][0-9]) )|([0-9]|[0-5][0-9]) |(\\* ))((([0-9]|[01][0-9]|2[0-3])(\\,|\\-|\\/){1}([0-9]|[01][0-9]|2[0-3]) )|([0-9]|[01][0-9]|2[0-3]) |(\\* ))((([0-9]|[0-2][0-9]|3[01])(\\,|\\-|\\/){1}([0-9]|[0-2][0-9]|3[01]) )|(([0-9]|[0-2][0-9]|3[01]) )|(\\? )|(\\* )|(([1-9]|[0-2][0-9]|3[01])L )|([1-7]W )|(LW )|([1-7]\\#[1-4] ))((([1-9]|0[1-9]|1[0-2])(\\,|\\-|\\/){1}([1-9]|0[1-9]|1[0-2]) )|([1-9]|0[1-9]|1[0-2]) |(\\* ))(([1-7](\\,|\\-|\\/){1}[1-7])|([1-7])|(\\?)|(\\*)|(([1-7]L)|([1-7]\\#[1-4]))))|(((^([0-9]|[0-5][0-9])(\\,|\\-|\\/){1}([0-9]|[0-5][0-9]) )|^([0-9]|[0-5][0-9]) |^(\\* ))((([0-9]|[0-5][0-9])(\\,|\\-|\\/){1}([0-9]|[0-5][0-9]) )|([0-9]|[0-5][0-9]) |(\\* ))((([0-9]|[01][0-9]|2[0-3])(\\,|\\-|\\/){1}([0-9]|[01][0-9]|2[0-3]) )|([0-9]|[01][0-9]|2[0-3]) |(\\* ))((([0-9]|[0-2][0-9]|3[01])(\\,|\\-|\\/){1}([0-9]|[0-2][0-9]|3[01]) )|(([0-9]|[0-2][0-9]|3[01]) )|(\\? )|(\\* )|(([1-9]|[0-2][0-9]|3[01])L )|([1-7]W )|(LW )|([1-7]\\#[1-4] ))((([1-9]|0[1-9]|1[0-2])(\\,|\\-|\\/){1}([1-9]|0[1-9]|1[0-2]) )|([1-9]|0[1-9]|1[0-2]) |(\\* ))(([1-7](\\,|\\-|\\/){1}[1-7] )|([1-7] )|(\\? )|(\\* )|(([1-7]L )|([1-7]\\#[1-4]) ))((19[789][0-9]|20[0-9][0-9])\\-(19[789][0-9]|20[0-9][0-9])))"; + //String tests = "0 0 0 L * ?"; + return CronExpression.isValidExpression(cron); + } + + public static boolean validDeviceName(String content){ + return content.contains("\\") || content.contains("/"); + } + /** + * List> 根据相同key的值去重 + * @param keyExtractor + * @param + * @return + */ + public static Predicate distinctByKey(Function keyExtractor) { + Map seen = new ConcurrentHashMap<>(); + return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; + } } diff --git a/zeus-core/pom.xml b/zeus-core/pom.xml index 815d6586..9ab69a7b 100644 --- a/zeus-core/pom.xml +++ b/zeus-core/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/context/LoginContext.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/context/LoginContext.java index 16e2cb8b..c71eed99 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/context/LoginContext.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/context/LoginContext.java @@ -2,8 +2,6 @@ import com.zmops.iot.core.auth.model.LoginUser; -import java.util.List; - /** * 当前登录用户信息获取的接口 * diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/entrypoint/JwtAuthenticationEntryPoint.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/entrypoint/JwtAuthenticationEntryPoint.java index 96fdee69..e5deff52 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/entrypoint/JwtAuthenticationEntryPoint.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/entrypoint/JwtAuthenticationEntryPoint.java @@ -31,15 +31,19 @@ public void commence(HttpServletRequest request, AuthenticationException authException) throws IOException { // GET请求跳转到主页 - if ("get".equalsIgnoreCase(request.getMethod()) && !request.getHeader("Accept").contains("application/json")) { + if ("get".equalsIgnoreCase(request.getMethod()) + && !request.getHeader("Accept").contains("application/json")) { + response.sendRedirect(request.getContextPath() + "/global/sessionError"); + } else { // POST请求返回json response.setCharacterEncoding("utf-8"); response.setContentType("application/json"); ErrorResponseData errorResponseData = new ErrorResponseData( - AuthExceptionEnum.NO_PAGE_ERROR.getCode(), AuthExceptionEnum.NO_PAGE_ERROR.getMessage()); + AuthExceptionEnum.NO_PAGE_ERROR.getCode(), + AuthExceptionEnum.NO_PAGE_ERROR.getMessage()); response.getWriter().write(JSON.toJSONString(errorResponseData)); } diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/AuthException.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/AuthException.java index b97baf19..7ff97b38 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/AuthException.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/AuthException.java @@ -13,7 +13,7 @@ public class AuthException extends RuntimeException { private Integer code; - private String errorMessage; + private String errorMessage; public AuthException() { super("认证失败!"); diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/PermissionException.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/PermissionException.java index 1a875e86..384d7ef1 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/PermissionException.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/exception/PermissionException.java @@ -14,7 +14,7 @@ public class PermissionException extends RuntimeException { private Integer code; - private String errorMessage; + private String errorMessage; public PermissionException() { super(NO_PERMISSION.getMessage()); diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/CommonFilter.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/CommonFilter.java new file mode 100644 index 00000000..28de7fc6 --- /dev/null +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/CommonFilter.java @@ -0,0 +1,29 @@ +package com.zmops.iot.core.auth.filter; + +import lombok.extern.slf4j.Slf4j; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.util.Objects; + +/** + * @author yefei + **/ +@Slf4j +public class CommonFilter implements Filter { + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + CommonHttpServletRequestWrapper customHttpServletRequestWrapper = null; + try { + HttpServletRequest req = (HttpServletRequest)request; + customHttpServletRequestWrapper = new CommonHttpServletRequestWrapper(req); + }catch (Exception e){ + log.warn("commonHttpServletRequestWrapper Error:", e); + } + + chain.doFilter((Objects.isNull(customHttpServletRequestWrapper) ? request : customHttpServletRequestWrapper), response); + } +} + diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/CommonHttpServletRequestWrapper.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/CommonHttpServletRequestWrapper.java new file mode 100644 index 00000000..8aac1217 --- /dev/null +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/CommonHttpServletRequestWrapper.java @@ -0,0 +1,93 @@ +package com.zmops.iot.core.auth.filter; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.*; + +/** + * @author yefei + **/ +public class CommonHttpServletRequestWrapper extends HttpServletRequestWrapper { + + + private String body; + + public CommonHttpServletRequestWrapper(HttpServletRequest request) { + super(request); + StringBuilder stringBuilder = new StringBuilder(); + BufferedReader bufferedReader = null; + InputStream inputStream = null; + try { + inputStream = request.getInputStream(); + if (inputStream != null) { + bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + char[] charBuffer = new char[128]; + int bytesRead = -1; + while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { + stringBuilder.append(charBuffer, 0, bytesRead); + } + } else { + stringBuilder.append(""); + } + } catch (IOException ex) { + + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + if (bufferedReader != null) { + try { + bufferedReader.close(); + } + catch (IOException e) { + e.printStackTrace(); + } + } + } + body = stringBuilder.toString(); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes()); + ServletInputStream servletInputStream = new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + @Override + public boolean isReady() { + return false; + } + @Override + public void setReadListener(ReadListener readListener) { + } + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + }; + return servletInputStream; + + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(this.getInputStream())); + } + + public String getBody() { + return this.body; + } + + public void setBody(String body) { + this.body = body; + } +} diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/CommonInterceptor.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/CommonInterceptor.java new file mode 100644 index 00000000..8ca5fece --- /dev/null +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/CommonInterceptor.java @@ -0,0 +1,75 @@ +package com.zmops.iot.core.auth.filter; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.core.auth.context.LoginContextHolder; +import com.zmops.iot.core.auth.util.FixLengthLinkedList; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.exception.enums.CoreExceptionEnum; +import com.zmops.iot.util.ToolUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.ArrayUtils; +import org.springframework.core.MethodParameter; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @author yefei + **/ +@Slf4j +public class CommonInterceptor implements HandlerInterceptor { + +// FixLengthLinkedList list = new FixLengthLinkedList<>(10); + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + if (!(handler instanceof HandlerMethod)) { + return true; + } + +// if (request instanceof CommonHttpServletRequestWrapper) { +// CommonHttpServletRequestWrapper requestWrapper = (CommonHttpServletRequestWrapper) request; +// int code = requestWrapper.getBody().hashCode(); +// log.debug("*************************" + code); +// if (list.contains(code)) { +// throw new ServiceException(CoreExceptionEnum.REPEATED_SUBMIT); +// } +// list.add(code); +// } + HandlerMethod handlerMethod = (HandlerMethod) handler; + pushTenantId2Body(request, handlerMethod); + + return true; + } + + private void pushTenantId2Body(HttpServletRequest request, HandlerMethod handlerMethod) { + try { + + MethodParameter[] methodParameters = handlerMethod.getMethodParameters(); + if (ArrayUtils.isEmpty(methodParameters)) { + return; + } + for (MethodParameter methodParameter : methodParameters) { + Class clazz = methodParameter.getParameterType(); + + if (request instanceof CommonHttpServletRequestWrapper) { + CommonHttpServletRequestWrapper requestWrapper = (CommonHttpServletRequestWrapper) request; + String body = requestWrapper.getBody(); + JSONObject param = JSONObject.parseObject(body); + if (param == null || ToolUtil.isNotEmpty(param.getString("tenantId"))) { + return; + } + param.put("tenantId", LoginContextHolder.getContext().getUser().getTenantId()); + requestWrapper.setBody(JSON.toJSONString(param)); + } + + } + } catch (Exception e) { + log.warn("fill userInfo to request body Error ", e); + } + } +} diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/JwtAuthorizationTokenFilter.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/JwtAuthorizationTokenFilter.java index cda66bee..23341bfe 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/JwtAuthorizationTokenFilter.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/JwtAuthorizationTokenFilter.java @@ -5,7 +5,6 @@ import com.zmops.iot.core.auth.jwt.JwtTokenUtil; import com.zmops.iot.core.auth.util.TokenUtil; import com.zmops.iot.util.ToolUtil; - import io.jsonwebtoken.JwtException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java index a346c96d..d3b88e3b 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/filter/NoneAuthedResources.java @@ -11,9 +11,8 @@ public class NoneAuthedResources { * 前端接口资源 */ public static final String[] FRONTEND_RESOURCES = { - "/assets/**", - "/favicon.ico", - "/activiti-editor/**" + "/static/**", + "/favicon.ico" }; @@ -22,7 +21,9 @@ public class NoneAuthedResources { */ public static final String[] NO_AUTH_API = { "/login", - "/rest/device/webhook" + "/device/status", + "/device/service", + "/device/problem" }; @@ -46,7 +47,7 @@ public class NoneAuthedResources { "/rest/login", // 登录接口放开过滤 "/login", - "/hello", + "/device/service/execute", //oauth登录的接口 "/oauth/render/*", diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/jwt/JwtTokenUtil.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/jwt/JwtTokenUtil.java index b53c40ca..3854fe24 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/jwt/JwtTokenUtil.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/jwt/JwtTokenUtil.java @@ -45,7 +45,7 @@ public class JwtTokenUtil { * 生成token,根据userId和默认过期时间 */ public static String generateToken(JwtPayLoad jwtPayLoad) { - Long expiredSeconds = getExpireSeconds(); + Long expiredSeconds = getExpireSeconds(); final Date expirationDate = new Date(System.currentTimeMillis() + expiredSeconds * 1000); return generateToken(String.valueOf(jwtPayLoad.getUserId()), expirationDate, jwtPayLoad.toMap()); } @@ -96,7 +96,7 @@ public static Date getExpirationDateFromToken(String token) { public static String generateToken(String userId, Date exppiredDate, Map claims) { final Date createdDate = new Date(); - String secret = getJwtSecret(); + String secret = getJwtSecret(); if (claims == null) { return Jwts.builder() diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java index 407cd6a3..96d94c29 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/model/LoginUser.java @@ -36,6 +36,16 @@ public class LoginUser implements UserDetails, Serializable { private static final long serialVersionUID = 1L; + public LoginUser() { + super(); + } + + public LoginUser(Long id, String token) { + super(); + this.id = id; + this.zbxToken = token; + } + /** * 用户主键ID */ @@ -56,6 +66,10 @@ public class LoginUser implements UserDetails, Serializable { */ private String email; + /** + * 用户组 + */ + private Long userGroupId; /** * 角色集 @@ -82,6 +96,11 @@ public class LoginUser implements UserDetails, Serializable { */ private Set permissions; + /** + * 租户ID + */ + private Long tenantId; + /** * zabbix token * diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/util/FixLengthLinkedList.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/util/FixLengthLinkedList.java new file mode 100644 index 00000000..1b648d23 --- /dev/null +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/util/FixLengthLinkedList.java @@ -0,0 +1,33 @@ +package com.zmops.iot.core.auth.util; + +import java.util.LinkedList; + +/** + * @author yefei + **/ +public class FixLengthLinkedList extends LinkedList { + + private int capacity; + + public FixLengthLinkedList(int capacity) { + super(); + this.capacity = capacity; + } + + @Override + public boolean add(T t) { + if (size() + 1 > capacity) { + super.removeFirst(); + } + return super.add(t); + } + + public static void main(String[] args) { + FixLengthLinkedList linkedList = new FixLengthLinkedList<>(3); + for (int i = 0; i < 100; i++) { + linkedList.add(i + ""); + } + + linkedList.forEach(l -> System.out.println(l)); + } +} diff --git a/zeus-core/src/main/java/com/zmops/iot/core/auth/util/TokenUtil.java b/zeus-core/src/main/java/com/zmops/iot/core/auth/util/TokenUtil.java index 0ef37120..5a025f51 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/auth/util/TokenUtil.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/auth/util/TokenUtil.java @@ -22,8 +22,8 @@ public class TokenUtil { */ public static String getToken() { - String authToken = null; - HttpServletRequest request = HttpContext.getRequest(); + String authToken = null; + HttpServletRequest request = HttpContext.getRequest(); //权限校验的头部 String tokenHeader = getTokenHeaderName(); diff --git a/zeus-core/src/main/java/com/zmops/iot/core/util/FileUtil.java b/zeus-core/src/main/java/com/zmops/iot/core/util/FileUtil.java index e571b591..824e4904 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/util/FileUtil.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/util/FileUtil.java @@ -25,8 +25,8 @@ public static byte[] toByteArray(String filename) { log.error("文件未找到!" + filename); throw new ServiceException(CoreExceptionEnum.FILE_NOT_FOUND); } - FileChannel channel = null; - FileInputStream fs = null; + FileChannel channel = null; + FileInputStream fs = null; try { fs = new FileInputStream(f); channel = fs.getChannel(); diff --git a/zeus-core/src/main/java/com/zmops/iot/core/util/HttpContext.java b/zeus-core/src/main/java/com/zmops/iot/core/util/HttpContext.java index adead48d..dce2d93e 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/util/HttpContext.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/util/HttpContext.java @@ -5,6 +5,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.net.InetAddress; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; @@ -14,6 +15,7 @@ */ public class HttpContext { + private static final String LOCALHOST = "127.0.0.1"; /** * 获取请求的ip地址 @@ -25,7 +27,31 @@ public static String getIp() { if (request == null) { return "127.0.0.1"; } else { - return request.getRemoteHost(); + String ipAddress; + try { + ipAddress = request.getHeader("x-forwarded-for"); + if (ipAddress == null || ipAddress.length() == 0 ) { + ipAddress = request.getHeader("Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 ) { + ipAddress = request.getHeader("WL-Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 ) { + ipAddress = request.getRemoteAddr(); + if (LOCALHOST.equals(ipAddress)) { + InetAddress inet = null; + try { + inet = InetAddress.getLocalHost(); + } catch (Exception e) { + e.printStackTrace(); + } + ipAddress = inet.getHostAddress(); + } + } + } catch (Exception e) { + ipAddress = ""; + } + return ipAddress; } } @@ -63,14 +89,14 @@ public static HttpServletResponse getResponse() { * @author fengshuonan */ public static Map getRequestParameters() { - HashMap values = new HashMap<>(); - HttpServletRequest request = HttpContext.getRequest(); + HashMap values = new HashMap<>(); + HttpServletRequest request = HttpContext.getRequest(); if (request == null) { return values; } Enumeration enums = request.getParameterNames(); while (enums.hasMoreElements()) { - String paramName = (String) enums.nextElement(); + String paramName = (String) enums.nextElement(); String paramValue = request.getParameter(paramName); values.put(paramName, paramValue); } diff --git a/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java b/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java index 984f6d64..a4f19435 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/util/RsaUtil.java @@ -1,7 +1,6 @@ package com.zmops.iot.core.util; -import com.zmops.iot.util.ToolUtil; import org.apache.commons.codec.binary.Base64; import javax.crypto.Cipher; @@ -17,27 +16,6 @@ */ public class RsaUtil { - //公钥为:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwgmYk5tASrKzbjPwYffD9eAt1WRjBL2oN8x0FSff0YBrwdaozUFX0uU6z/gkfcjHwdvEJ7PJAt3ELNZ2xyOcUyeLbS0ds7Yx4pMT7kOYGod4IQDRqjXx0NZIe+f8cijYp9Myg37gL1ptXKV7mWX5cOUfP0g9qI0XLqf3dPSJ77wIDAQAB - - private static final String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALCCZiTm0BKsrNuM/Bh98P14C3VZGMEvag3zHQVJ9/RgGvB1qjNQVfS5TrP" + - "+CR9yMfB28Qns8kC3cQs1nbHI5xTJ4ttLR2ztjHikxPuQ5gah3ghANGqNfHQ1kh75/xyKNin0zKDfuAvWm1cpXuZZflw5R8/SD2ojRcup/d09InvvAgMBAAECgYEAmxWXhai" + - "+/Ql2v1i6TxKo4SvOdYaY93QfbK5Eu1boY3Dleo0HxBo7y8/dVMxJW7XMJwl6c0wa9b23ty+epIxuayDWFiN3xSmQH0l/7H8MMxPY3AA/6U9AoyTUeSoUGRx6W+Lvv12jiVVGiL" + - "ZNaI6Ucm8irRunPSNdc2YcP5kptgECQQDmJel83TiOICj2TSiC5paAQTouhD31BHOgC5tMetXfmt/im1DGRPmocLqXO2uythZcvrhFGohgk7V6IQWAQ2lvAkEAxFYQSfcJcl2S8JTET" + - "td15JSUsfO1WCD+3Ik3q1v7jAxc8TubrCPlMZutmDzcalme150Nfh+siEZXyqjGQB/VgQJAGeYkS0/dwGiwE1+Fco2eXBp7AKcTDdKNbHJB7K5aCQq1rRuLUHSMn77n0IL4UKkbBR7VP7" + - "mHpU6Z+n9izhdH8wJAZMRXL98edhgYpml0J5Ll6x9nAb43QLgOllnGvKhE/qgJu7YAO+VgaImiGxSBfAPrRnZQyn6vKnIP9O+ScK7mAQJAd1zJBY/1ezjD9GvgC6mdG3b1xoBlBVvTxK5T" + - "0v5jybWe8W/H6gLEprWhzM0LgwA9CsLWe1KXmOcAGeyKwb02CA=="; - - /** - * 私钥解密 - */ - public static String decryptPwd(String password) throws Exception { - if (ToolUtil.isEmpty(password)) { - throw new IllegalArgumentException("密码为空!"); - } else { - return decrypt(password, privateKey); - } - } - /** * RSA私钥解密 */ @@ -45,8 +23,8 @@ public static String decrypt(String str, String privateKey) throws Exception { //64位解码加密后的字符串 byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8)); //base64编码的私钥 - byte[] decoded = Base64.decodeBase64(privateKey); - RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); + byte[] decoded = Base64.decodeBase64(privateKey); + RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); //RSA解密 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, priKey); diff --git a/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseController.java b/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseController.java index 56b3530c..2cf7d6fd 100644 --- a/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseController.java +++ b/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseController.java @@ -23,7 +23,7 @@ public class BaseController { protected final String REDIRECT = "redirect:"; - protected final String FORWARD = "forward:"; + protected final String FORWARD = "forward:"; protected static SuccessResponseData SUCCESS_TIP = new SuccessResponseData(); @@ -51,13 +51,6 @@ protected void setAttr(String name, Object value) { Objects.requireNonNull(HttpContext.getRequest()).setAttribute(name, value); } - /** - * 包装一个list,让list增加额外属性 - */ - protected Object warpObject(BaseControllerWrapper warpper) { - return warpper.wrap(); - } - /** * 删除cookie */ @@ -116,8 +109,8 @@ protected ResponseEntity renderFile(String fileName, byte[] * @author 0x0001 */ protected ResponseEntity renderFile(String fileName, InputStream inputStream) { - InputStreamResource resource = new InputStreamResource(inputStream); - String dfileName = null; + InputStreamResource resource = new InputStreamResource(inputStream); + String dfileName = null; try { dfileName = new String(fileName.getBytes("gb2312"), "iso8859-1"); } catch (UnsupportedEncodingException e) { diff --git a/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseControllerWrapper.java b/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseControllerWrapper.java deleted file mode 100644 index 8f8500e9..00000000 --- a/zeus-core/src/main/java/com/zmops/iot/core/web/base/BaseControllerWrapper.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.zmops.iot.core.web.base; - -import java.util.List; -import java.util.Map; - -/** - * @author nantian created at 2021/7/29 20:32 - */ -public abstract class BaseControllerWrapper { - -// private Page> page = null; -// -// private PageResult> pageResult = null; - - private Map single = null; - - private List> multi = null; - - public BaseControllerWrapper(Map single) { - this.single = single; - } - - public BaseControllerWrapper(List> multi) { - this.multi = multi; - } - -// public BaseControllerWrapper(Page> page) { -// if (page != null && page.getRecords() != null) { -// this.page = page; -// this.multi = page.getRecords(); -// } -// } -// -// public BaseControllerWrapper(PageResult> pageResult) { -// if (pageResult != null && pageResult.getRows() != null) { -// this.pageResult = pageResult; -// this.multi = pageResult.getRows(); -// } -// } - - @SuppressWarnings("unchecked") - public T wrap() { - - /** - * 包装结果 - */ - if (single != null) { - wrapTheMap(single); - } - if (multi != null) { - for (Map map : multi) { - wrapTheMap(map); - } - } - - /** - * 根据请求的参数响应 - */ -// if (page != null) { -// return (T) page; -// } -// if (pageResult != null) { -// return (T) pageResult; -// } - if (single != null) { - return (T) single; - } - if (multi != null) { - return (T) multi; - } - - return null; - } - - protected abstract void wrapTheMap(Map map); -} diff --git a/zeus-driver/pom.xml b/zeus-driver/pom.xml index 7c4982a1..29709683 100644 --- a/zeus-driver/pom.xml +++ b/zeus-driver/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 @@ -15,7 +16,6 @@ com.zmops zeus-core 1.0-beta - compile diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/Interface.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/Interface.java new file mode 100644 index 00000000..58665c3f --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/Interface.java @@ -0,0 +1,35 @@ +package com.zmops.zeus.driver.entity; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class Interface { + private String interfaceid; + + private String hostid; + + private String deviceId; + + private String main = "1"; + + private String type = "1"; + + private String useip="1"; + + private String ip; + + private String dns=""; + + private String port; + + private String avaiable; + + private String error; + + private String errors_from; + + private String disable_until; +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ItemParam.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ItemParam.java new file mode 100644 index 00000000..090dd8ac --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ItemParam.java @@ -0,0 +1,14 @@ +package com.zmops.zeus.driver.entity; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class ItemParam { + private String host; + private String key; + private String value; + private Long clock; +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/SendParam.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/SendParam.java new file mode 100644 index 00000000..98f95fe9 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/SendParam.java @@ -0,0 +1,13 @@ +package com.zmops.zeus.driver.entity; + +import lombok.Data; + +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class SendParam { + private List params; +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxHostGrpInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxHostGrpInfo.java new file mode 100644 index 00000000..1189309c --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxHostGrpInfo.java @@ -0,0 +1,14 @@ +package com.zmops.zeus.driver.entity; + +import lombok.Data; + +/** + * @author yefei + */ +@Data +public class ZbxHostGrpInfo { + + private String groupid; + private String name; + +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java index 506d53f4..8d8afbef 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxItemInfo.java @@ -2,6 +2,8 @@ import lombok.Data; +import java.util.List; + /** * @author nantian created at 2021/8/10 17:52 */ @@ -25,4 +27,14 @@ public class ZbxItemInfo { private String valuemapid; private String interfaceid; + + private String error; + + private List hosts; + + @Data + public static class HostInfo { + private String hostid; + private String host; + } } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxProblemInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxProblemInfo.java new file mode 100644 index 00000000..556b5570 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxProblemInfo.java @@ -0,0 +1,44 @@ +package com.zmops.zeus.driver.entity; + +import lombok.Data; + +/** + * @author nantian created at 2021/8/10 17:52 + */ +@Data +public class ZbxProblemInfo { + + private String eventid; + + private String source; + + private String object; + + private String objectid; + + private String clock; + + private String ns; + + private String r_eventid; + + private String r_clock; + + private String r_ns; + + private String correlationid; + + private String userid; + + private String name; + + private String acknowledged; + + private String severity; + + private String opdata; + + private String acknowledges; + + +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserGrpInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserGrpInfo.java new file mode 100644 index 00000000..f3f283b5 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserGrpInfo.java @@ -0,0 +1,14 @@ +package com.zmops.zeus.driver.entity; + +import lombok.Data; + +/** + * @author yefei + */ +@Data +public class ZbxUserGrpInfo { + + private String usrgrpid; + private String name; + +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserInfo.java new file mode 100644 index 00000000..543e19e2 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/entity/ZbxUserInfo.java @@ -0,0 +1,17 @@ +package com.zmops.zeus.driver.entity; + +import lombok.Data; + +/** + * @author yefei + */ +@Data +public class ZbxUserInfo { + + private String userid; + private String username; + private String name; + private String surname; + private String roleid; + +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java index 2328b46d..8b3e27eb 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/inteceptor/JsonBodyBuildInterceptor.java @@ -48,7 +48,7 @@ public void onInvokeMethod(ForestRequest request, ForestMethod method, Object[] } else { Annotation[][] paramAnnos = method.getMethod().getParameterAnnotations(); for (int i = 0; i < args.length; i++) { - if (paramAnnos[i][0] instanceof ParamName) { + if (paramAnnos[i].length > 0 && paramAnnos[i][0] instanceof ParamName) { ParamName paramAnno = (ParamName) paramAnnos[i][0]; paramMap.put(paramAnno.value(), args[i]); } @@ -58,7 +58,7 @@ public void onInvokeMethod(ForestRequest request, ForestMethod method, Object[] JsonPath jsonPath = method.getMethod().getAnnotation(JsonPath.class); if (null != jsonPath && StringUtils.isNotBlank(jsonPath.value())) { - String body = Objects.requireNonNull(JsonParseUtil.parse(jsonPath.value() + ".ftl", paramMap)); + String body = Objects.requireNonNull(JsonParseUtil.parse(jsonPath.value() + ".ftl", paramMap)); String sendBody = StringEscapeUtils.unescapeJava(body); log.debug("\n" + sendBody + "\n"); request.replaceBody(sendBody); diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java new file mode 100644 index 00000000..5907097b --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TDEngineRest.java @@ -0,0 +1,28 @@ +package com.zmops.zeus.driver.service; + +import com.dtflys.forest.annotation.BaseRequest; +import com.dtflys.forest.annotation.Body; +import com.dtflys.forest.annotation.Post; +import com.dtflys.forest.extensions.BasicAuth; +import com.dtflys.forest.http.ForestResponse; + +/** + * @author yefei + **/ +@BaseRequest( + baseURL = "${taosUrl}" +) +public interface TDEngineRest { + + /** + * TDEngine execute sql, 必须 2.2.0 以上版本 + * + * @param sql + * @return String + */ + @Post( + contentType = "application/json;charset=utf-8" + ) + @BasicAuth(username = "${taosUser}", password = "${taosPwd}") + ForestResponse executeSql(@Body String sql); +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TransferKit.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TransferKit.java new file mode 100644 index 00000000..8e72317b --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/TransferKit.java @@ -0,0 +1,87 @@ +package com.zmops.zeus.driver.service; + +import com.dtflys.forest.annotation.*; +import com.dtflys.forest.http.ForestResponse; +import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; + + +@BaseRequest(baseURL = "http://172.16.50.1:3000/logkit") +public interface TransferKit { + + + + /** + * 配置信息 + * + * @return + */ + @Get(url = "/configs") + String getConfigs(); + + + /** + * 状态信息 + * + * @return + */ + @Get(url = "/status") + String getStatus(); + + @Post(url = "/configs/${runnerName}", + interceptor = JsonBodyBuildInterceptor.class) + @JsonPath("/transfer/create") + String createRunner(@DataVariable("runnerName") String runnerName, + @ParamName("runnerName") String name, + @ParamName("logPath") String logPath, + @ParamName("batchInterval") Integer batchInterval, + @ParamName("batchSize") Integer batchSize); + + @Put(url = "/configs/${runnerName}", + interceptor = JsonBodyBuildInterceptor.class) + @JsonPath("/transfer/create") + String updateRunner(@DataVariable("runnerName") String runnerName, + @ParamName("runnerName") String name, + @ParamName("logPath") String logPath, + @ParamName("httpSendUrl") String httpSendUrl); + + /** + * 关闭 采集器 Runner + * + * @param runnerName 采集器 runner 名称 + * @return + */ + @Post(url = "/configs/${runnerName}/stop") + ForestResponse stopRunner(@DataVariable("runnerName") String runnerName); + + + /** + * 开启 采集器 Runner + * + * @param runnerName 采集器 runner 名称 + * @return + */ + @Post(url = "/configs/${runnerName}/start") + ForestResponse startRunner(@DataVariable("runnerName") String runnerName); + + + /** + * 重置 采集器 Runner + * + * @param runnerName 采集器 runner 名称 + * @return + */ + @Post(url = "/configs/${runnerName}/reset") + ForestResponse resetRunner(@DataVariable("runnerName") String runnerName); + + + /** + * 开启 采集器 Runner + * + * @param runnerName 采集器 runner 名称 + * @return + */ + @Delete(url = "/configs/${runnerName}") + ForestResponse deleteRunner(@DataVariable("runnerName") String runnerName); +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java deleted file mode 100644 index 8093da2a..00000000 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxAction.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.zmops.zeus.driver.service; - -import com.dtflys.forest.annotation.BaseRequest; -import com.dtflys.forest.annotation.Post; -import com.zmops.zeus.driver.annotation.JsonPath; -import com.zmops.zeus.driver.annotation.ParamName; - -/** - * @author nantian created at 2021/8/7 23:27 - */ - -@BaseRequest(baseURL = "${zbxApiUrl}") -public interface ZbxAction { - - - /** - * 创建默认 在线状态 Action - * - * @param userAuth api token - * @param scriptId 脚本ID - * @param groupId 全局主机组ID - * @return String - */ - @Post(headers = "authTag: noAuth") - @JsonPath("/action/action.init.create") - String createOfflineStatusAction(@ParamName("userAuth") String userAuth, - @ParamName("scriptId") String scriptId, - @ParamName("groupId") String groupId); - - - /** - * 获取 在线状态 Action - * - * @param userAuth api token - * @return String - */ - @Post(headers = "authTag: noAuth") - @JsonPath("/action/action.offline.get") - String getOfflineStatusAction(@ParamName("userAuth") String userAuth); -} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java index ff6aa3ad..5c9ca0f6 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxApiInfo.java @@ -3,12 +3,16 @@ import com.dtflys.forest.annotation.BaseRequest; import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; /** * @author nantian created at 2021/8/3 11:58 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxApiInfo { /** diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxConfig.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxConfig.java new file mode 100644 index 00000000..0c103574 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxConfig.java @@ -0,0 +1,32 @@ +package com.zmops.zeus.driver.service; + +import com.dtflys.forest.annotation.DataVariable; +import com.dtflys.forest.annotation.JSONBody; +import com.dtflys.forest.annotation.Post; +import com.dtflys.forest.annotation.Var; +import com.zmops.zeus.driver.entity.SendParam; + +/** + * @author yefei + */ + +public interface ZbxConfig { + + + /** + * 读取 zbx 配置信息 + * + * @return String + */ + @Post(url = "http://127.0.0.1:12800/zabbix/config") + String getConfig(); + + /** + * 读取 zbx 配置信息 + * + * @return String + */ + @Post(url = "http://${ip}:12800/device/attr/send") + String sendData(@Var("ip") String ip, @JSONBody SendParam sendParam); + +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java index 97b2bfb8..d2784e7b 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxDeviceStatusTrigger.java @@ -4,47 +4,52 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; /** * @author nantian created at 2021/8/10 16:32 *

* 设备离线 在线触发器,判断设备 在线,离线 状态 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxDeviceStatusTrigger { /** - * 在线状态 + * 创建 设备 在线,离线 触发器 + * + * @return String */ @Post - @JsonPath("/trigger/trigger.nodata.0.create") - public String nodataOnline(@ParamName("hostName") String hostName, - @ParamName("itemKey") String itemKey, - @ParamName("nodatTime") String nodataTime, - @ParamName("triggerName") String triggerName); + @JsonPath("/trigger/device.status.trigger") + String createDeviceStatusTrigger(@ParamName("ruleId") String ruleId, + @ParamName("deviceId") String deviceId, + @ParamName("itemKey") String itemKey, + @ParamName("ruleCondition") String ruleCondition, + @ParamName("ruleFunction") String ruleFunction, + @ParamName("itemKeyRecovery") String itemKeyRecovery, + @ParamName("ruleConditionRecovery") String ruleConditionRecovery, + @ParamName("ruleFunctionRecovery") String ruleFunctionRecovery); /** - * 离线状态 + * 修改 设备 在线,离线 触发器 + * + * @return String */ @Post - @JsonPath("/trigger/trigger.nodata.1.create") - public String nodataOffline(@ParamName("hostName") String hostName, - @ParamName("itemKey") String itemKey, - @ParamName("nodatTime") String nodataTime, - @ParamName("triggerName") String triggerName); - - - /** - * 自定义状态,最新值等于 ? 触发 - */ - @Post - @JsonPath("/trigger/trigger.last.create") - public String lastValueJudge(@ParamName("hostName") String hostName, - @ParamName("itemKey") String itemKey, - @ParamName("dataValue") String dataValue, - @ParamName("triggerName") String triggerName); - - + @JsonPath("/trigger/device.status.trigger.update") + String updateDeviceStatusTrigger(@ParamName("triggerId") String triggerId, + @ParamName("ruleId") String ruleId, + @ParamName("deviceId") String deviceId, + @ParamName("itemKey") String itemKey, + @ParamName("ruleCondition") String ruleCondition, + @ParamName("ruleFunction") String ruleFunction, + @ParamName("itemKeyRecovery") String itemKeyRecovery, + @ParamName("ruleConditionRecovery") String ruleConditionRecovery, + @ParamName("ruleFunctionRecovery") String ruleFunctionRecovery, + @ParamName("recoveryTriggerId") String recoveryTriggerId); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java index 5b385efe..c7bc0fdb 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHistoryGet.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.List; @@ -11,12 +12,26 @@ * @author nantian created at 2021/8/3 14:50 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxHistoryGet { @Post @JsonPath("/history/history.get") String historyGet(@ParamName("hostid") String hostid, @ParamName("itemids") List itemids, - @ParamName("hisNum") String hisNum); + @ParamName("hisNum") Integer hisNum, + @ParamName("valueType") Integer valueType, + @ParamName("timeFrom") Long timeFrom, + @ParamName("timeTill") Long timeTill); + + @Post(headers = "authTag: noAuth") + @JsonPath("/history/history.get") + String historyGetWithNoAuth(@ParamName("hostid") String hostid, + @ParamName("itemids") List itemids, + @ParamName("hisNum") Integer hisNum, + @ParamName("valueType") Integer valueType, + @ParamName("userAuth") String zbxApiToken); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java index fadf9a22..738146ce 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHost.java @@ -4,6 +4,8 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.entity.Interface; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import lombok.Data; import java.util.List; @@ -14,7 +16,10 @@ *

* 主机驱动 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxHost { /** @@ -29,12 +34,14 @@ public interface ZbxHost { @JsonPath("/host/host.create") String hostCreate(@ParamName("hostName") String hostName, @ParamName("groupids") List groupids, - @ParamName("templateid") String templateid); + @ParamName("templateid") String templateid, + @ParamName("proxyid") String proxyid, + @ParamName("interfaces") Interface interfaces); /** * 修改主机 * - * @param hostid 主机ID + * @param hostid 主机ID * @param groupids 主机分组IDs * @param templateid 主机模板ID,对应产品物模型ID * @return @@ -42,18 +49,33 @@ String hostCreate(@ParamName("hostName") String hostName, @Post @JsonPath("/host/host.update") String hostUpdate(@ParamName("hostid") String hostid, - @ParamName("groupids") List groupids, - @ParamName("templateid") String templateid); + @ParamName("groupids") List groupids, + @ParamName("templateid") String templateid, + @ParamName("proxyid") String proxyid, + @ParamName("interfaces") Interface interfaces); + + /** + * 修改主机状态 + * + * @param hostid 主机ID + * @param status 主机状态 + * @return + */ + @Post + @JsonPath("/host/host.status.update") + String hostStatusUpdate(@ParamName("hostid") String hostid, + @ParamName("status") String status); + /** * 删除主机 * - * @param hostIds 主机ID + * @param hostIds 主机ID * @return */ @Post @JsonPath("/host/host.delete") - void hostDelete(@ParamName("hostIds") List hostIds); + String hostDelete(@ParamName("hostIds") List hostIds); /** * 查询主机详情 @@ -64,6 +86,15 @@ String hostUpdate(@ParamName("hostid") String hostid, @JsonPath("/host/host.get") String hostDetail(@ParamName("hostid") String hostid); + /** + * 查询主机 + * + * @param host 主机ID + */ + @Post + @JsonPath("/host/host.get") + String hostGet(@ParamName("host") String host); + /** * 更新主机宏 * @@ -86,7 +117,18 @@ String hostMacroUpdate(@ParamName("hostId") String hostId, @Post @JsonPath("/host/host.tag.update") String hostTagUpdate(@ParamName("hostId") String hostId, - @ParamName("tagMap") Map tagMap); + @ParamName("tagMap") Map tagMap); + + + /** + * 通过主机名获取 模板IDS + * + * @param hostname + * @return + */ + @Post + @JsonPath("/host/host.tempid.get") + String hostTempidGet(@ParamName("hostname") String hostname); @Data diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java index d9f1af37..22b11d98 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxHostGroup.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.List; @@ -11,7 +12,10 @@ * @author nantian created at 2021/8/3 16:02 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxHostGroup { @@ -55,5 +59,14 @@ public interface ZbxHostGroup { */ @Post @JsonPath("/hostgroup/hostgroup.delete") - String hostGroupDelete(@ParamName("hostgGroupIds") List hostGrpIds); + String hostGroupDelete(@ParamName("hostGroupIds") List hostGrpIds); + + /** + * 获取 主机组 + * + * @return String + */ + @Post + @JsonPath("/hostgroup/hostgroup.get") + String getHostGroup(@ParamName("groupids") String groupids); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java new file mode 100644 index 00000000..0e017377 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInitService.java @@ -0,0 +1,63 @@ +package com.zmops.zeus.driver.service; + +import com.dtflys.forest.annotation.Post; +import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; + +/** + * @author nantian created at 2021/8/26 12:20 + */ + +public interface ZbxInitService { + + @Post( + url = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + headers = "authTag: noAuth", + interceptor = JsonBodyBuildInterceptor.class + ) + @JsonPath("/usergroup/cookieUserGroupCreate") + String createCookieUserGroup(@ParamName("hostGroupId") String hostGroupId, @ParamName("userAuth") String userAuth); + + @Post( + url = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + headers = "authTag: noAuth", + interceptor = JsonBodyBuildInterceptor.class + ) + @JsonPath("/usergroup/cookieUserGroupGet") + String getCookieUserGroup(@ParamName("userAuth") String userAuth); + + @Post( + url = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + headers = "authTag: noAuth", + interceptor = JsonBodyBuildInterceptor.class + ) + @JsonPath("/user/cookieUserGet") + String getCookieUser(@ParamName("userAuth") String userAuth); + + @Post( + url = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + headers = "authTag: noAuth", + interceptor = JsonBodyBuildInterceptor.class + ) + @JsonPath("/user/cookieUserAdd") + String createCookieUser(@ParamName("usrGrpId") String usrGrpId, + @ParamName("userAuth") String userAuth, + @ParamName("roleId") String roleId); + + @Post( + url = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + headers = "authTag: noAuth", + interceptor = JsonBodyBuildInterceptor.class + ) + @JsonPath("/role/adminRole.get") + String getAdminRole(@ParamName("userAuth") String zbxApiToken); + + @Post( + url = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + headers = "authTag: noAuth", + interceptor = JsonBodyBuildInterceptor.class + ) + @JsonPath("/role/guestRole.get") + String getGuestRole(@ParamName("userAuth") String zbxApiToken); +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInterface.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInterface.java new file mode 100644 index 00000000..e9c08ddf --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxInterface.java @@ -0,0 +1,25 @@ +package com.zmops.zeus.driver.service; + +import com.dtflys.forest.annotation.BaseRequest; +import com.dtflys.forest.annotation.Post; +import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; + +/** + * @author yefei + **/ +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + interceptor = JsonBodyBuildInterceptor.class +) +public interface ZbxInterface { + /** + * 查询主机接口 + * + * @param hostid 主机ID + */ + @Post + @JsonPath("/hostinterface/hostinterface.get") + String hostinterfaceGet(@ParamName("hostid") String hostid); +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java index 491bb28d..628f814f 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxItem.java @@ -5,6 +5,7 @@ import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; import com.zmops.zeus.driver.entity.ZbxProcessingStep; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.List; import java.util.Map; @@ -13,7 +14,10 @@ * @author nantian created at 2021/8/4 18:07 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxItem { @@ -35,11 +39,15 @@ public interface ZbxItem { String createTrapperItem(@ParamName("itemName") String itemName, @ParamName("itemKey") String itemKey, @ParamName("hostId") String hostId, + @ParamName("source") String source, + @ParamName("delay") String delay, + @ParamName("masterItemid") String masterItemid, @ParamName("valueType") String valueType, @ParamName("units") String units, @ParamName("processList") List processingStepList, @ParamName("valuemapid") String valuemapid, - @ParamName("tagMap") Map tagMap); + @ParamName("tagMap") Map tagMap, + @ParamName("interfaceid") String interfaceid); /** * 修改 Zabbix Trapper ITEM @@ -61,11 +69,15 @@ String updateTrapperItem(@ParamName("itemid") String itemid, @ParamName("itemName") String itemName, @ParamName("itemKey") String itemKey, @ParamName("hostId") String hostId, + @ParamName("source") String source, + @ParamName("delay") String delay, + @ParamName("masterItemid") String masterItemid, @ParamName("valueType") String valueType, @ParamName("units") String units, @ParamName("processList") List processingStepList, @ParamName("valuemapid") String valuemapid, - @ParamName("tagMap") Map tagMap); + @ParamName("tagMap") Map tagMap, + @ParamName("interfaceid") String interfaceid); /** * 删称 Zabbix Trapper ITEM @@ -85,4 +97,24 @@ String updateTrapperItem(@ParamName("itemid") String itemid, @Post @JsonPath("/item/item.get") String getItemInfo(@ParamName("itemId") String itemId, @ParamName("hostid") String hostid); + + /** + * 根据item key 获取 ITEM 信息 + * + * @param key key + * @return String + */ + @Post + @JsonPath("/item/item.get") + String getItemList(@ParamName("key") String key, @ParamName("hostid") String hostid); + + /** + * 根据item name 获取 ITEM 信息 + * + * @param name name + * @return String + */ + @Post + @JsonPath("/item/item.name.get") + String getItemListByName(@ParamName("name") String name); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java new file mode 100644 index 00000000..bbe05cbc --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxMacro.java @@ -0,0 +1,87 @@ +package com.zmops.zeus.driver.service; + + +import com.dtflys.forest.annotation.BaseRequest; +import com.dtflys.forest.annotation.Post; +import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; + +import java.util.List; + +/** + * 宏定义接口 + */ +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) +public interface ZbxMacro { + + + /** + * 创建宏 + * + * @param hostid 主机ID + * @param macro 宏 Key + * @param value 宏 Value + * @return + */ + @Post + @JsonPath("/macro/usermacro.create") + String macroCreate(@ParamName("hostid") String hostid, + @ParamName("macro") String macro, + @ParamName("value") String value, + @ParamName("description") String description); + + + /** + * 更新 宏 + * + * @param macroid 宏 ID + * @param macro 宏 Key + * @param value 宏 Value + * @return + */ + @Post + @JsonPath("/macro/usermacro.update") + String macroUpdate(@ParamName("macroid") String macroid, + @ParamName("macro") String macro, + @ParamName("value") String value, + @ParamName("description") String description); + + /** + * 获取 宏 + * + * @param hostid 主机ID + * @return + */ + @Post + @JsonPath("/macro/usermacro.get") + String macroGet(@ParamName("hostid") String hostid); + + + /** + * 搜索 宏 ID + * + * @param hostid 主机ID + * @param macro 宏 Key + * @return + */ + @Post + @JsonPath("/macro/usermacro.filter.get") + String macroQuery(@ParamName("hostid") String hostid, + @ParamName("macro") String macro); + + + /** + * 删除宏 + * + * @param macroids 宏IDs + * @return + */ + @Post + @JsonPath("/macro/usermacro.delete") + String macroDelete(@ParamName("macroids") List macroids); + +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java new file mode 100644 index 00000000..10bc1c01 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProblem.java @@ -0,0 +1,41 @@ +package com.zmops.zeus.driver.service; + +import com.dtflys.forest.annotation.BaseRequest; +import com.dtflys.forest.annotation.Post; +import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; + +/** + * @author nantian created at 2021/8/7 23:27 + */ + +@BaseRequest(baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", interceptor = JsonBodyBuildInterceptor.class) +public interface ZbxProblem { + + + /** + * 告警列表 + * + * @param hostId + * @return String + */ + @Post + @JsonPath("/problem/problem.get") + String getProblem(@ParamName("hostId") String hostId, + @ParamName("timeFrom") Long timeFrom, + @ParamName("timeTill") Long timeTill, + @ParamName("recent") String recent, + @ParamName("severity") String severity); + + @Post + @JsonPath("/problem/problem.event.get") + String getEventProblem(@ParamName("hostId") String hostId, + @ParamName("timeFrom") Long timeFrom, + @ParamName("timeTill") Long timeTill, + @ParamName("recent") String recent); + + @Post + @JsonPath("/problem/problem.acknowledgement") + String acknowledgement(@ParamName("eventId") String eventId, @ParamName("action") int action); +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProxy.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProxy.java new file mode 100644 index 00000000..ada79d9f --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxProxy.java @@ -0,0 +1,51 @@ +package com.zmops.zeus.driver.service; + +import com.dtflys.forest.annotation.BaseRequest; +import com.dtflys.forest.annotation.Post; +import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; + +import java.util.List; + +/** + * @author yefei + *

+ * 代理驱动 + */ +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}/zabbix/api_jsonrpc.php", + interceptor = JsonBodyBuildInterceptor.class +) +public interface ZbxProxy { + + /** + * 创建代理 + * + * @param name 代理名称 + * @return + */ + @Post + @JsonPath("/proxy/proxy.create") + String proxyCreate(@ParamName("name") String name); + + + /** + * 删除代理 + * + * @param hostIds 主机ID + * @return + */ + @Post + @JsonPath("/proxy/proxy.delete") + String proxyDelete(@ParamName("hostIds") List hostIds); + + /** + * 代理列表 + * + * @return + */ + @Post + @JsonPath("/proxy/proxy.get") + String get(@ParamName("proxyids") String proxyids); +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java deleted file mode 100644 index 900bb399..00000000 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxScript.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.zmops.zeus.driver.service; - -import com.dtflys.forest.annotation.BaseRequest; -import com.dtflys.forest.annotation.Post; -import com.zmops.zeus.driver.annotation.JsonPath; -import com.zmops.zeus.driver.annotation.ParamName; - -/** - * @author nantian created at 2021/8/7 20:42 - */ -@BaseRequest(baseURL = "${zbxApiUrl}") -public interface ZbxScript { - - - /** - * 创建 在线状态 回调地址 - * - * @param userApiToken apiToekn - * @param zeusServerIp 平台IP - * @param zeusServerPort 平台端口 - * @return String - */ - @Post(headers = "authTag: noAuth") - @JsonPath("/script/script.init.create") - String createOfflineStatusScript(@ParamName("userAuth") String userApiToken, - @ParamName("zeusServerIp") String zeusServerIp, - @ParamName("zeusServerPort") String zeusServerPort); - - - /** - * 获取 在线状态 回调脚本 ID - * - * @param userAuth 授权Token - * @return String - */ - @Post(headers = "authTag: noAuth") - @JsonPath("/script/script.offline.get") - String getOfflineStatusScript(@ParamName("userAuth") String userAuth); -} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java index e44a957c..f5ed77aa 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTemplate.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.Map; @@ -11,7 +12,10 @@ * @author nantian created at 2021/8/3 15:47 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxTemplate { /** @@ -55,6 +59,15 @@ String templateTagUpdate(@ParamName("templateId") String templateId, * @param templateid 模板ID */ @Post - @JsonPath("/template/template.get") + @JsonPath("/template/template.detail.get") String templateDetail(@ParamName("templateid") String templateid); + + /** + * 查询模板信息 + * + * @param templateid 模板ID + */ + @Post + @JsonPath("/template/template.get") + String templateGet(@ParamName("templateid") String templateid); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java new file mode 100644 index 00000000..affcffe8 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxTrigger.java @@ -0,0 +1,134 @@ +package com.zmops.zeus.driver.service; + + +import com.dtflys.forest.annotation.BaseRequest; +import com.dtflys.forest.annotation.Post; +import com.zmops.zeus.driver.annotation.JsonPath; +import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; + +import java.util.Map; + +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) +public interface ZbxTrigger { + + /** + * 创建告警触发器 + * + * @param triggerName 触发器名称 + * @param expression 触发器 表达式 + * @param ruleLevel 告警等级 + * @return + */ + @Post + @JsonPath("/trigger/trigger.create") + String triggerCreate(@ParamName("triggerName") String triggerName, + @ParamName("expression") String expression, + @ParamName("ruleLevel") Byte ruleLevel, + @ParamName("type") Integer type); + + /** + * 创建场景联动触发器 + * + * @param triggerName 触发器名称 + * @param expression 触发器 表达式 + * @param ruleLevel 告警等级 + * @return + */ + @Post + @JsonPath("/trigger/trigger.execute.create") + String executeTriggerCreate(@ParamName("triggerName") String triggerName, + @ParamName("expression") String expression, + @ParamName("ruleLevel") Byte ruleLevel); + + /** + * 更新告警触发器 + * + * @param triggerId 触发器ID + * @param expression 触发器 表达式 + * @param ruleLevel 告警等级 + * @return + */ + @Post + @JsonPath("/trigger/trigger.update") + String triggerUpdate(@ParamName("triggerId") String triggerId, + @ParamName("expression") String expression, + @ParamName("ruleLevel") Byte ruleLevel); + + + /** + * 更新创建 触发器 Tag + * + * @param triggerId 触发器ID + * @param tags 标签 + * @return + */ + @Post + @JsonPath("/trigger/trigger.tags.update") + String triggerTagCreate(@ParamName("triggerId") String triggerId, + @ParamName("tagMap") Map tags); + + /** + * 根据TRIGGER ID查询触发器 + * + * @param triggerIds 触发器IDs + */ + @Post + @JsonPath("/trigger/trigger.get") + String triggerGet(@ParamName("triggerIds") String triggerIds); + + + /** + * 根据TRIGGER ID查询触发器及触发器标签 + * + * @param triggerIds 触发器IDs + */ + @Post + @JsonPath("/trigger/triggerAndTags.get") + String triggerAndTagsGet(@ParamName("triggerIds") String triggerIds); + + + /** + * 根据host 查询触发器 + * + * @param host 设备ID + */ + @Post + @JsonPath("/trigger/trigger.get") + String triggerGetByHost(@ParamName("host") String host); + + /** + * 根据触发器名称 查询触发器 + * + * @param description 触发器名称 + */ + @Post + @JsonPath("/trigger/trigger.get") + String triggerGetByName(@ParamName("description") String description); + + + /** + * 修改触发器状态 + * + * @param triggerId + * @param status + * @return + */ + @Post + @JsonPath("/trigger/trigger.status.update") + String triggerStatusUpdate(@ParamName("triggerid") String triggerId, + @ParamName("status") String status); + + /** + * 修改触发器状态 + * + * @param triggerId + * @return + */ + @Post + @JsonPath("/trigger/trigger.delete") + String triggerDelete(@ParamName("triggerid") String triggerId); +} diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java index eb84cd36..cff9626f 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUser.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.List; @@ -13,7 +14,10 @@ * ZABBIX User 接口 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxUser { /** @@ -39,7 +43,10 @@ String userLogin(@ParamName("username") String username, */ @Post @JsonPath("/user/userAdd") - String userAdd(@ParamName("name") String name, @ParamName("password") String password, @ParamName("usrGrpId") String usrGrpId); + String userAdd(@ParamName("name") String name, + @ParamName("password") String password, + @ParamName("usrGrpId") String usrGrpId, + @ParamName("roleId") String roleId); /** * 用户修改 @@ -50,7 +57,9 @@ String userLogin(@ParamName("username") String username, */ @Post @JsonPath("/user/userUpdate") - String userUpdate(@ParamName("userId") String userId, @ParamName("usrGrpId") String usrGrpId); + String userUpdate(@ParamName("userId") String userId, + @ParamName("usrGrpId") String usrGrpId, + @ParamName("roleId") String roleId); /** * 用户删除 @@ -61,4 +70,24 @@ String userLogin(@ParamName("username") String username, @Post @JsonPath("/user/userDelete") String userDelete(@ParamName("usrids") List usrids); + + /** + * 用户修改密码 + * + * @param userId 用户id + * @param passwd 用户组ID + * @return 用户信息 + */ + @Post + @JsonPath("/user/userUpdatePwd") + String updatePwd(@ParamName("userId") String userId, @ParamName("passwd") String passwd); + + /** + * 用户查询 + * + * @return + */ + @Post + @JsonPath("/user/userGet") + String getUser(@ParamName("userids") String userIds); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java index 5ccf1d46..4694c9bf 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxUserGroup.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.List; @@ -13,7 +14,10 @@ * ZABBIX UserGrp 接口 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxUserGroup { @@ -49,4 +53,8 @@ public interface ZbxUserGroup { @JsonPath("/usergroup/userGroupBindHostGroup") String userGrpBindHostGroup(@ParamName("hostGroupIds") List hostGroupIds, @ParamName("userGroupId") String userGroupId); + + @Post + @JsonPath("/usergroup/userGroupGet") + String getUserGrp(@ParamName("usrgrpids") String usrgrpids); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java index 54ec7e61..0517bfcb 100644 --- a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZbxValueMap.java @@ -4,6 +4,7 @@ import com.dtflys.forest.annotation.Post; import com.zmops.zeus.driver.annotation.JsonPath; import com.zmops.zeus.driver.annotation.ParamName; +import com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor; import java.util.Map; @@ -12,7 +13,10 @@ *

* 值映射设置 */ -@BaseRequest(baseURL = "${zbxApiUrl}") +@BaseRequest( + baseURL = "http://${zbxServerIp}:${zbxServerPort}${zbxApiUrl}", + interceptor = JsonBodyBuildInterceptor.class +) public interface ZbxValueMap { /** @@ -55,4 +59,14 @@ String valueMapUpdate(@ParamName("hostId") String hostId, @ParamName("valueMapName") String valueMapName, @ParamName("valMaps") Map valMaps, @ParamName("valueMapId") String valueMapId); + + /** + * 删除值映射 + * + * @param valuemapids 值映射ID + * @return String + */ + @Post + @JsonPath("/valuemap/valuemap.get") + String valueMapGet(@ParamName("valuemapids") String valuemapids); } diff --git a/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZeusServer.java b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZeusServer.java new file mode 100644 index 00000000..45e092b3 --- /dev/null +++ b/zeus-driver/src/main/java/com/zmops/zeus/driver/service/ZeusServer.java @@ -0,0 +1,24 @@ +package com.zmops.zeus.driver.service; + +import com.dtflys.forest.annotation.DataFile; +import com.dtflys.forest.annotation.Post; +import com.dtflys.forest.annotation.Var; +import com.dtflys.forest.callback.OnProgress; +import org.springframework.web.multipart.MultipartFile; + +/** + * @author yefei + **/ +public interface ZeusServer { + + /** + * 上传 协议包 + * + * @param ip 服务器IP + * @param file 文件 + * @param onProgress 进度处理 + * @return map + */ + @Post(url = "http://${ip}:12800/protocol/component/upload") + void upload(@Var("ip") String ip, @DataFile("file") MultipartFile file, OnProgress onProgress); +} diff --git a/zeus-driver/src/main/resources/api-json/action/action.create.ftl b/zeus-driver/src/main/resources/api-json/action/action.create.ftl index e69de29b..4ab8c3dc 100644 --- a/zeus-driver/src/main/resources/api-json/action/action.create.ftl +++ b/zeus-driver/src/main/resources/api-json/action/action.create.ftl @@ -0,0 +1,35 @@ +{ + "jsonrpc": "2.0", + "method": "action.create", + "params": { + "name": "${name}", + "eventsource": 0, + "status": 0, + "esc_period": "2m", + "filter": { + "evaltype": 0, + "conditions": [ + { + "conditiontype": 25, + "operator": 0, + "value": "${tagName}" + } + ] + }, + "operations": [ + { + "operationtype": 1, + "opcommand_hst": [ + { + "hostid": "0" + } + ], + "opcommand": { + "scriptid": "${scriptId}" + } + } + ] + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/action/action.init.create.ftl b/zeus-driver/src/main/resources/api-json/action/action.init.create.ftl index 0b41642d..37b0908c 100644 --- a/zeus-driver/src/main/resources/api-json/action/action.init.create.ftl +++ b/zeus-driver/src/main/resources/api-json/action/action.init.create.ftl @@ -2,7 +2,7 @@ "jsonrpc": "2.0", "method": "action.create", "params": { - "name": "__offline_status__", + "name": "${name}", "eventsource": 0, "status": 0, "esc_period": "2m", @@ -12,16 +12,29 @@ { "conditiontype": 25, "operator": 0, - "value": "DEVICE_STATUS" + "value": "${tagName}" } ] }, "operations": [ { "operationtype": 1, - "opcommand_grp": [ + "opcommand_hst": [ { - "groupid": "${groupId}" + "hostid": "0" + } + ], + "opcommand": { + "scriptid": "${scriptId}" + } + } + ], + "recovery_operations": [ + { + "operationtype": "1", + "opcommand_hst": [ + { + "hostid": "0" } ], "opcommand": { diff --git a/zeus-driver/src/main/resources/api-json/action/action.offline.get.ftl b/zeus-driver/src/main/resources/api-json/action/action.offline.get.ftl index 7d6e83e9..50d576be 100644 --- a/zeus-driver/src/main/resources/api-json/action/action.offline.get.ftl +++ b/zeus-driver/src/main/resources/api-json/action/action.offline.get.ftl @@ -6,7 +6,7 @@ "actionid" ], "search": { - "name": "__offline_status__" + "name": "${name}" } }, "auth": "${userAuth}", diff --git a/zeus-driver/src/main/resources/api-json/history/history.get.ftl b/zeus-driver/src/main/resources/api-json/history/history.get.ftl index a274186d..511ca5ac 100644 --- a/zeus-driver/src/main/resources/api-json/history/history.get.ftl +++ b/zeus-driver/src/main/resources/api-json/history/history.get.ftl @@ -3,7 +3,7 @@ "method": "history.get", "params": { "output": "extend", - "history": 0, + "history": ${valueType}, <#if hostid??> "hostids": "${hostid}", @@ -14,6 +14,12 @@ ], + <#if timeFrom??> + "time_from":${timeFrom}, + + <#if timeTill??> + "time_till":${timeTill}, + "sortfield": "clock", "sortorder": "DESC", "limit": ${hisNum} diff --git a/zeus-driver/src/main/resources/api-json/host/host.create.ftl b/zeus-driver/src/main/resources/api-json/host/host.create.ftl index 82c6780d..aa266d77 100644 --- a/zeus-driver/src/main/resources/api-json/host/host.create.ftl +++ b/zeus-driver/src/main/resources/api-json/host/host.create.ftl @@ -3,6 +3,21 @@ "method": "host.create", "params": { "host": "${hostName}", + <#if interfaces??> + "interfaces": [ + { + "type": ${interfaces.type}, + "main": ${interfaces.main}, + "useip": ${interfaces.useip}, + "ip": "${interfaces.ip}", + "dns": "", + "port": "${interfaces.port}" + } + ], + + <#if proxyid??> + "proxy_hostid":"${proxyid}", + "groups": [ <#if groupids??> <#list groupids as groupid> diff --git a/zeus-driver/src/main/resources/api-json/host/host.get.ftl b/zeus-driver/src/main/resources/api-json/host/host.get.ftl index dd180015..771b6dde 100644 --- a/zeus-driver/src/main/resources/api-json/host/host.get.ftl +++ b/zeus-driver/src/main/resources/api-json/host/host.get.ftl @@ -2,12 +2,20 @@ "jsonrpc": "2.0", "method": "host.get", "params": { + <#if host??> + "filter": { + "host": "${host}" + }, + + <#if hostid??> + "hostids": "${hostid}", + "output": "extend", "selectTags":"extend", "selectMacros":"extend", "selectValueMaps":"extend", - "hostids":${hostid} - }, + "selectInterface":"extend" + }, "auth": "${userAuth}", "id": 1 } \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/host/host.status.update.ftl b/zeus-driver/src/main/resources/api-json/host/host.status.update.ftl new file mode 100644 index 00000000..49ad4bdd --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/host/host.status.update.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "host.update", + "params": { + "hostid":"${hostid}", + "status":"${status}" + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/host/host.tempid.get.ftl b/zeus-driver/src/main/resources/api-json/host/host.tempid.get.ftl new file mode 100644 index 00000000..953f8ffd --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/host/host.tempid.get.ftl @@ -0,0 +1,21 @@ +<#--通过主机ID查询模板ID--> +{ + "jsonrpc": "2.0", + "method": "host.get", + "params": { + "output": [ + "hostid" + ], + "selectParentTemplates": [ + "templateid", + "name" + ], + "filter": { + "host": [ + "${hostname}" + ] + } + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/host/host.update.ftl b/zeus-driver/src/main/resources/api-json/host/host.update.ftl index 946f3787..b278dab0 100644 --- a/zeus-driver/src/main/resources/api-json/host/host.update.ftl +++ b/zeus-driver/src/main/resources/api-json/host/host.update.ftl @@ -2,8 +2,22 @@ "jsonrpc": "2.0", "method": "host.update", "params": { - "hostid":"${hostid}" - "host": "${hostName}", + "hostid":"${hostid}", + <#if interfaces??> + "interfaces": [ + { + "type": ${interfaces.type}, + "main": ${interfaces.main}, + "useip": ${interfaces.useip}, + "ip": "${interfaces.ip}", + "dns": "${interfaces.dns}", + "port": "${interfaces.port}" + } + ], + + <#if proxyid??> + "proxy_hostid": "${proxyid}", + "groups": [ <#if groupids??> <#list groupids as groupid> diff --git a/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.delete.ftl b/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.delete.ftl index e180a868..dff9fab3 100644 --- a/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.delete.ftl +++ b/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.delete.ftl @@ -2,8 +2,8 @@ "jsonrpc": "2.0", "method": "hostgroup.delete", "params": [ - <#if hostgGroupIds??> - <#list hostgGroupIds as hostgroupid> + <#if hostGroupIds??> + <#list hostGroupIds as hostgroupid> "${hostgroupid}"<#if hostgroupid_has_next>, diff --git a/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.get.ftl b/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.get.ftl new file mode 100644 index 00000000..b4b18385 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/hostgroup/hostgroup.get.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "hostgroup.get", + "params": { + "output": "extend", + "groupids": ${groupids} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/hostinterface/hostinterface.get.ftl b/zeus-driver/src/main/resources/api-json/hostinterface/hostinterface.get.ftl new file mode 100644 index 00000000..00a90878 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/hostinterface/hostinterface.get.ftl @@ -0,0 +1,9 @@ +{ + "jsonrpc": "2.0", + "method": "hostinterface.get", + "params": { + "hostids": ${hostid} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/item/item.get.ftl b/zeus-driver/src/main/resources/api-json/item/item.get.ftl index cd11da3a..7177c6b1 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.get.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.get.ftl @@ -5,6 +5,17 @@ "selectTags":"extend", "selectValueMap":"extend", "selectPreprocessing":"extend", + <#if key??> + "search":{ + "key_":"${key}" + }, + + <#if itemId??> + "itemids": ${itemId}, + + <#if hostid??> + "hostids": ${hostid}, + "output": [ "itemid", "hostid", @@ -14,14 +25,9 @@ "value_type", "units", "valuemapid", - "interfaceid" - ], - <#if itemId??> - "itemids": "${itemId}" - - <#if hostid??> - "hostids": "${hostid}" - + "interfaceid", + "error" + ] }, "auth": "${userAuth}", "id": 1 diff --git a/zeus-driver/src/main/resources/api-json/item/item.name.get.ftl b/zeus-driver/src/main/resources/api-json/item/item.name.get.ftl new file mode 100644 index 00000000..91cc12fe --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/item/item.name.get.ftl @@ -0,0 +1,25 @@ +{ + "jsonrpc": "2.0", + "method": "item.get", + "params": { + "selectHosts":["host"], + <#if name??> + "search":{ + "name":"${name}" + }, + + "output": [ + "itemid", + "hostid", + "name", + "key_", + "status", + "value_type", + "units", + "valuemapid", + "interfaceid" + ] + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl b/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl index 9b62e833..f6faa5ae 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.trapper.create.ftl @@ -5,14 +5,27 @@ "name": "${itemName}", "key_": "${itemKey}", "hostid": "${hostId}", - "type": 2, <#--zabbix trapper--> + "type": ${source}, + <#if interfaceid??> + "interfaceid": "${interfaceid}", + + "trends":"0", + <#if delay??> + "delay":"${delay}", + + "history":"30d", + <#if source == '18'> + "master_itemid":${masterItemid}, + "value_type": ${valueType}, <#if valuemapid?? && valuemapid != ''> "valuemapid":${valuemapid}, + <#if valueType == '0' || valueType == '3'> <#if units??> "units": "${units}", + "preprocessing": [ <#if processList??> <#list processList as process> diff --git a/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl b/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl index e9c39023..55e4067f 100644 --- a/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl +++ b/zeus-driver/src/main/resources/api-json/item/item.trapper.update.ftl @@ -6,13 +6,24 @@ "name": "${itemName}", "key_": "${itemKey}", "hostid": "${hostId}", - "type": 2, <#--zabbix trapper--> + <#if interfaceid??> + "interfaceid": "${interfaceid}", + + "type": ${source}, + <#if delay??> + "delay":"${delay}", + + <#if source == '18'> + "master_itemid":${masterItemid}, + "value_type": ${valueType}, - <#if valuemapid??> + <#if valuemapid?? && valuemapid != ''> "valuemapid":${valuemapid}, <#if valueType == '0' || valueType == '3'> - "units": "${units}", + <#if units??> + "units": "${units}", + "preprocessing": [ <#if processList??> diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl new file mode 100644 index 00000000..318648e3 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.create.ftl @@ -0,0 +1,14 @@ +{ + "jsonrpc": "2.0", + "method": "usermacro.create", + "params": { + "hostid": "${hostid}", + "macro": "${macro}", + "value": "${value}" + <#if description??> + ,"description":"${description}" + + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.delete.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.delete.ftl new file mode 100644 index 00000000..10cc7292 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.delete.ftl @@ -0,0 +1,11 @@ +{ + "jsonrpc": "2.0", + "method": "usermacro.delete", + "params": [ + <#list macroids as id> + "${id}"<#if id_has_next>, + + ], + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.filter.get.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.filter.get.ftl new file mode 100644 index 00000000..566f24c0 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.filter.get.ftl @@ -0,0 +1,19 @@ +{ + "jsonrpc": "2.0", + "method": "usermacro.get", + "params": { + "output": [ + "macro", + "value", + "description" + ], + "hostids": "${hostid}", + <#if macro??> + "filter": { + "macro": "${macro}" + } + + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.get.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.get.ftl new file mode 100644 index 00000000..76fdb651 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.get.ftl @@ -0,0 +1,15 @@ +{ + "jsonrpc": "2.0", + "method": "usermacro.get", + "params": { + "output": [ + "hostmacroid", + "macro", + "value", + "description" + ], + "hostids": "${hostid}" + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl b/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl new file mode 100644 index 00000000..666ac75f --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/macro/usermacro.update.ftl @@ -0,0 +1,14 @@ +{ + "jsonrpc": "2.0", + "method": "usermacro.update", + "params": { + "hostmacroid": "${macroid}", + "macro": "${macro}", + "value": "${value}", + <#if description??> + "description":"${description}" + + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.acknowledgement.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.acknowledgement.ftl new file mode 100644 index 00000000..02966716 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/problem/problem.acknowledgement.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "event.acknowledge", + "params": { + "eventids": "${eventId}", + "action": ${action} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.event.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.event.get.ftl new file mode 100644 index 00000000..e56b375f --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/problem/problem.event.get.ftl @@ -0,0 +1,26 @@ +{ + "jsonrpc": "2.0", + "method": "problem.get", + "params": { + "output": "extend", + "selectTags": "extend", + "recent": ${recent}, + "sortfield": ["eventid"], + <#if hostId??> + "hostids":${hostId}, + + <#if timeFrom??> + "time_from":${timeFrom}, + + <#if timeTill??> + "time_till":${timeTill}, + + "tags":[{"tag": "__event__"}], + "filter":{ + "source":"0" + }, + "sortorder": "DESC" + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl new file mode 100644 index 00000000..fc505bf6 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/problem/problem.get.ftl @@ -0,0 +1,31 @@ +{ + "jsonrpc": "2.0", + "method": "problem.get", + "params": { + "output": "extend", + "selectAcknowledges": "extend", + "selectTags": "extend", + "selectSuppressionData": "extend", + "recent": ${recent}, + "sortfield": ["eventid"], + <#if hostId??> + "hostids":${hostId}, + + <#if timeFrom??> + "time_from":${timeFrom}, + + <#if timeTill??> + "time_till":${timeTill}, + + <#if severity?? && severity != ''> + "severities":${severity}, + + "tags":[{"tag": "__alarm__"}], + "filter":{ + "source":"0" + }, + "sortorder": "DESC" + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/proxy/proxy.create.ftl b/zeus-driver/src/main/resources/api-json/proxy/proxy.create.ftl new file mode 100644 index 00000000..623bbaae --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/proxy/proxy.create.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "proxy.create", + "params": { + "host": "${name}", + "status": "5" + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/proxy/proxy.delete.ftl b/zeus-driver/src/main/resources/api-json/proxy/proxy.delete.ftl new file mode 100644 index 00000000..fb224064 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/proxy/proxy.delete.ftl @@ -0,0 +1,13 @@ +{ + "jsonrpc": "2.0", + "method": "proxy.delete", + "params": [ + <#if hostIds??> + <#list hostIds as hostId> + "${hostId}"<#if hostId_has_next>, + + + ], + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/proxy/proxy.get.ftl b/zeus-driver/src/main/resources/api-json/proxy/proxy.get.ftl new file mode 100644 index 00000000..64c4ee9a --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/proxy/proxy.get.ftl @@ -0,0 +1,11 @@ +{ + "jsonrpc": "2.0", + "method": "proxy.get", + "params": { + "output": "extend", + "selectInterface": "extend", + "proxyids": ${proxyids} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/role/adminRole.get.ftl b/zeus-driver/src/main/resources/api-json/role/adminRole.get.ftl new file mode 100644 index 00000000..62fc5472 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/role/adminRole.get.ftl @@ -0,0 +1,12 @@ +{ + "jsonrpc": "2.0", + "method": "role.get", + "params": { + "output": "extend", + "filter": { + "name":"Super admin role" + } + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/role/guestRole.get.ftl b/zeus-driver/src/main/resources/api-json/role/guestRole.get.ftl new file mode 100644 index 00000000..0b0022b4 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/role/guestRole.get.ftl @@ -0,0 +1,12 @@ +{ + "jsonrpc": "2.0", + "method": "role.get", + "params": { + "output": "extend", + "filter": { + "name":"Guest role" + } + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/role/superAdminRole.get.ftl b/zeus-driver/src/main/resources/api-json/role/superAdminRole.get.ftl new file mode 100644 index 00000000..62fc5472 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/role/superAdminRole.get.ftl @@ -0,0 +1,12 @@ +{ + "jsonrpc": "2.0", + "method": "role.get", + "params": { + "output": "extend", + "filter": { + "name":"Super admin role" + } + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl index 2321d950..66bb1720 100644 --- a/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl +++ b/zeus-driver/src/main/resources/api-json/script/script.init.create.ftl @@ -1,12 +1,29 @@ { "jsonrpc": "2.0", "method": "script.create", - "params": { - "name": "__offline_status__", - "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\",\\"deviceStatus\\":\\"{EVENT.ID}\\"}' http://${zeusServerIp}:${zeusServerPort}/rest/device/webhook", - "type": 0, - "execute_on": 1 - }, + "params": [ + { + "name": "__offline_status__", <#--上下线 调用 webapp--> + "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\",\\"recovery\\":\\"{EVENT.RECOVERY.STATUS}\\"}' http://127.0.0.1:9090/device/status", + "type": 0, + "execute_on": 1 + },{ + "name": "__trigger_webhook__", <#-- 告警 回调 --> + "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\",\\"triggerName\\":\\"{TRIGGER.NAME}\\"}' http://127.0.0.1:9090/device/problem", + "type": 0, + "execute_on": 1 + },{ + "name": "__trigger_execute__", <#-- 执行 方法 --> + "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"triggerName\\":\\"{TRIGGER.NAME}\\",\\"triggerId\\":\\"{TRIGGER.ID}\\"}' http://127.0.0.1:12800/device/action/exec", + "type": 0, + "execute_on": 1 + },{ + "name": "__attr_event__", <#-- 属性事件 回调 --> + "command": "curl -H \\"Content-Type:application/json\\" -X POST --data '{\\"hostname\\":\\"{HOST.HOST}\\",\\"itemName\\":\\"{ITEM.NAME}\\"}' http://127.0.0.1:12800/device/event", + "type": 0, + "execute_on": 1 + } + ], "auth": "${userAuth}", "id": 1 } \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/script/script.offline.get.ftl b/zeus-driver/src/main/resources/api-json/script/script.offline.get.ftl index fbbb7015..c34fe440 100644 --- a/zeus-driver/src/main/resources/api-json/script/script.offline.get.ftl +++ b/zeus-driver/src/main/resources/api-json/script/script.offline.get.ftl @@ -3,10 +3,11 @@ "method": "script.get", "params": { "output": [ - "scriptid" + "scriptid", + "name" ], "search": { - "name": "__offline_status__" <#--在线状态--> + "name": "__" <#--在线状态--> } }, "auth": "${userAuth}", diff --git a/zeus-driver/src/main/resources/api-json/template/template.detail.get.ftl b/zeus-driver/src/main/resources/api-json/template/template.detail.get.ftl new file mode 100644 index 00000000..5620acb4 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/template/template.detail.get.ftl @@ -0,0 +1,13 @@ +{ + "jsonrpc": "2.0", + "method": "template.get", + "params": { + "output": "extend", + "selectTags":"extend", + "selectMacros":"extend", + "selectValueMaps":"extend", + "templateids":${templateid} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/template/template.get.ftl b/zeus-driver/src/main/resources/api-json/template/template.get.ftl index 5620acb4..82809eb9 100644 --- a/zeus-driver/src/main/resources/api-json/template/template.get.ftl +++ b/zeus-driver/src/main/resources/api-json/template/template.get.ftl @@ -3,9 +3,6 @@ "method": "template.get", "params": { "output": "extend", - "selectTags":"extend", - "selectMacros":"extend", - "selectValueMaps":"extend", "templateids":${templateid} }, "auth": "${userAuth}", diff --git a/zeus-driver/src/main/resources/api-json/transfer/create.ftl b/zeus-driver/src/main/resources/api-json/transfer/create.ftl new file mode 100644 index 00000000..70221f19 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/transfer/create.ftl @@ -0,0 +1,53 @@ +{ + "name": "${runnerName}", + "batch_interval": ${batchInterval}, + "batch_size": ${batchSize}, + "extra_info": false, + "reader": { + "log_path": "${logPath}", + "read_from": "oldest", + "datasource_tag": "datasource", + "encoding": "UTF-8", + "mode": "file" + }, + "cleaner": {}, + "parser": { + "type": "json", + "keep_raw_data": "false", + "name": "parser", + "disable_record_errdata": "false" + }, + "transforms": [ + { + "key": "groups,applications,datasource,name", + "type": "discard" + }, + { + "key": "type", + "mode": "keep", + "pattern": "^[0|3]$", + "type": "filter" + }, + { + "key": "source", + "override": false, + "type": "label", + "value": "s1" + } + ], + "senders": [{ + "http_sender_url": "http://127.0.0.1:12800/zabbix/data-transfer", + "http_sender_protocol": "json", + "http_sender_escape_html": "true", + "http_sender_csv_split": ",", + "http_sender_gzip": "true", + "http_sender_timeout": "30s", + "ft_strategy": "backup_only", + "ft_discard_failed_data": "false", + "ft_memory_channel": "false", + "ft_long_data_discard": "false", + "max_disk_used_bytes": "524288000", + "max_size_per_file": "104857600", + "sender_type": "http" + }] +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl new file mode 100644 index 00000000..3a5f7e29 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.ftl @@ -0,0 +1,41 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.create", + "params": [ + { + "description": "${ruleId}", <#--trigger name--> + <#if ruleFunction == "nodata"> + "expression": "nodata(/${deviceId}/${itemKey},${ruleCondition}) = 1", <#--下线规则,nodata = 1 --> + <#else> + "expression": "last(/${deviceId}/${itemKey}) ${ruleFunction} ${ruleCondition}", + + "recovery_mode": 2, + "type": 1, + "tags": [ + { + "tag": "__offline__", + "value": "{HOST.HOST}" <#--device id--> + } + ] + }, + { + "description": "${ruleId}", <#--trigger name--> + "recovery_mode": 2, + "type": 1, + <#if ruleFunctionRecovery == "nodata"> + "expression": "nodata(/${deviceId}/${itemKeyRecovery},${ruleConditionRecovery}) = 0", <#-- 上线规则 nodata = 0 --> + <#else> + "expression": "last(/${deviceId}/${itemKeyRecovery}) ${ruleFunctionRecovery} ${ruleConditionRecovery}", + + "tags": [ + { + "tag": "__online__", + "value": "{HOST.HOST}" <#--device id--> + } + ] + } + <#-- nodata(/Zabbix server/system.cpu.util[,nice],20s)=0 --> + ], + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl new file mode 100644 index 00000000..3bb7fef6 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/trigger/device.status.trigger.update.ftl @@ -0,0 +1,26 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.update", + "params": [ + { + "triggerid": "${triggerId}", + "description": "${ruleId}", <#--trigger name--> + <#if ruleFunction == "nodata"> + "expression": "nodata(/${deviceId}/${itemKey},${ruleCondition}) = 1" <#--下线规则,nodata = 1 --> + <#else> + "expression": "last(/${deviceId}/${itemKey}) ${ruleFunction} ${ruleCondition}" + + },{ + "triggerid": "${recoveryTriggerId}", + "description": "${ruleId}", <#--trigger name--> + <#if ruleFunctionRecovery == "nodata"> + "expression": "nodata(/${deviceId}/${itemKeyRecovery},${ruleConditionRecovery}) = 0" <#-- 上线规则 nodata = 0 --> + <#else> + "expression": "last(/${deviceId}/${itemKeyRecovery}) ${ruleFunctionRecovery} ${ruleConditionRecovery}" + + } + <#-- nodata(/Zabbix server/system.cpu.util[,nice],20s)=0 --> + ], + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.create.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.create.ftl index e69de29b..f37650fa 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.create.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.create.ftl @@ -0,0 +1,12 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.create", + "params": { + "description": "${triggerName}", + "expression": "${expression}", + "priority" : ${ruleLevel}, + "manual_close":1 + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.delete.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.delete.ftl index e69de29b..766425e2 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.delete.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.delete.ftl @@ -0,0 +1,9 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.delete", + "params": [ + ${triggerid} + ], + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.execute.create.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.execute.create.ftl new file mode 100644 index 00000000..edd139e2 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.execute.create.ftl @@ -0,0 +1,14 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.create", + "params": { + "description": "${triggerName}", + "expression": "${expression}", + "priority" : ${ruleLevel}, + "manual_close":1, + "recovery_mode":2, + "type":1 + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl index e69de29b..80a71344 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.get.ftl @@ -0,0 +1,22 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.get", + "params": { + "selectHosts":["host"], + "selectTags":["tag"], + <#if triggerIds??> + "triggerids":${triggerIds}, + + <#if host??> + "host":"${host}", + + <#if description??> + "filter":{ + "description":${description} + }, + + "output": "extend" + }, + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.last.create.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.last.create.ftl deleted file mode 100644 index 4ca18746..00000000 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.last.create.ftl +++ /dev/null @@ -1,14 +0,0 @@ -{ - "jsonrpc": "2.0", - "method": "trigger.create", - "params": [ - { - "description": "${triggerName}", - "expression": "last(/${hostName}/${itemKey})=${dataValue}", - "recovery_mode": 2, - "status": 1 - } - ], - "auth": "${userAuth}", - "id": 1 -} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.0.create.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.0.create.ftl deleted file mode 100644 index a6ecc32e..00000000 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.0.create.ftl +++ /dev/null @@ -1,14 +0,0 @@ -{ - "jsonrpc": "2.0", - "method": "trigger.create", - "params": [ - { - "description": "${triggerName}", <#--多长时间内有数据--> - "expression": "nodata(/${hostName}/${itemKey},${nodataTime})=0", - "recovery_mode": 2, - "status": 1 - } - ], - "auth": "${userAuth}", - "id": 1 -} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.1.create.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.1.create.ftl deleted file mode 100644 index f0442b46..00000000 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.nodata.1.create.ftl +++ /dev/null @@ -1,14 +0,0 @@ -{ - "jsonrpc": "2.0", - "method": "trigger.create", - "params": [ - { - "description": "${triggerName}", <#--多长时间内没数据--> - "expression": "nodata(/${hostName}/${itemKey},${nodataTime})=1", - "recovery_mode": 2, - "status": 1 - } - ], - "auth": "${userAuth}", - "id": 1 -} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.status.update.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.status.update.ftl new file mode 100644 index 00000000..f5a3aa98 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.status.update.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.update", + "params": { + "triggerid": "${triggerid}", + "status": ${status} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.tags.update.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.tags.update.ftl new file mode 100644 index 00000000..0e0078f1 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.tags.update.ftl @@ -0,0 +1,17 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.update", + "params": { + "triggerid": "${triggerId}", + "tags": [ + <#list tagMap?keys as key> + { + "tag": "${key}", + "value": "${tagMap[key]}" + }<#if key_has_next>, + + ] + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/trigger.update.ftl b/zeus-driver/src/main/resources/api-json/trigger/trigger.update.ftl index e69de29b..e520f230 100644 --- a/zeus-driver/src/main/resources/api-json/trigger/trigger.update.ftl +++ b/zeus-driver/src/main/resources/api-json/trigger/trigger.update.ftl @@ -0,0 +1,11 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.update", + "params": { + "triggerid": "${triggerId}", + "expression": "${expression}", + "priority" : ${ruleLevel} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/trigger/triggerAndTags.get.ftl b/zeus-driver/src/main/resources/api-json/trigger/triggerAndTags.get.ftl new file mode 100644 index 00000000..44f21db6 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/trigger/triggerAndTags.get.ftl @@ -0,0 +1,11 @@ +{ + "jsonrpc": "2.0", + "method": "trigger.get", + "params": { + "selectTags":"extend", + "triggerids":${triggerIds}, + "output": "extend" + }, + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/user/cookieUserAdd.ftl b/zeus-driver/src/main/resources/api-json/user/cookieUserAdd.ftl new file mode 100644 index 00000000..6eeaa644 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/user/cookieUserAdd.ftl @@ -0,0 +1,16 @@ +{ + "jsonrpc": "2.0", + "method": "user.create", + "params": { + "username": "cookie", + "passwd": "cookie", + "roleid": "${roleId}", + "usrgrps": [ + { + "usrgrpid": "${usrGrpId}" + } + ] + }, + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/user/cookieUserGet.ftl b/zeus-driver/src/main/resources/api-json/user/cookieUserGet.ftl new file mode 100644 index 00000000..b46b16f4 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/user/cookieUserGet.ftl @@ -0,0 +1,12 @@ +{ + "jsonrpc": "2.0", + "method": "user.get", + "params": { + "output": "extend", + "filter":{ + "username":"cookie" + } + }, + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/user/userAdd.ftl b/zeus-driver/src/main/resources/api-json/user/userAdd.ftl index e8962ea7..7f122bc1 100644 --- a/zeus-driver/src/main/resources/api-json/user/userAdd.ftl +++ b/zeus-driver/src/main/resources/api-json/user/userAdd.ftl @@ -4,7 +4,8 @@ "params": { "username": "${name}", "passwd": "${password}", - "roleid": "2", + "roleid": "${roleId}", + "autologout":"0s", "usrgrps": [ { "usrgrpid": "${usrGrpId}" diff --git a/zeus-driver/src/main/resources/api-json/user/userGet.ftl b/zeus-driver/src/main/resources/api-json/user/userGet.ftl new file mode 100644 index 00000000..8571ef25 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/user/userGet.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "user.get", + "params": { + "output": "extend", + "userids": ${userids} + }, + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/user/userUpdate.ftl b/zeus-driver/src/main/resources/api-json/user/userUpdate.ftl index c9e517bf..221bc7de 100644 --- a/zeus-driver/src/main/resources/api-json/user/userUpdate.ftl +++ b/zeus-driver/src/main/resources/api-json/user/userUpdate.ftl @@ -3,7 +3,7 @@ "method": "user.update", "params": { "userid": "${userId}", - "roleid": "2", + "roleid": "${roleId}", "usrgrps": [ { "usrgrpid": "${usrGrpId}" diff --git a/zeus-driver/src/main/resources/api-json/user/userUpdatePwd.ftl b/zeus-driver/src/main/resources/api-json/user/userUpdatePwd.ftl new file mode 100644 index 00000000..c2730823 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/user/userUpdatePwd.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "user.update", + "params": { + "userid": "${userId}", + "passwd": "${passwd}" + }, + "id": 1, + "auth": "${userAuth}" +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupCreate.ftl b/zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupCreate.ftl new file mode 100644 index 00000000..9cea5716 --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupCreate.ftl @@ -0,0 +1,14 @@ +{ + "jsonrpc": "2.0", + "method": "usergroup.create", + "params": { + "name": "cookie", + "gui_access": 0, + "rights": { + "permission": 2, + "id": "${hostGroupId}" + } + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupGet.ftl b/zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupGet.ftl new file mode 100644 index 00000000..fc3925ce --- /dev/null +++ b/zeus-driver/src/main/resources/api-json/usergroup/cookieUserGroupGet.ftl @@ -0,0 +1,13 @@ +{ + "jsonrpc": "2.0", + "method": "usergroup.get", + "params": { + "output": "extend", + "status": 0, + "filter":{ + "name":"cookie" + } + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/usergroup/userGroupGet.ftl b/zeus-driver/src/main/resources/api-json/usergroup/userGroupGet.ftl index e69de29b..575304a7 100644 --- a/zeus-driver/src/main/resources/api-json/usergroup/userGroupGet.ftl +++ b/zeus-driver/src/main/resources/api-json/usergroup/userGroupGet.ftl @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "method": "usergroup.get", + "params": { + "output": "extend", + "usrgrpids": ${usrgrpids} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-driver/src/main/resources/api-json/valuemap/valuemap.get.ftl b/zeus-driver/src/main/resources/api-json/valuemap/valuemap.get.ftl index e69de29b..ccfbbb42 100644 --- a/zeus-driver/src/main/resources/api-json/valuemap/valuemap.get.ftl +++ b/zeus-driver/src/main/resources/api-json/valuemap/valuemap.get.ftl @@ -0,0 +1,11 @@ +{ + "jsonrpc": "2.0", + "method": "valuemap.get", + "params": { + "output": "extend", + "selectMappings": "extend", + "valuemapids": ${valuemapids} + }, + "auth": "${userAuth}", + "id": 1 +} \ No newline at end of file diff --git a/zeus-iot-dist/pom.xml b/zeus-iot-dist/pom.xml new file mode 100644 index 00000000..37a67839 --- /dev/null +++ b/zeus-iot-dist/pom.xml @@ -0,0 +1,92 @@ + + + + com.zmops + zeus-iot + 1.0-beta + + 4.0.0 + + zmops-zeus-iot + pom + + + + + server + + true + + + + com.zmops + server-starter + ${project.version} + + + + + + webapp + + true + + + + com.zmops + zeus-starter + ${project.version} + + + + + + + + + maven-assembly-plugin + + + dist + package + + single + + + zeus-iot-bin + + ${project.basedir}/src/main/assembly/binary.xml + + + + + + true + posix + false + false + + + + maven-antrun-plugin + + + dist + package + + run + + + + + + + + + + + + + \ No newline at end of file diff --git a/zeus-iot-dist/src/main/assembly/binary.xml b/zeus-iot-dist/src/main/assembly/binary.xml new file mode 100644 index 00000000..70c7e121 --- /dev/null +++ b/zeus-iot-dist/src/main/assembly/binary.xml @@ -0,0 +1,71 @@ + + + + dist + + tar.gz + + + + ${project.basedir}/../dist-material/bin + bin + + *.sh + *.bat + **/*.sql + + 0755 + + + ${project.basedir}/../dist-material + config + + log4j2.xml + + + + ${project.basedir}/../iot-server/server-bootstrap/src/main/resources + + application.yml + + config + + + ${project.basedir}/../iot-server/server-starter/target/iot-server-assembly/iot-server/libs + + iot-server-libs + + + + + + ${project.basedir}/../zeus-starter/target/zeus-webapp.jar + webapp + 0644 + + + ${project.basedir}/../zeus-starter/src/main/assembly/webapp.yml + webapp + 0644 + + + diff --git a/zeus-iot-ui b/zeus-iot-ui new file mode 160000 index 00000000..eff93973 --- /dev/null +++ b/zeus-iot-ui @@ -0,0 +1 @@ +Subproject commit eff93973c8df6167c1c3dbd48add87cfaa584d49 diff --git a/zeus-alarm/pom.xml b/zeus-message/pom.xml similarity index 72% rename from zeus-alarm/pom.xml rename to zeus-message/pom.xml index 4cee762d..35ae3ae6 100644 --- a/zeus-alarm/pom.xml +++ b/zeus-message/pom.xml @@ -3,30 +3,38 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 - iot-alarm + zeus-message com.zmops zeus-common 1.0-beta - compile io.netty netty-codec-http - ${netty.version} + + + com.corundumstudio.socketio + netty-socketio + 1.7.12 com.zmops zeus-driver 1.0-beta - compile + + + com.sun.mail + javax.mail + 1.6.2 @@ -46,7 +54,7 @@ true - io.ebean.tile:enhancement:12.9.3 + io.ebean.tile:enhancement:12.11.3 diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/AlarmCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/AlarmCallback.java similarity index 71% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/AlarmCallback.java rename to zeus-message/src/main/java/com/zmops/iot/media/AlarmCallback.java index 3b963355..4af88add 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/AlarmCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/AlarmCallback.java @@ -1,5 +1,4 @@ - -package com.zmops.iot.mediaType; +package com.zmops.iot.media; import com.zmops.iot.domain.alarm.AlarmMessage; @@ -10,7 +9,7 @@ */ public interface AlarmCallback { - void doAlarm(List alarmMessage); + void doAlarm(List alarmMessage,Long tenantId); String getType(); } diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/AlarmMessageFormatter.java b/zeus-message/src/main/java/com/zmops/iot/media/AlarmMessageFormatter.java similarity index 96% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/AlarmMessageFormatter.java rename to zeus-message/src/main/java/com/zmops/iot/media/AlarmMessageFormatter.java index 899775dc..0ca7cc6d 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/AlarmMessageFormatter.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/AlarmMessageFormatter.java @@ -16,7 +16,7 @@ * */ -package com.zmops.iot.mediaType; +package com.zmops.iot.media; import java.util.ArrayList; @@ -30,7 +30,7 @@ * - Successful rate of endpoint {name} is lower than 75% */ public class AlarmMessageFormatter { - private List formatSegments; + private List formatSegments; private List valueFroms; public AlarmMessageFormatter(String format) { @@ -40,7 +40,7 @@ public AlarmMessageFormatter(String format) { formatSegments = new ArrayList<>(); this.valueFroms = new ArrayList<>(); boolean match = false; - int idx = 0; + int idx = 0; do { match = false; int start = format.indexOf("{", idx); diff --git a/zeus-message/src/main/java/com/zmops/iot/media/Notice.java b/zeus-message/src/main/java/com/zmops/iot/media/Notice.java new file mode 100644 index 00000000..04bcc343 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/Notice.java @@ -0,0 +1,27 @@ +package com.zmops.iot.media; + + +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.domain.sys.SysUser; + +import java.util.Map; + +public interface Notice { + int sms = 1; + int email = 2; + int wechat = 3; + int dingtalk = 4; + + /** + * 发送通知 + * + * @param receiver + * @param macroMap + * @return + */ + NoticeResult send(SysUser receiver, Map macroMap); + + int getType(); + + int getSilent(); +} diff --git a/zeus-message/src/main/java/com/zmops/iot/media/NoticeService.java b/zeus-message/src/main/java/com/zmops/iot/media/NoticeService.java new file mode 100644 index 00000000..d2f97863 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/NoticeService.java @@ -0,0 +1,49 @@ +package com.zmops.iot.media; + + +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.domain.messages.query.QNoticeRecord; +import com.zmops.iot.domain.sys.SysUser; +import com.zmops.iot.util.LocalDateTimeUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +@Service +public class NoticeService { + + + @Autowired + Collection notices; + + public Map notice(SysUser sysUser, Map macroMap,String triggerId) { +// Problem problem = problemMapper.selectById(Integer.parseInt(macroMap.get("${eventId}"))); + Map res = new HashMap<>(); + notices.forEach(notice -> { + int type = notice.getType(); + + QNoticeRecord eq = new QNoticeRecord().noticeType + .eq(type).creatTime + .ge(LocalDateTimeUtils.minu(LocalDateTime.now(), notice.getSilent(), ChronoUnit.MINUTES)) + .problemId.eq(triggerId); + + if (eq.findCount() > 0) { + return; + } + try { + NoticeResult send = notice.send(sysUser, macroMap); + if (send.getStatus() != NoticeResult.NoticeStatus.skipped) { + res.put(notice.getType(), send); + } + } catch (Exception e) { + e.printStackTrace(); + } + }); + return res; + } +} diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java similarity index 82% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java index c9df1217..bf9ba03c 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/WebhookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/WebhookCallback.java @@ -16,40 +16,24 @@ * */ -package com.zmops.iot.mediaType; +package com.zmops.iot.media; import com.zmops.iot.domain.alarm.AlarmMessage; -import io.netty.handler.codec.http.HttpHeaderValues; import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpHeaders; -import org.apache.http.HttpStatus; -import org.apache.http.StatusLine; import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; - -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.nio.charset.StandardCharsets; import java.util.List; -/** - * Use SkyWalking alarm webhook API call a remote endpoints. - */ @Slf4j public class WebhookCallback implements AlarmCallback { - private static final int HTTP_CONNECT_TIMEOUT = 1000; + private static final int HTTP_CONNECT_TIMEOUT = 1000; private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; - private static final int HTTP_SOCKET_TIMEOUT = 10000; + private static final int HTTP_SOCKET_TIMEOUT = 10000; private RequestConfig requestConfig; @Override - public void doAlarm(List alarmMessage) { + public void doAlarm(List alarmMessage,Long tenantId) { } diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java similarity index 91% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkHookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java index 3355bc0a..71b1fd6c 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkHookCallback.java @@ -16,10 +16,10 @@ * */ -package com.zmops.iot.mediaType.dingtalk; +package com.zmops.iot.media.dingtalk; import com.zmops.iot.domain.alarm.AlarmMessage; -import com.zmops.iot.mediaType.AlarmCallback; +import com.zmops.iot.media.AlarmCallback; import io.netty.handler.codec.http.HttpHeaderValues; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; @@ -48,17 +48,14 @@ import java.util.Base64; import java.util.List; -/** - * Use SkyWalking alarm dingtalk webhook API. - */ @Slf4j @Service public class DingtalkHookCallback implements AlarmCallback { - private static final int HTTP_CONNECT_TIMEOUT = 1000; - private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; - private static final int HTTP_SOCKET_TIMEOUT = 10000; - private RequestConfig requestConfig; + private static final int HTTP_CONNECT_TIMEOUT = 1000; + private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; + private static final int HTTP_SOCKET_TIMEOUT = 10000; + private RequestConfig requestConfig; @Autowired DingtalkSettingService dingtalkSettingService; @@ -75,8 +72,8 @@ public DingtalkHookCallback() { * Send alarm message if the settings not empty */ @Override - public void doAlarm(List alarmMessages) { - DingtalkSettings dingtalkSettings = dingtalkSettingService.get(); + public void doAlarm(List alarmMessages,Long tenantId) { + DingtalkSettings dingtalkSettings = dingtalkSettingService.get(tenantId); if (dingtalkSettings == null || dingtalkSettings.getWebhooks().isEmpty()) { return; } @@ -123,7 +120,7 @@ private String getSignUrl(DingtalkSettings.WebHookUrl webHookUrl) { */ private String sign(final Long timestamp, String secret) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException { String stringToSign = timestamp + "\n" + secret; - Mac mac = Mac.getInstance("HmacSHA256"); + Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8)); return URLEncoder.encode(new String(Base64.getEncoder().encode(signData)), StandardCharsets.UTF_8.name()); diff --git a/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettingService.java b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettingService.java new file mode 100644 index 00000000..ee7822a1 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettingService.java @@ -0,0 +1,63 @@ +package com.zmops.iot.media.dingtalk; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.alarm.MediaTypeSetting; +import com.zmops.iot.domain.alarm.query.QMediaTypeSetting; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author yefei + **/ +@Service +public class DingtalkSettingService { + + private volatile DingtalkSettings instance; + + private volatile Map instanceMap = new ConcurrentHashMap<>(); + + public DingtalkSettings get(Long tenantId) { + if (null == tenantId) { + return getOne(); + } else { + return getFromMap(tenantId); + } + + } + + private DingtalkSettings getFromMap(Long tenantId) { + if (instanceMap.get(tenantId) != null) { + return instanceMap.get(tenantId); + } + MediaTypeSetting setting = new QMediaTypeSetting().type.eq("dingtalk").tenantId.eq(tenantId).findOne(); + DingtalkSettings instance = buildDingdingSetting(setting); + instanceMap.put(tenantId,instance); + return instance; + } + + private DingtalkSettings getOne() { + if (instance != null) { + return instance; + } + MediaTypeSetting setting = new QMediaTypeSetting().type.eq("dingtalk").tenantId.isNull().findOne(); + + return instance = buildDingdingSetting(setting); + } + + private DingtalkSettings buildDingdingSetting(MediaTypeSetting setting) { + JSONObject jsonObject = JSONObject.parseObject(setting.getWebhooks()); + String secret = Optional.ofNullable(jsonObject.getString("secret")).orElse(""); + String url = Optional.ofNullable(jsonObject.getString("url")).orElse(""); + return DingtalkSettings.builder().textTemplate(setting.getTemplate()) + .webhooks(Arrays.asList(new DingtalkSettings.WebHookUrl(secret, url))).build(); + } + + + public void test() { + + } +} diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettings.java b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettings.java similarity index 82% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettings.java rename to zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettings.java index 8b7a48f2..1132b449 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/dingtalk/DingtalkSettings.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/dingtalk/DingtalkSettings.java @@ -1,6 +1,4 @@ - - -package com.zmops.iot.mediaType.dingtalk; +package com.zmops.iot.media.dingtalk; import lombok.*; @@ -14,7 +12,7 @@ @Data public class DingtalkSettings { - private String textTemplate; + private String textTemplate; @Builder.Default private List webhooks = new ArrayList<>(); diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java similarity index 91% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java index 623359b3..c87055b4 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuHookCallback.java @@ -16,15 +16,16 @@ * */ -package com.zmops.iot.mediaType.feishu; +package com.zmops.iot.media.feishu; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.AlarmMessage; -import com.zmops.iot.mediaType.AlarmCallback; +import com.zmops.iot.media.AlarmCallback; import com.zmops.iot.util.ToolUtil; import io.netty.handler.codec.http.HttpHeaderValues; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.binary.Base64; import org.apache.http.HttpHeaders; import org.apache.http.HttpStatus; import org.apache.http.StatusLine; @@ -38,26 +39,25 @@ import org.apache.http.util.EntityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.apache.commons.codec.binary.Base64; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.util.*; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; -/** - * Use SkyWalking alarm feishu webhook API. - */ @Slf4j @Service public class FeishuHookCallback implements AlarmCallback { - private static final int HTTP_CONNECT_TIMEOUT = 1000; + private static final int HTTP_CONNECT_TIMEOUT = 1000; private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; - private static final int HTTP_SOCKET_TIMEOUT = 10000; + private static final int HTTP_SOCKET_TIMEOUT = 10000; @Autowired FeishuSettingService feishuSettingService; @@ -81,8 +81,8 @@ public FeishuHookCallback() { * Send alarm message if the settings not empty */ @Override - public void doAlarm(List alarmMessages) { - FeishuSettings feishuSettings = feishuSettingService.get(); + public void doAlarm(List alarmMessages,Long tenantId) { + FeishuSettings feishuSettings = feishuSettingService.get(tenantId); if (feishuSettings == null || feishuSettings.getWebhooks().isEmpty()) { return; } @@ -111,8 +111,8 @@ public void doAlarm(List alarmMessages) { */ private String getRequestBody(FeishuSettings.WebHookUrl webHookUrl, AlarmMessage alarmMessage, String requestBody) { - JSONObject jsonObject = JSONObject.parseObject(requestBody); - Map content = buildContent(jsonObject); + JSONObject jsonObject = JSONObject.parseObject(requestBody); + Map content = buildContent(jsonObject); if (ToolUtil.isNotEmpty(webHookUrl.getSecret())) { Long timestamp = System.currentTimeMillis() / 1000; content.put("timestamp", timestamp); @@ -132,7 +132,7 @@ private Map buildContent(JSONObject jsonObject) { Map content = new HashMap<>(); content.put("msg_type", jsonObject.getString("msg_type")); if (jsonObject.get("ats") != null) { - String ats = jsonObject.getString("ats"); + String ats = jsonObject.getString("ats"); String text = jsonObject.getJSONObject("content").getString("text"); List collect = Arrays.stream(ats.split(",")) .map(String::trim).collect(Collectors.toList()); @@ -150,7 +150,7 @@ private Map buildContent(JSONObject jsonObject) { */ private String sign(final Long timestamp, String secret) throws NoSuchAlgorithmException, InvalidKeyException { String stringToSign = timestamp + "\n" + secret; - Mac mac = Mac.getInstance("HmacSHA256"); + Mac mac = Mac.getInstance("HmacSHA256"); mac.init(new SecretKeySpec(stringToSign.getBytes(), "HmacSHA256")); byte[] signData = mac.doFinal(); return Base64.encodeBase64String(signData); diff --git a/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettingService.java b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettingService.java new file mode 100644 index 00000000..35adebff --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettingService.java @@ -0,0 +1,62 @@ +package com.zmops.iot.media.feishu; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.alarm.MediaTypeSetting; +import com.zmops.iot.domain.alarm.query.QMediaTypeSetting; +import com.zmops.iot.media.dingtalk.DingtalkSettings; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author yefei + **/ +@Service +public class FeishuSettingService { + + private volatile FeishuSettings instance; + + private volatile Map instanceMap = new ConcurrentHashMap<>(); + + public FeishuSettings get(Long tenantId) { + if (null == tenantId) { + return getOne(); + } else { + return getFromMap(tenantId); + } + } + + private FeishuSettings getFromMap(Long tenantId) { + if (instanceMap.get(tenantId) != null) { + return instanceMap.get(tenantId); + } + MediaTypeSetting setting = new QMediaTypeSetting().type.eq("feishu").tenantId.eq(tenantId).findOne(); + FeishuSettings instance = buildFeishuSetting(setting); + instanceMap.put(tenantId,instance); + return instance; + } + + private FeishuSettings getOne() { + if (instance != null) { + return instance; + } + MediaTypeSetting setting = new QMediaTypeSetting().type.eq("feishu").tenantId.isNull().findOne(); + + return instance = buildFeishuSetting(setting); + } + + private FeishuSettings buildFeishuSetting(MediaTypeSetting setting) { + JSONObject jsonObject = JSONObject.parseObject(setting.getWebhooks()); + String secret = Optional.ofNullable(jsonObject.getString("secret")).orElse(""); + String url = Optional.ofNullable(jsonObject.getString("url")).orElse(""); + return FeishuSettings.builder().textTemplate(setting.getTemplate()) + .webhooks(Arrays.asList(new FeishuSettings.WebHookUrl(secret, url))).build(); + } + + public void test() { + + } +} diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettings.java b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettings.java similarity index 93% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettings.java rename to zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettings.java index 39a7c670..4667f5e0 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/feishu/FeishuSettings.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/feishu/FeishuSettings.java @@ -16,7 +16,7 @@ * */ -package com.zmops.iot.mediaType.feishu; +package com.zmops.iot.media.feishu; import lombok.*; @@ -31,7 +31,7 @@ @ToString public class FeishuSettings { - private String textTemplate; + private String textTemplate; @Builder.Default private List webhooks = new ArrayList<>(); diff --git a/zeus-message/src/main/java/com/zmops/iot/media/mail/MailMessage.java b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailMessage.java new file mode 100644 index 00000000..2bfe74aa --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailMessage.java @@ -0,0 +1,53 @@ +package com.zmops.iot.media.mail; + +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 邮件内容 + * @author yefei + * + **/ +@Data +@NoArgsConstructor +public class MailMessage { + /** + * 收件人名称 + */ + private String user; + /** + * 告警信息 + */ + private String message; + /** + * 服务 + */ + private String server; + /** + * 对象类型 + */ + private String objectType; + /** + * 告警规则 + */ + private String alarmRule; + /** + * 告警等级 + */ + private String level; + + /** + * 告警时间 + */ + private String time; + + /** + * ip + */ + private String ip; + + /** + * 指标值 + */ + private String table; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/media/mail/MailNotice.java b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailNotice.java new file mode 100644 index 00000000..0cd705d2 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailNotice.java @@ -0,0 +1,11 @@ +package com.zmops.iot.media.mail; + + +import com.zmops.iot.domain.messages.MailSetting; +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.media.Notice; + +public interface MailNotice extends Notice { + + NoticeResult test(MailSetting setting, String receiver); +} diff --git a/zeus-message/src/main/java/com/zmops/iot/media/mail/MailNoticer.java b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailNoticer.java new file mode 100644 index 00000000..bd84c62a --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailNoticer.java @@ -0,0 +1,106 @@ +package com.zmops.iot.media.mail; + + +import com.zmops.iot.domain.messages.MailSetting; +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.domain.sys.SysUser; +import com.zmops.iot.util.ToolUtil; +import freemarker.template.Template; +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; +import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; +import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/** + * @author yefei + **/ +@Service +public class MailNoticer implements MailNotice { + + @Autowired + MailSettingService mailSettingService; + @Autowired + private FreeMarkerConfigurer configurer; + + @Override + public NoticeResult test(MailSetting setting, String receiver) { + return MailUtils.test(setting, receiver); + } + + + @Override + public NoticeResult send(SysUser receiver, Map macroMap) { + if (ToolUtil.isEmpty(receiver.getEmail())) { + return NoticeResult.skipped(); + } + MailSetting setting = mailSettingService.get(); + if (setting == null) { + return NoticeResult.skipped(); + } + if (!setting.getSeverity().contains(macroMap.get("${severity}"))) { + return NoticeResult.skipped(); + } + Integer problemId = Integer.parseInt(macroMap.get("${problemId}")); + + String alarmInfo = "【Zeus】 触发[${level}]告警“[${context}]”,[${time}]。请及时处理。"; + for (Map.Entry entry : macroMap.entrySet()) { + String value = Optional.ofNullable(entry.getValue()).orElse(""); + alarmInfo = alarmInfo.replace(entry.getKey(), value); + } + + try { + MailUtils.send(setting, mimeMessage -> { + try { + String subject = "触发${level}告警", + content = "【Zeus】 触发[${level}]告警“[${context}]”,[${time}]。请及时处理。\n"; + for (Map.Entry entry : macroMap.entrySet()) { + String value = Optional.ofNullable(entry.getValue()).orElse(""); + subject = subject.replace(entry.getKey(), value); + content = content.replace(entry.getKey(), value); + } + MailMessage message = new MailMessage(); + message.setUser(receiver.getName()); + message.setMessage(content); + message.setAlarmRule(macroMap.get("${metricName}")); + message.setLevel(macroMap.get("${level}")); + message.setObjectType(macroMap.get("${typeName}")); + message.setServer(macroMap.get("${topMoType}")); + message.setTime(macroMap.get("${time}")); +// message.setTable(values.toString()); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); + helper.setFrom(setting.getSender());//发送者 + helper.setTo(receiver.getEmail());//接收者 + helper.setSubject(subject);//邮件标题 + Map model = new HashMap<>(); + model.put("params", message); + Template template = configurer.getConfiguration().getTemplate("argusAlarmEmailTemplate.html", "UTF-8"); + String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, model); + helper.setText(text, true); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } catch (Exception e) { + e.printStackTrace(); + return NoticeResult.failed("发送失败: " + StringUtils.left(e.getMessage(), 100), alarmInfo, receiver.getEmail()); + } + return NoticeResult.success(alarmInfo, receiver.getEmail()); + } + + @Override + public int getType() { + return email; + } + + @Override + public int getSilent() { + MailSetting setting = mailSettingService.get(); + return Optional.ofNullable(setting.getSilent()).orElse(3); + } +} diff --git a/zeus-message/src/main/java/com/zmops/iot/media/mail/MailSettingService.java b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailSettingService.java new file mode 100644 index 00000000..006f0178 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailSettingService.java @@ -0,0 +1,19 @@ +package com.zmops.iot.media.mail; + + +import com.zmops.iot.domain.messages.MailParam; +import com.zmops.iot.domain.messages.MailSetting; +import com.zmops.iot.domain.messages.NoticeResult; + +/** + * @author yefei + * @email yefei@zmops.com + * @date Created in 2020/11/10 18:58 + * @Description + */ +public interface MailSettingService { + + MailSetting get(); + NoticeResult test(MailParam mailTestVo); + Integer updateSettings(MailSetting mailTestVo); +} diff --git a/zeus-message/src/main/java/com/zmops/iot/media/mail/MailUtils.java b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailUtils.java new file mode 100644 index 00000000..ef3fc77f --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/media/mail/MailUtils.java @@ -0,0 +1,95 @@ +package com.zmops.iot.media.mail; + +import com.sun.mail.util.MailSSLSocketFactory; +import com.zmops.iot.domain.messages.MailSetting; +import com.zmops.iot.domain.messages.NoticeResult; +import org.springframework.mail.javamail.MimeMessageHelper; + +import javax.mail.Authenticator; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.MimeMessage; +import java.security.GeneralSecurityException; +import java.util.Properties; +import java.util.function.Consumer; + +/** + * @author yefei + *

+ * 邮件发送工具类 + **/ +public class MailUtils { + + public static void send(MailSetting setting, Consumer consumer) + throws GeneralSecurityException, javax.mail.MessagingException { + + Properties prop = new Properties(); + prop.setProperty("mail.smtp.host", setting.getHost()); + prop.setProperty("mail.smtp.port", setting.getPort().toString()); + prop.setProperty("mail.transport.protocol", "smtp"); + prop.setProperty("mail.smtp.auth", "true"); + prop.setProperty("mail.smtp.connectiontimeout", "2000"); + prop.setProperty("mail.smtp.writetimeout", "5000"); + + if (setting.sslAvailable()) { + MailSSLSocketFactory sf = new MailSSLSocketFactory(); + sf.setTrustAllHosts(true); + prop.put("mail.smtp.ssl.enable", "true"); + prop.put("mail.smtp.ssl.socketFactory", sf); + } + + if (setting.tlsAvailable()) { + prop.put("mail.smtp.ssl.checkserveridentity", "false"); + prop.put("mail.smtp.ssl.trust", setting.getHost()); + prop.put("mail.smtp.host", setting.getHost()); + prop.put("mail.smtp.starttls.enable", "true"); + } + + Session session = Session.getInstance(prop, new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(setting.getAccount(), setting.getPassword()); + } + }); + + Transport transport = session.getTransport(); + transport.connect(setting.getHost(), setting.getAccount(), setting.getPassword()); + + MimeMessage mimeMessage = new MimeMessage(session); + consumer.accept(mimeMessage); + + transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients()); + transport.close(); + } + + + /** + * 仅限于页面测试功能调用 + * + * @param setting + * @param receiver + * @return + */ + public static NoticeResult test(MailSetting setting, String receiver) { + try { + send(setting, mimeMessage -> { + try { + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); + helper.setFrom(setting.getSender()); + helper.setTo(receiver); + helper.setSubject("Zesu-iot邮件测试"); + helper.setText("这是一封Zesu-iot测试邮件,请不要回复。", false); + } catch (javax.mail.MessagingException e) { + e.printStackTrace(); + } + }); + return NoticeResult.success(); + } catch (Exception e) { + e.printStackTrace(); + return NoticeResult.failed(e.getMessage()); + } + } + + +} diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java similarity index 70% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatHookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java index 7f1c7343..0693f82e 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatHookCallback.java @@ -16,10 +16,10 @@ * */ -package com.zmops.iot.mediaType.wechat; +package com.zmops.iot.media.wechat; import com.zmops.iot.domain.alarm.AlarmMessage; -import com.zmops.iot.mediaType.AlarmCallback; +import com.zmops.iot.media.AlarmCallback; import io.netty.handler.codec.http.HttpHeaderValues; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpHeaders; @@ -31,23 +31,19 @@ import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.IOException; import java.util.List; -/** - * Use SkyWalking alarm wechat webhook API. - */ @Slf4j @Service public class WechatHookCallback implements AlarmCallback { - private static final int HTTP_CONNECT_TIMEOUT = 1000; - private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; - private static final int HTTP_SOCKET_TIMEOUT = 10000; - private RequestConfig requestConfig; + private static final int HTTP_CONNECT_TIMEOUT = 1000; + private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; + private static final int HTTP_SOCKET_TIMEOUT = 10000; + private RequestConfig requestConfig; @Autowired WechatSettingService wechatSettingService; @@ -66,28 +62,28 @@ public WechatHookCallback() { } @Override - public void doAlarm(List alarmMessages) { - WechatSettings wechatSettings = wechatSettingService.get(); - if (wechatSettings == null || wechatSettings.getWebhooks().isEmpty()) { - return; - } - CloseableHttpClient httpClient = HttpClients.custom().build(); - try { - wechatSettings.getWebhooks().forEach(url -> { - alarmMessages.forEach(alarmMessage -> { - String requestBody = String.format( - wechatSettings.getTextTemplate(), alarmMessage.getAlarmMessage() - ); - sendAlarmMessage(httpClient, url, requestBody); - }); - }); - } finally { - try { - httpClient.close(); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } + public void doAlarm(List alarmMessages,Long tenantId) { +// WechatSettings wechatSettings = wechatSettingService.get(tenantId); +// if (wechatSettings == null || wechatSettings.getWebhooks().isEmpty()) { +// return; +// } +// CloseableHttpClient httpClient = HttpClients.custom().build(); +// try { +// wechatSettings.getWebhooks().forEach(url -> { +// alarmMessages.forEach(alarmMessage -> { +// String requestBody = String.format( +// wechatSettings.getTextTemplate(), alarmMessage.getAlarmMessage() +// ); +// sendAlarmMessage(httpClient, url, requestBody); +// }); +// }); +// } finally { +// try { +// httpClient.close(); +// } catch (IOException e) { +// log.error(e.getMessage(), e); +// } +// } } private void sendAlarmMessage(CloseableHttpClient httpClient, String url, String requestBody) { diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatSettingService.java similarity index 59% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java rename to zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatSettingService.java index e0fae096..9db4f892 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettingService.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatSettingService.java @@ -1,13 +1,13 @@ -package com.zmops.iot.mediaType.wechat; +package com.zmops.iot.media.wechat; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.MediaTypeSetting; import com.zmops.iot.domain.alarm.query.QMediaTypeSetting; -import com.zmops.iot.mediaType.dingtalk.DingtalkSettings; import org.springframework.stereotype.Service; import java.util.Arrays; -import java.util.Optional; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * @author yefei @@ -17,8 +17,24 @@ public class WechatSettingService { private volatile WechatSettings instance; - public WechatSettings get() { - return getOne(); + private volatile Map instanceMap = new ConcurrentHashMap<>(); + + public WechatSettings get(Long tenantId) { + if (null == tenantId) { + return getOne(); + } else { + return getFromMap(tenantId); + } + } + + private WechatSettings getFromMap(Long tenantId) { + if (instanceMap.get(tenantId) != null) { + return instanceMap.get(tenantId); + } + MediaTypeSetting setting = new QMediaTypeSetting().type.eq("wechat").tenantId.eq(tenantId).findOne(); + WechatSettings instance = buildWechatSetting(setting); + instanceMap.put(tenantId, instance); + return instance; } private WechatSettings getOne() { diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettings.java b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatSettings.java similarity index 96% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettings.java rename to zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatSettings.java index 7f5f278c..0af12b56 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/wechat/WechatSettings.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/wechat/WechatSettings.java @@ -16,7 +16,7 @@ * */ -package com.zmops.iot.mediaType.wechat; +package com.zmops.iot.media.wechat; import lombok.*; diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkHookCallback.java b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java similarity index 82% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkHookCallback.java rename to zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java index 2b2a2743..8f93b342 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkHookCallback.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkHookCallback.java @@ -16,13 +16,13 @@ * */ -package com.zmops.iot.mediaType.welink; +package com.zmops.iot.media.welink; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.AlarmMessage; -import com.zmops.iot.mediaType.AlarmCallback; +import com.zmops.iot.media.AlarmCallback; import io.netty.handler.codec.http.HttpHeaderValues; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpHeaders; @@ -43,9 +43,6 @@ import java.nio.charset.StandardCharsets; import java.util.*; -/** - * Use SkyWalking alarm WeLink webhook API. - */ @Slf4j @Service public class WeLinkHookCallback implements AlarmCallback { @@ -53,10 +50,10 @@ public class WeLinkHookCallback implements AlarmCallback { @Autowired WeLinkSettingService weLinkSettingService; - private static final int HTTP_CONNECT_TIMEOUT = 1000; - private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; - private static final int HTTP_SOCKET_TIMEOUT = 10000; - private final RequestConfig requestConfig; + private static final int HTTP_CONNECT_TIMEOUT = 1000; + private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; + private static final int HTTP_SOCKET_TIMEOUT = 10000; + private final RequestConfig requestConfig; public WeLinkHookCallback() { this.requestConfig = RequestConfig.custom() @@ -70,22 +67,22 @@ public WeLinkHookCallback() { * Send alarm message if the settings not empty */ @Override - public void doAlarm(List alarmMessages) { - WeLinkSettings weLinkSettings = weLinkSettingService.get(); - if (weLinkSettings == null || weLinkSettings.getWebhooks().isEmpty()) { - return; - } - weLinkSettings.getWebhooks().forEach(webHookUrl -> { - String accessToken = getAccessToken(webHookUrl); - alarmMessages.forEach(alarmMessage -> { - String content = String.format( - Locale.US, - weLinkSettings.getTextTemplate(), - alarmMessage.getAlarmMessage() - ); - sendAlarmMessage(webHookUrl, accessToken, content); - }); - }); + public void doAlarm(List alarmMessages,Long tenantId) { +// WeLinkSettings weLinkSettings = weLinkSettingService.get(tenantId); +// if (weLinkSettings == null || weLinkSettings.getWebhooks().isEmpty()) { +// return; +// } +// weLinkSettings.getWebhooks().forEach(webHookUrl -> { +// String accessToken = getAccessToken(webHookUrl); +// alarmMessages.forEach(alarmMessage -> { +// String content = String.format( +// Locale.US, +// weLinkSettings.getTextTemplate(), +// alarmMessage.getAlarmMessage() +// ); +// sendAlarmMessage(webHookUrl, accessToken, content); +// }); +// }); } /** @@ -117,8 +114,8 @@ private void sendAlarmMessage(WeLinkSettings.WebHookUrl webHookUrl, String acces */ private String getAccessToken(WeLinkSettings.WebHookUrl webHookUrl) { String accessTokenUrl = webHookUrl.getAccessTokenUrl(); - String clientId = webHookUrl.getClientId(); - String clientSecret = webHookUrl.getClientSecret(); + String clientId = webHookUrl.getClientId(); + String clientSecret = webHookUrl.getClientSecret(); String response = sendPostRequest( accessTokenUrl, Collections.emptyMap(), String.format(Locale.US, "{\"client_id\":%s,\"client_secret\":%s}", clientId, clientSecret) diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettingService.java similarity index 92% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java rename to zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettingService.java index 5541b056..aab1e3b1 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettingService.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettingService.java @@ -1,9 +1,8 @@ -package com.zmops.iot.mediaType.welink; +package com.zmops.iot.media.welink; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.alarm.MediaTypeSetting; import com.zmops.iot.domain.alarm.query.QMediaTypeSetting; -import com.zmops.iot.mediaType.wechat.WechatSettings; import org.springframework.stereotype.Service; import java.util.Arrays; @@ -17,7 +16,7 @@ public class WeLinkSettingService { private volatile WeLinkSettings instance; - public WeLinkSettings get() { + public WeLinkSettings get(Long tenantId) { return getOne(); } diff --git a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettings.java b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettings.java similarity index 75% rename from zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettings.java rename to zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettings.java index 272b757e..04d06869 100644 --- a/zeus-alarm/src/main/java/com/zmops/iot/mediaType/welink/WeLinkSettings.java +++ b/zeus-message/src/main/java/com/zmops/iot/media/welink/WeLinkSettings.java @@ -1,5 +1,4 @@ - -package com.zmops.iot.mediaType.welink; +package com.zmops.iot.media.welink; import lombok.*; @@ -14,7 +13,7 @@ @ToString public class WeLinkSettings { - private String textTemplate; + private String textTemplate; @Builder.Default private List webhooks = new ArrayList<>(); @@ -36,12 +35,12 @@ public static class WebHookUrl { private final String groupIds; public static WebHookUrl generateFromMap(Map params) { - String clientId = params.get("clientId"); - String clientSecret = params.get("clientSecret"); + String clientId = params.get("clientId"); + String clientSecret = params.get("clientSecret"); String accessTokenUrl = params.get("accessTokenUrl"); - String messageUrl = params.get("messageUrl"); - String groupIds = params.get("groupIds"); - String robotName = params.getOrDefault("robotName", "robot"); + String messageUrl = params.get("messageUrl"); + String groupIds = params.get("groupIds"); + String robotName = params.getOrDefault("robotName", "robot"); return new WebHookUrl(clientId, clientSecret, accessTokenUrl, messageUrl, robotName, groupIds ); diff --git a/zeus-message/src/main/java/com/zmops/iot/message/config/Event.java b/zeus-message/src/main/java/com/zmops/iot/message/config/Event.java new file mode 100644 index 00000000..15aa7bfa --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/config/Event.java @@ -0,0 +1,27 @@ +package com.zmops.iot.message.config; + +/** + * @author nantian created at 2021/9/26 23:15 + */ +public interface Event { + + /** + * 聊天事件 + */ + String CHAT = "chat"; + + /** + * 广播消息 + */ + String BROADCAST = "broadcast"; + + /** + * 群聊 + */ + String GROUP = "group"; + + /** + * 加入群聊 + */ + String JOIN = "join"; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/config/MessageServerConfig.java b/zeus-message/src/main/java/com/zmops/iot/message/config/MessageServerConfig.java new file mode 100644 index 00000000..439df834 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/config/MessageServerConfig.java @@ -0,0 +1,46 @@ +package com.zmops.iot.message.config; + +import cn.hutool.core.util.StrUtil; +import com.corundumstudio.socketio.SocketConfig; +import com.corundumstudio.socketio.SocketIOServer; +import com.corundumstudio.socketio.annotation.SpringAnnotationScanner; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author nantian created at 2021/9/26 22:39 + */ + +@Configuration +@EnableConfigurationProperties({SocketIoConfig.class}) +public class MessageServerConfig { + + @Bean + public SocketIOServer server(SocketIoConfig socketIoConfig) { + com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration(); + + SocketConfig socketConfig = new SocketConfig(); + socketConfig.setReuseAddress(true); + config.setSocketConfig(socketConfig); + config.setHostname(socketIoConfig.getHost()); + config.setPort(socketIoConfig.getPort()); + + config.setAuthorizationListener(data -> { + String token = data.getSingleUrlParam("token"); + return StrUtil.isNotBlank(token); + }); + + return new SocketIOServer(config); + } + + + /** + * Spring 扫描自定义注解 + */ + @Bean + public SpringAnnotationScanner springAnnotationScanner(SocketIOServer server) { + return new SpringAnnotationScanner(server); + } + +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/config/SocketIoConfig.java b/zeus-message/src/main/java/com/zmops/iot/message/config/SocketIoConfig.java new file mode 100644 index 00000000..8d3d2d9f --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/config/SocketIoConfig.java @@ -0,0 +1,24 @@ +package com.zmops.iot.message.config; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * @author nantian created at 2021/9/26 22:47 + */ +@Getter +@Setter +@ConfigurationProperties(prefix = "socketio.server") +public class SocketIoConfig { + + /** + * 端口号 + */ + private Integer port; + + /** + * host + */ + private String host; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/config/UserClientMap.java b/zeus-message/src/main/java/com/zmops/iot/message/config/UserClientMap.java new file mode 100644 index 00000000..a74f8380 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/config/UserClientMap.java @@ -0,0 +1,35 @@ +package com.zmops.iot.message.config; + +import cn.hutool.core.collection.CollUtil; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +@Component +public class UserClientMap { + + public static final ConcurrentHashMap DB = new ConcurrentHashMap<>(); + + public List findAll() { + return CollUtil.newArrayList(DB.values()); + } + + + public Optional findByUserId(String userId) { + return Optional.ofNullable(DB.get(userId)); + } + + + public void save(String userId, UUID sessionId) { + DB.put(userId, sessionId); + } + + + public void deleteByUserId(String userId) { + DB.remove(userId); + } + +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/controller/SocketIoController.java b/zeus-message/src/main/java/com/zmops/iot/message/controller/SocketIoController.java new file mode 100644 index 00000000..6071e383 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/controller/SocketIoController.java @@ -0,0 +1,35 @@ +package com.zmops.iot.message.controller; + +import com.zmops.iot.message.handler.MessageEventHandler; +import com.zmops.iot.message.payload.BroadcastMessageRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * @author nantian created at 2021/9/27 0:16 + */ + +@Slf4j +@RestController +@RequestMapping("/send") +public class SocketIoController { + + @Autowired + private MessageEventHandler messageHandler; + + /** + * just for test + * + * @param message + */ + @PostMapping("/broadcast") + public void broadcast(@RequestBody BroadcastMessageRequest message) { + messageHandler.sendToBroadcast(message); + } + + @PostMapping("/sendToUser") + public void sendToUser(@RequestParam("userId") String userId,@RequestParam("msg") String msg) { + messageHandler.sendToUser(userId,msg); + } +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java new file mode 100644 index 00000000..81177e7c --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/handler/MessageEventHandler.java @@ -0,0 +1,116 @@ +package com.zmops.iot.message.handler; + +import com.corundumstudio.socketio.AckRequest; +import com.corundumstudio.socketio.SocketIOClient; +import com.corundumstudio.socketio.SocketIOServer; +import com.corundumstudio.socketio.annotation.OnConnect; +import com.corundumstudio.socketio.annotation.OnDisconnect; +import com.corundumstudio.socketio.annotation.OnEvent; +import com.zmops.iot.message.config.Event; +import com.zmops.iot.message.config.UserClientMap; +import com.zmops.iot.message.payload.BroadcastMessageRequest; +import com.zmops.iot.message.payload.GroupMessageRequest; +import com.zmops.iot.message.payload.JoinRequest; +import com.zmops.iot.message.payload.SingleMessageRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.UUID; + +/** + * @author nantian created at 2021/9/26 23:13 + */ + +@Slf4j +@Component +public class MessageEventHandler { + + @Autowired + private SocketIOServer server; + + @Autowired + private UserClientMap userClient; + + + @OnConnect + public void onConnect(SocketIOClient client) { + if (client != null) { + + String token = client.getHandshakeData().getSingleUrlParam("token"); + String userId = client.getHandshakeData().getSingleUrlParam("userId"); + + UUID sessionId = client.getSessionId(); + + userClient.save(userId, sessionId); + + log.info("socketio connect successfully,【token】= {},【sessionId】= {}", token, sessionId); + } + } + + @OnDisconnect + public void onDisconnect(SocketIOClient client) { + if (client != null) { + String userId = client.getHandshakeData().getSingleUrlParam("token"); + userClient.deleteByUserId(userId); + client.disconnect(); + } + } + + @OnEvent(value = Event.JOIN) + public void onJoinEvent(SocketIOClient client, AckRequest request, JoinRequest data) { + + log.info("user:{} has join group chat:{}", data.getUserId(), data.getGroupId()); + client.joinRoom(data.getGroupId()); + + server.getRoomOperations(data.getGroupId()).sendEvent(Event.JOIN, data); + } + + + @OnEvent(value = Event.CHAT) + public void onChatEvent(SocketIOClient client, AckRequest request, SingleMessageRequest data) { + System.out.println(data.getMessage()); + } + + @OnEvent(value = Event.GROUP) + public void onGroupEvent(SocketIOClient client, AckRequest request, GroupMessageRequest data) { + Collection clients = server.getRoomOperations(data.getGroupId()).getClients(); + } + + public void sendDisconnectMsg(String userId) { + if (userClient.findByUserId(userId).isPresent()) { + UUID uuid = userClient.findByUserId(userId).get(); + if (null != server.getClient(uuid)) { + BroadcastMessageRequest message = new BroadcastMessageRequest(); + message.setMessage("disconnect"); + server.getClient(uuid).sendEvent(Event.BROADCAST, message); + } + } + } + + public void sendToUser(String userId, String msg) { + if (userClient.findByUserId(userId).isPresent()) { + UUID uuid = userClient.findByUserId(userId).get(); + if (null != server.getClient(uuid)) { + BroadcastMessageRequest message = new BroadcastMessageRequest(); + message.setMessage(msg); + server.getClient(uuid).sendEvent(Event.BROADCAST, message); + } + } + } + + public void sendToBroadcast(BroadcastMessageRequest message) { + for (UUID clientId : userClient.findAll()) { + if (server.getClient(clientId) == null) { + continue; + } + + server.getClient(clientId).sendEvent(Event.BROADCAST, message); + } + } + + public void sendToGroup(GroupMessageRequest message) { + server.getRoomOperations(message.getGroupId()).sendEvent(Event.GROUP, message); + } +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/payload/BroadcastMessageRequest.java b/zeus-message/src/main/java/com/zmops/iot/message/payload/BroadcastMessageRequest.java new file mode 100644 index 00000000..79427994 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/payload/BroadcastMessageRequest.java @@ -0,0 +1,15 @@ +package com.zmops.iot.message.payload; + +import lombok.Data; + +/** + * @author nantian created at 2021/9/26 23:16 + */ +@Data +public class BroadcastMessageRequest { + + /** + * 消息内容 + */ + private String message; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/payload/GroupMessageRequest.java b/zeus-message/src/main/java/com/zmops/iot/message/payload/GroupMessageRequest.java new file mode 100644 index 00000000..16d0398e --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/payload/GroupMessageRequest.java @@ -0,0 +1,24 @@ +package com.zmops.iot.message.payload; + +import lombok.Data; + +/** + * @author nantian created at 2021/9/26 23:16 + */ +@Data +public class GroupMessageRequest { + /** + * 消息发送方用户id + */ + private String fromUid; + + /** + * 群组id + */ + private String groupId; + + /** + * 消息内容 + */ + private String message; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/payload/JoinRequest.java b/zeus-message/src/main/java/com/zmops/iot/message/payload/JoinRequest.java new file mode 100644 index 00000000..56b4390f --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/payload/JoinRequest.java @@ -0,0 +1,19 @@ +package com.zmops.iot.message.payload; + +import lombok.Data; + +/** + * @author nantian created at 2021/9/26 23:16 + */ +@Data +public class JoinRequest { + /** + * 用户id + */ + private String userId; + + /** + * 群名称 + */ + private String groupId; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/payload/SingleMessageRequest.java b/zeus-message/src/main/java/com/zmops/iot/message/payload/SingleMessageRequest.java new file mode 100644 index 00000000..34706c34 --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/payload/SingleMessageRequest.java @@ -0,0 +1,24 @@ +package com.zmops.iot.message.payload; + +import lombok.Data; + +/** + * @author nantian created at 2021/9/26 23:16 + */ +@Data +public class SingleMessageRequest { + /** + * 消息发送方用户id + */ + private String fromUid; + + /** + * 消息接收方用户id + */ + private String toUid; + + /** + * 消息内容 + */ + private String message; +} diff --git a/zeus-message/src/main/java/com/zmops/iot/message/server/SocketIoServer.java b/zeus-message/src/main/java/com/zmops/iot/message/server/SocketIoServer.java new file mode 100644 index 00000000..6d6c515c --- /dev/null +++ b/zeus-message/src/main/java/com/zmops/iot/message/server/SocketIoServer.java @@ -0,0 +1,37 @@ +package com.zmops.iot.message.server; + +import com.corundumstudio.socketio.SocketIOServer; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; + +import javax.annotation.PreDestroy; + +/** + * @author nantian created at 2021/9/26 23:21 + */ + +@Slf4j +@Component +public class SocketIoServer implements CommandLineRunner { + + @Autowired + private SocketIOServer server; + + @Override + public void run(String... args) throws Exception { + server.start(); + } + + /** + * 退出时 销毁 SocketIOServer + * + * @throws Exception + */ + @PreDestroy + public void stop() throws Exception { + server.stop(); + } +} + diff --git a/zeus-rest/pom.xml b/zeus-rest/pom.xml index 1b33a1a7..9912ce6f 100644 --- a/zeus-rest/pom.xml +++ b/zeus-rest/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 @@ -17,6 +18,12 @@ 1.0-beta compile + + com.zmops + zeus-webapp + 1.0-beta + compile + @@ -35,7 +42,7 @@ true - io.ebean.tile:enhancement:12.9.3 + io.ebean.tile:enhancement:12.11.3 diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java deleted file mode 100644 index 5696a669..00000000 --- a/zeus-rest/src/main/java/com/zmops/iot/rest/DeviceStatusWebhookController.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.zmops.iot.rest; - -import com.alibaba.fastjson.JSON; -import com.zmops.iot.model.response.ResponseData; -import org.springframework.web.bind.annotation.*; - -import java.util.Map; - -/** - * @author nantian created at 2021/8/7 14:56 - *

- * 设备在线状态 回调接口 - */ - -@RestController -@RequestMapping("/rest/device") -public class DeviceStatusWebhookController { - - - /** - * 在线状态 回调 - * - * @param params webhook 回调参数 - * @return ResponseData - */ - @RequestMapping("/webhook") - public ResponseData deviceStatusWebhook(@RequestBody Map params) { - - - System.out.println(JSON.toJSONString(params)); - - return ResponseData.success("OK"); - } -} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/ProductionController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/ProductionController.java deleted file mode 100644 index f1cca95a..00000000 --- a/zeus-rest/src/main/java/com/zmops/iot/rest/ProductionController.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.zmops.iot.rest; - -/** - * @author nantian created at 2021/7/23 23:55 - *

- * 产品管理 Controller - */ -public class ProductionController { -} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/controller/AlarmRestController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/AlarmRestController.java new file mode 100644 index 00000000..fd8b5057 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/AlarmRestController.java @@ -0,0 +1,30 @@ +package com.zmops.iot.rest.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.dto.param.DeviceParams; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 告警记录接口 + **/ +@RestController +@RequestMapping("/rest/alarm") +public class AlarmRestController { + + /** + * 告警列表 + * + * @return + */ + @PostMapping("/list") + public ResponseData deviceList(@RequestBody DeviceParams deviceParams) { + + return ResponseData.success(); + } + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceLogRestController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceLogRestController.java new file mode 100644 index 00000000..710d7124 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceLogRestController.java @@ -0,0 +1,32 @@ +package com.zmops.iot.rest.controller; + +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.web.device.dto.param.DeviceParam; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 设备日志接口 + **/ +@RestController +@RequestMapping("/rest/deviceLog") +public class DeviceLogRestController { + + /** + * 服务日志分页列表 + * + * @return + */ + @PostMapping("/getDeviceByPage") + public Pager devicePageList(@RequestBody DeviceParam deviceParam) { + + return new Pager<>(); + } + + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceRestController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceRestController.java new file mode 100644 index 00000000..0f848991 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/DeviceRestController.java @@ -0,0 +1,44 @@ +package com.zmops.iot.rest.controller; + +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.dto.param.DeviceParam; +import com.zmops.iot.web.device.dto.param.DeviceParams; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 设备接口 + **/ +@RestController +@RequestMapping("/rest/device") +public class DeviceRestController { + + /** + * 设备分页列表 + * + * @return + */ + @PostMapping("/getDeviceByPage") + public Pager devicePageList(@RequestBody DeviceParam deviceParam) { + + return new Pager<>(); + } + + /** + * 设备列表 + * + * @return + */ + @PostMapping("/list") + public ResponseData deviceList(@RequestBody DeviceParams deviceParams) { + + return ResponseData.success(); + } + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/controller/LoginRestController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/LoginRestController.java new file mode 100644 index 00000000..da0f470b --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/LoginRestController.java @@ -0,0 +1,31 @@ +package com.zmops.iot.rest.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.dto.param.DeviceParams; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 登录接口 + **/ +@RestController +@RequestMapping("/rest/login") +public class LoginRestController { + + + /** + * 登录 + * + * @return + */ + @PostMapping("/list") + public ResponseData deviceList(@RequestBody DeviceParams deviceParams) { + + return ResponseData.success(); + } + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/controller/ProductRestController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/ProductRestController.java new file mode 100644 index 00000000..4c1c3174 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/ProductRestController.java @@ -0,0 +1,16 @@ +package com.zmops.iot.rest.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + * + * 产品接口 + **/ +@RestController +@RequestMapping("/rest/product") +public class ProductRestController { + + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/controller/SceneRestController.java b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/SceneRestController.java new file mode 100644 index 00000000..dfa31824 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/controller/SceneRestController.java @@ -0,0 +1,16 @@ +package com.zmops.iot.rest.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 场景接口 + **/ +@RestController +@RequestMapping("/rest/scene") +public class SceneRestController { + + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/service/DeviceRestService.java b/zeus-rest/src/main/java/com/zmops/iot/rest/service/DeviceRestService.java new file mode 100644 index 00000000..29df4e89 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/service/DeviceRestService.java @@ -0,0 +1,13 @@ +package com.zmops.iot.rest.service; + +import org.springframework.stereotype.Service; + +/** + * @author yefei + * + * 设备 rest 服务 + **/ +@Service +public class DeviceRestService { + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/service/ProductRestService.java b/zeus-rest/src/main/java/com/zmops/iot/rest/service/ProductRestService.java new file mode 100644 index 00000000..66f43755 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/service/ProductRestService.java @@ -0,0 +1,13 @@ +package com.zmops.iot.rest.service; + +import org.springframework.stereotype.Service; + +/** + * @author yefei + * + * 产品 rest 服务 + **/ +@Service +public class ProductRestService { + +} diff --git a/zeus-rest/src/main/java/com/zmops/iot/rest/service/SceneRestService.java b/zeus-rest/src/main/java/com/zmops/iot/rest/service/SceneRestService.java new file mode 100644 index 00000000..284ca906 --- /dev/null +++ b/zeus-rest/src/main/java/com/zmops/iot/rest/service/SceneRestService.java @@ -0,0 +1,13 @@ +package com.zmops.iot.rest.service; + +import org.springframework.stereotype.Service; + +/** + * @author yefei + * + * 场景 rest 服务 + **/ +@Service +public class SceneRestService { + +} diff --git a/zeus-server-pom/pom.xml b/zeus-server-pom/pom.xml deleted file mode 100644 index 28e7581e..00000000 --- a/zeus-server-pom/pom.xml +++ /dev/null @@ -1,133 +0,0 @@ - - - 4.0.0 - - com.zmops - zeus-server-pom - 1.0-beta - - pom - - - ../iot-server - ../iot-server-dist - - - - 1.8 - 8 - 8 - - UTF-8 - - 1.6.2 - 3.0.0-M2 - - 2.8.2 - 3.1.0 - 3.1.0 - 3.8.0 - 3.1.0 - 3.0.1 - 1.8 - 3.1.1 - 0.4.13 - 2.25.4 - - - - - - - - maven-antrun-plugin - ${maven-antrun-plugin.version} - - - maven-deploy-plugin - ${maven-deploy-plugin.version} - - - maven-assembly-plugin - ${maven-assembly-plugin.version} - - - maven-jar-plugin - ${maven-jar-plugin.version} - - true - - - - maven-shade-plugin - ${maven-shade-plugin.version} - - - - - - kr.motd.maven - os-maven-plugin - ${os-maven-plugin.version} - - - initialize - - detect - - - - - - maven-enforcer-plugin - ${maven-enforcer-plugin.version} - - - enforce-java - - enforce - - validate - - - - - 1.8 - - - 3.6 - - - - - - - - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${compiler.version} - ${compiler.version} - ${project.build.sourceEncoding} - - - - maven-resources-plugin - ${maven-resource-plugin.version} - - ${project.build.sourceEncoding} - - - - com.spotify - docker-maven-plugin - ${docker.plugin.version} - - true - - - - - \ No newline at end of file diff --git a/zeus-starter/pom.xml b/zeus-starter/pom.xml index de8c0d12..8884572a 100644 --- a/zeus-starter/pom.xml +++ b/zeus-starter/pom.xml @@ -3,17 +3,20 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 - + jar zeus-starter 8 8 + 1.11.0 + ../zeus-iot-ui @@ -44,29 +47,89 @@ com.zmops - iot-alarm + zeus-message ${project.version} + + org.apache.camel + camel-pgevent + 3.11.4 + + zeus-webapp - - src/main/resources - - **/*.* - - true - - + + + maven-compiler-plugin + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.springframework.boot spring-boot-maven-plugin - 2.3.12.RELEASE + ${spring.boot.version} - com.zmops.iot.IOTApplication + com.zmops.iot.IoTApplication diff --git a/zeus-starter/src/main/assembly/webapp.yml b/zeus-starter/src/main/assembly/webapp.yml new file mode 100644 index 00000000..7c854e70 --- /dev/null +++ b/zeus-starter/src/main/assembly/webapp.yml @@ -0,0 +1,64 @@ +server: + port: 9090 + max-http-header-size: 10240 + shutdown: graceful + undertow: + threads: + worker: 256 + buffer-size: 1024 + direct-buffers: true +management: + endpoint: + shutdown: + enabled: true + endpoints: + web: + exposure: + include: shutdown + +# EBean Database Setting +spring: + application: + name: ZEUS-IOT + datasource: + druid: + driver-class-name: org.postgresql.Driver + username: ${ZEUS_DB_USERNAME:postgres} + password: ${ZEUS_DB_PASSWORD:postgres} + url: jdbc:postgresql://${ZEUS_DB_HOST:127.0.0.1}:${ZEUS_DB_PORT:5432}/zeus-iot + servlet: + multipart: + max-request-size: 200MB + max-file-size: 200MB + jackson: + generator: + write_numbers_as_strings: true + mvc: + view: + prefix: /public + freemarker: + suffix: .html + template-loader-path: classpath:/public/ + checkTemplateLocation: false + +forest: + log-enabled: false + timeout: 5000 + max-retry-count: 3 # 最大请求重试次数,默认为 0 次 + max-retry-interval: 10 # 为最大重试时间间隔, 单位为毫秒,默认为 0 毫秒 + variables: + ## Zabbix API IP And ServerIp and ServerPort + zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} + zbxServerPort: ${ZEUS_ZABBIX_PORT:80} + zbxApiUrl: ${ZEUS_ZABBIX_API_URL:/zabbix/api_jsonrpc.php} + zbxApiToken: 3464dee6b3fa3ce4173972e0497d7b84a93bdf8477ff1bdd51a7719cc0db2cd9 + + ## tdengine http request address + taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/zeus_data + taosUser: root + taosPwd: taosdata + +socketio: + server: + port: 9080 + host: 0.0.0.0 \ No newline at end of file diff --git a/zeus-starter/src/main/java/com/zmops/iot/IOTApplication.java b/zeus-starter/src/main/java/com/zmops/iot/IoTApplication.java similarity index 61% rename from zeus-starter/src/main/java/com/zmops/iot/IOTApplication.java rename to zeus-starter/src/main/java/com/zmops/iot/IoTApplication.java index 474044e2..6867f69d 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/IOTApplication.java +++ b/zeus-starter/src/main/java/com/zmops/iot/IoTApplication.java @@ -1,6 +1,8 @@ package com.zmops.iot; import com.dtflys.forest.springboot.annotation.ForestScan; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -13,10 +15,13 @@ */ @SpringBootApplication @ForestScan("com.zmops.zeus.driver.service") -public class IOTApplication { +public class IoTApplication { + + private final static Logger logger = LoggerFactory.getLogger(IoTApplication.class); public static void main(String[] args) { TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); - SpringApplication.run(IOTApplication.class, args); + SpringApplication.run(IoTApplication.class, args); + logger.info(IoTApplication.class.getSimpleName() + " webapp started successfully!"); } } diff --git a/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java b/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java index 4ae7e403..7f077904 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java +++ b/zeus-starter/src/main/java/com/zmops/iot/config/security/WebSecurityConfig.java @@ -16,8 +16,6 @@ import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import java.util.List; - /** * @author nantian created at 2021/7/29 22:54 */ @@ -52,8 +50,6 @@ protected void configure(HttpSecurity httpSecurity) throws Exception { //自定义退出 httpSecurity.logout().disable(); - //禁用匿名用户 - httpSecurity.anonymous().disable(); httpSecurity.exceptionHandling().authenticationEntryPoint(unauthorizedHandler); @@ -83,10 +79,9 @@ public void configure(WebSecurity web) throws Exception { // 静态资源放开过滤 .and().ignoring().antMatchers(HttpMethod.GET, - "/assets/**", - "/favicon.ico", - "/activiti-editor/**" - ); + "/static/**", + "/favicon.ico" + ); } } diff --git a/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java b/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java index 772f50b6..516ebd86 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java +++ b/zeus-starter/src/main/java/com/zmops/iot/config/web/WebConfig.java @@ -4,6 +4,7 @@ import com.google.code.kaptcha.util.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.Properties; @@ -15,6 +16,11 @@ @Configuration public class WebConfig implements WebMvcConfigurer { + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/static/**").addResourceLocations("classpath:/public/static/"); + } + /** * 验证码 Bean * @@ -32,8 +38,10 @@ public DefaultKaptcha kaptcha() { properties.put("kaptcha.session.key", "code"); properties.put("kaptcha.textproducer.char.length", "4"); properties.put("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑"); - Config config = new Config(properties); + + Config config = new Config(properties); DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + defaultKaptcha.setConfig(config); return defaultKaptcha; } diff --git a/zeus-starter/src/main/java/com/zmops/iot/config/zbxapi/ZbxApiInfoValidation.java b/zeus-starter/src/main/java/com/zmops/iot/config/zbxapi/ZbxApiInfoValidation.java index b2980ccd..f770af3c 100644 --- a/zeus-starter/src/main/java/com/zmops/iot/config/zbxapi/ZbxApiInfoValidation.java +++ b/zeus-starter/src/main/java/com/zmops/iot/config/zbxapi/ZbxApiInfoValidation.java @@ -4,7 +4,6 @@ import com.zmops.zeus.driver.service.ZbxApiInfo; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeansException; -import org.springframework.boot.ExitCodeGenerator; import org.springframework.boot.SpringApplication; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -20,8 +19,8 @@ public class ZbxApiInfoValidation implements ApplicationContextAware { @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - ZbxApiInfo apiInfo = applicationContext.getBean(ZbxApiInfo.class); - String response = apiInfo.getApiInfo(); + ZbxApiInfo apiInfo = applicationContext.getBean(ZbxApiInfo.class); + String response = apiInfo.getApiInfo(); int version = NumberUtil.parseInt(response.replaceAll("\\.", "")); diff --git a/zeus-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/zeus-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 00000000..0e2701a7 --- /dev/null +++ b/zeus-starter/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,14 @@ +{ + "properties": [ + { + "name": "socketio.server.host", + "type": "java.lang.String", + "description": "socketio host." + }, + { + "name": "socketio.server.port", + "type": "java.lang.String", + "description": "socketio port." + } + ] +} \ No newline at end of file diff --git a/zeus-starter/src/main/resources/application.yaml b/zeus-starter/src/main/resources/application.yaml index 3322eefa..c25e6159 100644 --- a/zeus-starter/src/main/resources/application.yaml +++ b/zeus-starter/src/main/resources/application.yaml @@ -1,4 +1,3 @@ -# =========== 宙斯物联网采集分析基础平台 =========== server: port: 9090 max-http-header-size: 10240 @@ -17,7 +16,7 @@ management: exposure: include: shutdown -# EBean Database 配置 +# EBean Database Setting spring: application: name: ZEUS-IOT @@ -34,23 +33,31 @@ spring: jackson: generator: write_numbers_as_strings: true + mvc: + view: + prefix: /public + freemarker: + suffix: .html + template-loader-path: classpath:/public/ forest: + log-enabled: true + timeout: 5000 +# max-retry-count: 3 # 最大请求重试次数,默认为 0 次 +# max-retry-interval: 10 # 为最大重试时间间隔, 单位为毫秒,默认为 0 毫秒 variables: - ## Zabbix API IP 和 端口 - zbxApiUrl: http://${ZEUS_ZABBIX_HOST:127.0.0.1}:${ZEUS_ZABBIX_API_PORT:80}/zabbix/api_jsonrpc.php + ## Zabbix API IP And ServerIp and ServerPort zbxServerIp: ${ZEUS_ZABBIX_HOST:127.0.0.1} - zbxServerPort: ${ZEUS_ZABBIX_PORT:10051} - zbxApiToken: e39f259dc2b5a5deb583531380a56d85 + zbxServerPort: ${ZEUS_ZABBIX_PORT:80} + zbxApiUrl: ${ZEUS_ZABBIX_API_URL:/zabbix/api_jsonrpc.php} + zbxApiToken: bd3eee6676ef363b4627c1d1f9ab83d5edc8ca741e56c7bd5a6cf64c3b4f7615 - ## 设备状态变更 等回调地址 - zeusServerIp: ${ZEUS_CALLBACK_HOST:127.0.0.1} - zeusServerPort: ${ZEUS_CALLBACK_PORT:9090} - interceptors: - - com.zmops.zeus.driver.inteceptor.JsonBodyBuildInterceptor - log-enabled: false - timeout: 5000 + ## tdengine http request address + taosUrl: http://${ZEUS_TAOS_HOST:127.0.0.1}:${ZEUS_TAOS_REST_PORT:6041}/rest/sql/zeus_data + taosUser: root + taosPwd: taosdata -logging: - level: - io.ebean: DEBUG \ No newline at end of file +socketio: + server: + port: 9080 + host: 0.0.0.0 \ No newline at end of file diff --git a/zeus-starter/src/main/resources/log4j2.xml b/zeus-starter/src/main/resources/log4j2.xml index f0789393..da090853 100644 --- a/zeus-starter/src/main/resources/log4j2.xml +++ b/zeus-starter/src/main/resources/log4j2.xml @@ -72,13 +72,15 @@ - - - + + + + + diff --git a/zeus-webapp-bom/pom.xml b/zeus-webapp-bom/pom.xml new file mode 100644 index 00000000..2fbf608f --- /dev/null +++ b/zeus-webapp-bom/pom.xml @@ -0,0 +1,159 @@ + + + + zeus-iot + com.zmops + 1.0-beta + + 4.0.0 + pom + zeus-webapp-bom + + Zeus IoT 业务平台 + + + 8 + 8 + 2.25.4 + 4.1.65.Final + + + + ../zeus-common + ../zeus-message + ../zeus-core + ../zeus-driver + ../zeus-rest + ../zeus-starter + ../zeus-webapp + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + + + org.springframework.boot + spring-boot-starter-logging + + + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + + org.springframework.boot + spring-boot-starter-undertow + + + org.springframework + spring-jdbc + + + com.alibaba + druid-spring-boot-starter + 1.2.6 + + + org.springframework.boot + spring-boot-configuration-processor + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-freemarker + + + org.freemarker + freemarker + + + com.alibaba + fastjson + 1.2.58 + + + org.aspectj + aspectjweaver + + + org.postgresql + postgresql + + + org.projectlombok + lombok + true + + + org.yaml + snakeyaml + + + one.util + streamex + 0.7.3 + + + com.github.penggle + kaptcha + 2.3.2 + + + commons-lang + commons-lang + 2.6 + + + com.dtflys.forest + forest-spring-boot-starter + 1.5.8 + + + commons-logging + commons-logging + + + + + io.ebean + ebean + 12.13.1 + + + + + \ No newline at end of file diff --git a/zeus-webapp/pom.xml b/zeus-webapp/pom.xml index d0305752..7ffafe25 100644 --- a/zeus-webapp/pom.xml +++ b/zeus-webapp/pom.xml @@ -3,9 +3,10 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - zeus-iot + zeus-webapp-bom com.zmops 1.0-beta + ../zeus-webapp-bom/pom.xml 4.0.0 @@ -23,19 +24,42 @@ com.zmops - iot-alarm + zeus-message ${project.version} com.zmops zeus-driver 1.0-beta - compile + + + + + - com.zmops - toolkit-async - 1.0-beta + org.springframework.boot + spring-boot-starter-websocket + + + commons-httpclient + commons-httpclient + 3.1 + + + io.nats + jnats + 2.2.0 + + + com.taosdata.jdbc + taos-jdbcdriver + 2.0.31 + + + org.apache.camel + camel-core + 3.11.4 compile @@ -55,7 +79,7 @@ true - io.ebean.tile:enhancement:12.9.3 + io.ebean.tile:enhancement:12.11.3 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java index dd3e58d7..437d73b4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/AlarmController.java @@ -1,8 +1,15 @@ package com.zmops.iot.web.alarm.controller; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.alarm.dto.AlarmDto; +import com.zmops.iot.web.alarm.dto.param.AlarmParam; import com.zmops.iot.web.alarm.service.AlarmService; +import com.zmops.iot.web.auth.Permission; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** @@ -15,8 +22,25 @@ public class AlarmController { @Autowired AlarmService alarmService; - @RequestMapping("/test") - public void test() { - alarmService.test(); + @Permission(code = "alarmList") + @RequestMapping("/getAlarmByPage") + public Pager getAlarmByPage(@RequestBody AlarmParam alarmParam) { + return alarmService.getAlarmByPage(alarmParam); } + + @Permission(code = "alarmList") + @RequestMapping("/acknowledgement") + public ResponseData acknowledgement(@RequestParam String eventId) { + alarmService.acknowledgement(eventId); + return ResponseData.success(); + } + + + @Permission(code = "alarmList") + @RequestMapping("/resolve") + public ResponseData resolve(@RequestParam String eventId) { + alarmService.resolve(eventId); + return ResponseData.success(); + } + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MailSettingController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MailSettingController.java new file mode 100644 index 00000000..5745ca03 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MailSettingController.java @@ -0,0 +1,48 @@ +package com.zmops.iot.web.alarm.controller; + + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.messages.MailSetting; +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.domain.messages.MailParam; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.alarm.service.MailSettingServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + * + **/ +@RestController +@RequestMapping("mailSetting") +public class MailSettingController { + + @Autowired + MailSettingServiceImpl settingService; + + @RequestMapping("get") + public ResponseData get() { + return ResponseData.success(settingService.get()); + } + + @PostMapping("test") + public ResponseData test(@Validated(MailParam.Test.class) @RequestBody MailParam mailParam) { + NoticeResult test = settingService.test(mailParam); + if(test.getStatus().equals(NoticeResult.NoticeStatus.success)){ + return ResponseData.success(test.getMsg()); + }else{ + return ResponseData.error(test.getMsg()); + } + } + + @PostMapping("update") + public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody MailParam mailParam) { + return ResponseData.success(settingService.updateSettings(mailParam.getSettings())); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MediaTypeSettingController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MediaTypeSettingController.java index bf0e9e40..6d8c6f76 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MediaTypeSettingController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MediaTypeSettingController.java @@ -1,5 +1,6 @@ package com.zmops.iot.web.alarm.controller; +import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.domain.alarm.MediaTypeSetting; import com.zmops.iot.domain.alarm.query.QMediaTypeSetting; import com.zmops.iot.model.response.ResponseData; @@ -23,11 +24,18 @@ public class MediaTypeSettingController { @GetMapping("/list") public ResponseData list(@RequestParam(value = "type", required = false) String type) { + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); QMediaTypeSetting qMediaTypeSetting = new QMediaTypeSetting(); + if (null != tenantId) { + qMediaTypeSetting.tenantId.eq(tenantId); + } else { + qMediaTypeSetting.tenantId.isNull(); + } if (ToolUtil.isNotEmpty(type)) { qMediaTypeSetting.type.eq(type); } - return new SuccessResponseData(qMediaTypeSetting.findList()); + + return new SuccessResponseData(qMediaTypeSetting.orderBy().id.asc().findList()); } @PostMapping("update") diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MessageController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MessageController.java new file mode 100644 index 00000000..749636f5 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/controller/MessageController.java @@ -0,0 +1,69 @@ +package com.zmops.iot.web.alarm.controller; + + +import com.zmops.iot.domain.messages.Messages; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.web.alarm.dto.param.MessageParam; +import com.zmops.iot.web.alarm.service.MessageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +/** + * @author yefei + **/ +@RestController +@RequestMapping("/message") +public class MessageController { + + @Autowired + MessageService messageService; + + /** + * 消息分页列表 + * + * @param messageParam + * @return + */ + @RequestMapping("/getMessageByPage") + public Pager getMessageByPage(@RequestBody MessageParam messageParam) { + return messageService.list(messageParam); + } + + /** + * 消息详情 + * + * @param id + * @return + */ + @RequestMapping("/info") + public Messages info(@RequestParam("id") Integer id) { + return messageService.info(id); + } + + + /** + * 消息置为已读 + * + * @param messageVo + * @return + */ + @RequestMapping("/read") + public List read(@RequestBody MessageParam messageVo) { + return messageService.read(messageVo); + } + + /** + * 未读消息数 + * + * @return + */ + @GetMapping("/num") + public Map unReadNum() { + return messageService.unReadNum(); + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java new file mode 100644 index 00000000..8f9020c1 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/AlarmDto.java @@ -0,0 +1,38 @@ +package com.zmops.iot.web.alarm.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class AlarmDto { + + private Long eventId; + + private Long objectId; + + private LocalDateTime clock; + + private LocalDateTime rClock; + + private String name; + + private String acknowledged; + + @CachedValue(type = DicType.Device, fieldName = "deviceName") + private String deviceId; + + @CachedValue(value = "EVENT_LEVEL",fieldName = "severityName") + private String severity; + + private String status; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java new file mode 100644 index 00000000..a2c7a013 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/AlarmParam.java @@ -0,0 +1,18 @@ +package com.zmops.iot.web.alarm.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class AlarmParam extends BaseQueryParam { + private String deviceId; + + private Long timeFrom; + private Long timeTill; + private String name; + private String statusName; + private Integer severity; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/MessageParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/MessageParam.java new file mode 100644 index 00000000..409907e3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/dto/param/MessageParam.java @@ -0,0 +1,16 @@ +package com.zmops.iot.web.alarm.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class MessageParam extends BaseQueryParam { + private Integer readed; + + private List ids; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java index 1b81acec..2f7b787e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/AlarmService.java @@ -1,13 +1,30 @@ package com.zmops.iot.web.alarm.service; import com.zmops.iot.domain.alarm.AlarmMessage; -import com.zmops.iot.mediaType.AlarmCallback; +import com.zmops.iot.domain.alarm.Problem; +import com.zmops.iot.domain.alarm.query.QProblem; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.media.AlarmCallback; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.alarm.dto.AlarmDto; +import com.zmops.iot.web.alarm.dto.param.AlarmParam; +import com.zmops.iot.web.device.service.DeviceService; +import com.zmops.zeus.driver.service.ZbxProblem; +import io.ebean.PagedList; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; /** * @author yefei @@ -18,14 +35,122 @@ public class AlarmService { @Autowired Collection alarmCallbacks; + @Autowired + ZbxProblem zbxProblem; + + @Autowired + DeviceService deviceService; + + private static final String PROBLEM_RESOLVE = "已解决"; + + + public void alarm(Map alarmInfo) { + List deviceIds = (List) alarmInfo.get("hostname"); + String eventRuleId = (String) alarmInfo.get("triggerName"); + + if (ToolUtil.isEmpty(deviceIds) || ToolUtil.isEmpty(eventRuleId)) { + return; + } + + List deviceList = new QDevice().deviceId.in(deviceIds).findList(); + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(Long.parseLong(eventRuleId)).findOne(); - public void test() { List alarmMessages = new ArrayList<>(); - alarmMessages.add(AlarmMessage.builder().alarmMessage("DELTA 一级预警").build()); - alarmCallbacks.forEach(alarmCallback -> { - if (alarmCallback.getType().equals("welink")) { - alarmCallback.doAlarm(alarmMessages); + + if (ToolUtil.isNotEmpty(deviceList) && null != productEvent) { + String deviceName = deviceList.parallelStream().map(Device::getName).collect(Collectors.joining(",")); + String alarmmessage = "设备:" + deviceName + "发生告警,告警内容:" + productEvent.getEventRuleName(); + alarmMessages.add(AlarmMessage.builder().alarmMessage(alarmmessage).build()); + alarmCallbacks.forEach(alarmCallback -> { + alarmCallback.doAlarm(alarmMessages, deviceList.get(0).getTenantId()); + }); + } + } + + public void action(Map alarmInfo) { + String deviceId = alarmInfo.get("hostname"); + String serviceName = alarmInfo.get("serviceName"); + + if (ToolUtil.isEmpty(deviceId) || ToolUtil.isEmpty(serviceName)) { + return; + } + + Device device = new QDevice().deviceId.eq(deviceId).findOne(); + + List alarmMessages = new ArrayList<>(); + + if (null != device) { + String alarmmessage = "设备:" + device.getName() + "触发联动服务,服务名称:" + serviceName; + alarmMessages.add(AlarmMessage.builder().alarmMessage(alarmmessage).build()); + alarmCallbacks.forEach(alarmCallback -> { +// if (alarmCallback.getType().equals("welink")) { + alarmCallback.doAlarm(alarmMessages, device.getTenantId()); +// } + }); + } + } + + + public Pager getAlarmByPage(AlarmParam alarmParam) { + + QProblem query = buildQproblem(alarmParam); + + PagedList problemList = query.setFirstRow((alarmParam.getPage() - 1) * alarmParam.getMaxRow()) + .setMaxRows(alarmParam.getMaxRow()).findPagedList(); + + return new Pager<>(formatAlarmList(problemList.getList()), problemList.getTotalCount()); + } + + public List getAlarmList(AlarmParam alarmParam) { + + QProblem query = buildQproblem(alarmParam); + + return formatAlarmList(query.findList()); + } + + private QProblem buildQproblem(AlarmParam alarmParam) { + QProblem query = new QProblem(); + if (ToolUtil.isNotEmpty(alarmParam.getDeviceId())) { + query.deviceId.eq(alarmParam.getDeviceId()); + } + if (ToolUtil.isNotEmpty(alarmParam.getTimeFrom())) { + query.clock.ge(LocalDateTimeUtils.getLDTByMilliSeconds(alarmParam.getTimeFrom() * 1000)); + } + if (ToolUtil.isNotEmpty(alarmParam.getTimeTill())) { + query.clock.lt(LocalDateTimeUtils.getLDTByMilliSeconds(alarmParam.getTimeTill() * 1000)); + } + if (ToolUtil.isNotEmpty(alarmParam.getStatusName())) { + if (PROBLEM_RESOLVE.equals(alarmParam.getStatusName())) { + query.rClock.isNotNull(); + } else { + query.rClock.isNull(); } + } + if (ToolUtil.isNotEmpty(alarmParam.getSeverity())) { + query.severity.eq(alarmParam.getSeverity()); + } + query.orderBy().clock.desc(); + return query; + } + + private List formatAlarmList(List problemList) { + List list = new ArrayList<>(); + problemList.forEach(problem -> { + AlarmDto alarmDto = new AlarmDto(); + BeanUtils.copyProperties(problem, alarmDto); + alarmDto.setSeverity(problem.getSeverity() + ""); + alarmDto.setStatus(problem.getRClock() == null ? "未解决" : "已解决"); + alarmDto.setAcknowledged(problem.getAcknowledged() == 0 ? "未确认" : "已确认"); + list.add(alarmDto); }); + return list; + } + + public void acknowledgement(String eventId) { + zbxProblem.acknowledgement(eventId, 2); + } + + public void resolve(String eventId) { + zbxProblem.acknowledgement(eventId, 1); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MailSettingServiceImpl.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MailSettingServiceImpl.java new file mode 100644 index 00000000..2acfdcf0 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MailSettingServiceImpl.java @@ -0,0 +1,80 @@ +package com.zmops.iot.web.alarm.service; + + +import com.zmops.iot.core.auth.context.LoginContextHolder; +import com.zmops.iot.domain.messages.MailParam; +import com.zmops.iot.domain.messages.MailSetting; +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.domain.messages.query.QMailSetting; +import com.zmops.iot.media.mail.MailNotice; +import com.zmops.iot.media.mail.MailSettingService; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * @author yefei + **/ +@Service +@Slf4j +public class MailSettingServiceImpl implements MailSettingService { + + @Autowired + MailNotice mailNotice; + + private volatile Map instanceMap = new HashMap<>(); + + @Override + public MailSetting get() { + return Optional.ofNullable(getOne()).orElse(new MailSetting()); + } + + private MailSetting getOne() { + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + tenantId = Optional.ofNullable(tenantId).orElse(-1L); + if (instanceMap.get(tenantId) != null) { + return instanceMap.get(tenantId); + } + MailSetting mailSetting = Optional.of(new QMailSetting().findList()) + .map(Collection::iterator) + .filter(Iterator::hasNext) + .map(Iterator::next).orElse(null); + if (mailSetting != null) { + instanceMap.put(tenantId, mailSetting); + } + return mailSetting; + } + + + @Override + public NoticeResult test(MailParam mailParam) { + MailSetting mailSetting = mailParam.getSettings(); + NoticeResult noticeResult = mailNotice.test(mailSetting, mailParam.getReceiver()); + //updateSettings(noticeResult, mailSetting); + return noticeResult; + } + + @Override + public Integer updateSettings(MailSetting mailSetting) { + if (mailSetting.getTls() == null) { + mailSetting.setTls(0); + } + if (mailSetting.getSsl() == null) { + mailSetting.setSsl(0); + } + MailSetting dbSetting = getOne(); + if (dbSetting == null) { + DB.insert(mailSetting); + } else { + mailSetting.setId(dbSetting.getId()); + DB.update(mailSetting); + } + Long tenantId = Optional.ofNullable(mailSetting.getTenantId()).orElse(-1L); + instanceMap.put(tenantId, mailSetting); + return mailSetting.getId(); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java new file mode 100644 index 00000000..c6dc4231 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/alarm/service/MessageService.java @@ -0,0 +1,153 @@ +package com.zmops.iot.web.alarm.service; + +import com.alibaba.fastjson.JSON; +import com.zmops.iot.core.auth.context.LoginContextHolder; +import com.zmops.iot.core.auth.model.LoginUser; +import com.zmops.iot.domain.messages.MessageBody; +import com.zmops.iot.domain.messages.Messages; +import com.zmops.iot.domain.messages.query.QMessages; +import com.zmops.iot.domain.sys.SysUser; +import com.zmops.iot.domain.sys.query.QSysUser; +import com.zmops.iot.message.handler.MessageEventHandler; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.alarm.dto.param.MessageParam; +import io.ebean.DB; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 消息服务 + **/ +@Service +public class MessageService { + + protected final static int sys = 1; + + @Autowired + MessageEventHandler messageEventHandler; + + /** + * 发送消息 + * + * @param body + */ + public void push(MessageBody body) { + Objects.requireNonNull(body.getMsg()); + + List tos; + + if (!CollectionUtils.isEmpty(body.getTo())) { + tos = body.getTo(); + } else { + List userList = new QSysUser().findList(); + tos = userList.parallelStream().map(SysUser::getUserId).collect(Collectors.toList()); + } + + if (body.isPersist()) { + tos.forEach(to -> { + Messages messages = new Messages(); + messages.setClassify(sys); + messages.setTitle(body.getMsg()); + messages.setUserId(to); + + String content = ""; + if (ToolUtil.isNotEmpty(body.getBody())) { + content = JSON.toJSONString(body.getBody()); + messages.setContent(content); + } + + messages.setClock(System.currentTimeMillis() / 1000); + saveMessage(messages); + }); + } + body.addBody("classify", sys); + + tos.forEach(to -> { + messageEventHandler.sendToUser(to + "", JSON.toJSONString(body)); + }); + } + + /** + * 消息列表 + * + * @param messageParam + * @return + */ + public Pager list(MessageParam messageParam) { + LoginUser user = LoginContextHolder.getContext().getUser(); + QMessages qMessages = new QMessages(); + + qMessages.userId.eq(user.getId()); + + if (messageParam.getReaded() != null) { + qMessages.readed.eq(messageParam.getReaded()); + } + qMessages.orderBy(" readed asc, clock desc"); + List list = qMessages.setFirstRow((messageParam.getPage() - 1) * messageParam.getMaxRow()) + .setMaxRows(messageParam.getMaxRow()).findList(); + + return new Pager<>(list, qMessages.findCount()); + } + + /** + * 读消息 + * + * @param messageParam + * @return + */ + public List read(MessageParam messageParam) { + LoginUser user = LoginContextHolder.getContext().getUser(); + Messages messages = new Messages(); + messages.setReaded(1); + QMessages qMessages = new QMessages(); + if (!CollectionUtils.isEmpty(messageParam.getIds())) { + qMessages.id.in(messageParam.getIds()); + } + qMessages.userId.eq(user.getId()); + + new QMessages().asUpdate().set("readed", 1).update(); + return messageParam.getIds(); + } + + /** + * 未读消息数 + * + * @return + */ + public Map unReadNum() { + LoginUser user = LoginContextHolder.getContext().getUser(); + + Map map = new HashMap<>(); + + int count = new QMessages().readed.eq(0).userId.eq(user.getId()).findCount(); + map.put("count", count); + + return map; + } + + /** + * 消息详情 + * + * @param id + * @return + */ + public Messages info(Integer id) { + return new QMessages().id.eq(id).findOne(); + } + + + private void saveMessage(Messages messages) { + DB.save(messages); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java new file mode 100644 index 00000000..64767899 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HistoryController.java @@ -0,0 +1,31 @@ +package com.zmops.iot.web.analyse.controller; + +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.iot.web.analyse.dto.param.HistoryParam; +import com.zmops.iot.web.analyse.service.HistoryService; +import com.zmops.iot.web.auth.Permission; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 历史数据 + **/ +@RestController +@RequestMapping("/history") +public class HistoryController { + + @Autowired + HistoryService historyService; + + @RequestMapping("/query") +// @Permission(code = "latest") + public Pager qeuryHistory(@Validated @RequestBody HistoryParam historyParam) { + return historyService.queryHistory(historyParam); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java new file mode 100644 index 00000000..41037e26 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/HomeController.java @@ -0,0 +1,109 @@ +package com.zmops.iot.web.analyse.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.analyse.service.HomeService; +import com.zmops.iot.web.analyse.service.ZbxChartsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +/** + * @author yefei + *

+ * 全局概览 + **/ +@RestController +@RequestMapping("/home") +public class HomeController { + + @Autowired + HomeService homeService; + + @Autowired + ZbxChartsService zbxChartsService; + + /** + * 设备数量统计 + */ + @RequestMapping("/deviceNum") + public ResponseData getDeviceNum(@RequestParam("timeFrom") Integer timeFrom, @RequestParam("timeTill") Integer timeTill) { + return ResponseData.success(homeService.getDeviceNum(timeFrom, timeTill)); + } + + /** + * 告警数量统计 + */ + @RequestMapping("/alarmNum") + public ResponseData getAlarmNum(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { + return ResponseData.success(homeService.getAlarmNum(timeFrom, timeTill)); + } + + + /** + * 服务器取数速率 + * + * @return + */ + @RequestMapping("/collectonRate") + public ResponseData collectonRate(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { + return ResponseData.success(homeService.collectionRate(timeFrom, timeTill)); + } + + /** + * 事件数量统计 + */ + @RequestMapping("/eventNum") + public ResponseData getEventNum(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { + return ResponseData.success(homeService.getEventNum(timeFrom, timeTill)); + } + + /** + * 告警TOP统计 + */ + @RequestMapping("/alarmTop") + public ResponseData getAlarmTop(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { + return ResponseData.success(homeService.getAlarmTop(timeFrom, timeTill)); + } + + + /** + * 服务调用统计 + */ + @RequestMapping("/serviceExecuteNum") + public ResponseData serviceExecuteNum(@RequestParam("timeFrom") long timeFrom, @RequestParam("timeTill") long timeTill) { + return ResponseData.success(homeService.serviceExecuteNum(timeFrom, timeTill)); + } + + /** + * 数据量统计 + */ + @RequestMapping("/dataLevel") + public ResponseData dataLevel() { + return ResponseData.success(homeService.dataLevel()); + } + + + /** + * 获取 数据图形展示 + * + * @param response http响应 + * @param from 开始时间 + * @param to 结束时间 + * @param attrIds 设备属性ID + * @param width 图表宽度 + * @param height 图表高度 + */ + @RequestMapping("/getCharts") + public void getCookie(HttpServletResponse response, + @RequestParam("from") String from, + @RequestParam("to") String to, + @RequestParam("attrIds") List attrIds, + @RequestParam("width") String width, + @RequestParam("height") String height) { + zbxChartsService.getCharts(response, from, to, attrIds, width, height); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java new file mode 100644 index 00000000..19a75694 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/LatestController.java @@ -0,0 +1,49 @@ +package com.zmops.iot.web.analyse.controller; + +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.iot.web.analyse.dto.param.LatestParam; +import com.zmops.iot.web.analyse.service.LatestService; +import com.zmops.iot.web.auth.Permission; +import com.zmops.zeus.driver.service.TDEngineRest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 最新数据 + **/ +@RestController +@RequestMapping("/latest") +public class LatestController { + + @Autowired + LatestService latestService; + + @Autowired + private TDEngineRest tdEngineRest; + + @RequestMapping("/query") +// @Permission(code = "latest") + public Pager qeuryLatest(@Validated @RequestBody LatestParam latestParam) { + return latestService.qeuryLatest(latestParam); + } + + @RequestMapping("/queryMap") +// @Permission(code = "latest") + public ResponseData queryMap(@RequestParam("deviceId") String deviceId) { + return ResponseData.success(latestService.queryMap(deviceId)); + } + + + @RequestMapping("/tdexecutesql") + public ResponseData getTdEngineData(@RequestParam String sql) { + return ResponseData.success(tdEngineRest.executeSql(sql)); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/SelfMonitorController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/SelfMonitorController.java new file mode 100644 index 00000000..21326448 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/controller/SelfMonitorController.java @@ -0,0 +1,43 @@ +package com.zmops.iot.web.analyse.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.analyse.service.SelfMonitorService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + * 自监控 + **/ +@RestController +@RequestMapping("/monitor/self") +public class SelfMonitorController { + + @Autowired + SelfMonitorService selfMonitorService; + + @GetMapping("memory") + public ResponseData getMemInfo(){ + return ResponseData.success(selfMonitorService.getMemInfo()); + } + + @GetMapping("cpuLoad") + public ResponseData getCpuInfo(){ + return ResponseData.success(selfMonitorService.getCpuLoadInfo()); + } + + @GetMapping("cpuUtilization") + public ResponseData getCpuUtilization(){ + return ResponseData.success(selfMonitorService.getCpuUtilization()); + } + + @RequestMapping("process") + public ResponseData getProcessInfo(){ + return ResponseData.success(selfMonitorService.getProcessInfo()); + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java new file mode 100644 index 00000000..a662652b --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/LatestDto.java @@ -0,0 +1,36 @@ +package com.zmops.iot.web.analyse.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import lombok.Data; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class LatestDto { + + private String name; + + private String itemid; + + private Long attrId; + + private String key; + + private String clock; + + private String value; + + private String originalValue; + + private String change; + + private String tags; + + @CachedValue(value = "UNITS",fieldName = "unitsName") + private String units; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/Mapping.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/Mapping.java new file mode 100644 index 00000000..808c4fb5 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/Mapping.java @@ -0,0 +1,20 @@ +package com.zmops.iot.web.analyse.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author yefei + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Mapping { + private Integer mappingid; + private Integer valuemapid; + private String value; + private String newvalue; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/ValueMap.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/ValueMap.java new file mode 100644 index 00000000..5981742f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/ValueMap.java @@ -0,0 +1,17 @@ +package com.zmops.iot.web.analyse.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class ValueMap { + private String valuemapid; + + private String name; + + private List mappings; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java new file mode 100644 index 00000000..a0f82f6d --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/HistoryParam.java @@ -0,0 +1,23 @@ +package com.zmops.iot.web.analyse.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class HistoryParam extends BaseQueryParam { + + @NotNull(message = "请选择一个设备再查询") + private String deviceId; + + private List attrIds; + + private String timeFrom; + + private String timeTill; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java new file mode 100644 index 00000000..1554a3a1 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/dto/param/LatestParam.java @@ -0,0 +1,20 @@ +package com.zmops.iot.web.analyse.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class LatestParam extends BaseQueryParam { + @NotNull(message = "请选择一个设备再查询") + private String deviceId; + + private List attrIds; + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/CpuLoadEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/CpuLoadEnum.java new file mode 100644 index 00000000..39fe89ff --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/CpuLoadEnum.java @@ -0,0 +1,35 @@ +package com.zmops.iot.web.analyse.enums; + +import lombok.Getter; + +/** + * @author yefei + **/ +public enum CpuLoadEnum { + avg1("system.cpu.load[all,avg1]", "cpuLoadAvg1"), + avg5("system.cpu.load[all,avg5]", "cpuLoadAvg5"), + avg15("system.cpu.load[all,avg15]", "cpuLoadAvg15"); + + @Getter + String code; + @Getter + String message; + + CpuLoadEnum(String code, String message) { + this.code = code; + this.message = message; + } + + public static String getDescription(String status) { + if (status == null) { + return ""; + } else { + for (CpuLoadEnum s : CpuLoadEnum.values()) { + if (s.getCode().equals(status)) { + return s.getMessage(); + } + } + return ""; + } + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/MemoryUtilizationEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/MemoryUtilizationEnum.java new file mode 100644 index 00000000..a17ac3ec --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/MemoryUtilizationEnum.java @@ -0,0 +1,35 @@ +package com.zmops.iot.web.analyse.enums; + +import lombok.Getter; + +/** + * @author yefei + **/ +public enum MemoryUtilizationEnum { + utilization("vm.memory.utilization", "memoryUtilization"), + total("vm.memory.size[total]", "memoryTotal"), + available("vm.memory.size[available]", "memoryAvailable"); + + @Getter + String code; + @Getter + String message; + + MemoryUtilizationEnum(String code, String message) { + this.code = code; + this.message = message; + } + + public static String getDescription(String status) { + if (status == null) { + return ""; + } else { + for (MemoryUtilizationEnum s : MemoryUtilizationEnum.values()) { + if (s.getCode().equals(status)) { + return s.getMessage(); + } + } + return ""; + } + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/ProcessEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/ProcessEnum.java new file mode 100644 index 00000000..477c9eb7 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/enums/ProcessEnum.java @@ -0,0 +1,35 @@ +package com.zmops.iot.web.analyse.enums; + +import lombok.Getter; + +/** + * @author yefei + **/ +public enum ProcessEnum { + num("proc.num", "num"), + run("proc.num[,,run]", "run"), + max("kernel.maxproc", "max"); + + @Getter + String code; + @Getter + String message; + + ProcessEnum(String code, String message) { + this.code = code; + this.message = message; + } + + public static String getDescription(String status) { + if (status == null) { + return ""; + } else { + for (ProcessEnum s : ProcessEnum.values()) { + if (s.getCode().equals(status)) { + return s.getMessage(); + } + } + return ""; + } + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java new file mode 100644 index 00000000..daed9d8a --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HistoryService.java @@ -0,0 +1,155 @@ +package com.zmops.iot.web.analyse.service; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.iot.web.analyse.dto.Mapping; +import com.zmops.iot.web.analyse.dto.ValueMap; +import com.zmops.iot.web.analyse.dto.param.HistoryParam; +import com.zmops.zeus.driver.service.ZbxHistoryGet; +import com.zmops.zeus.driver.service.ZbxValueMap; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 历史数据服务 + **/ +@Service +public class HistoryService { + + @Autowired + ZbxHistoryGet zbxHistoryGet; + + @Autowired + ZbxValueMap zbxValueMap; + + public Pager queryHistory(HistoryParam historyParam) { + + List latestDtos = queryHistory(historyParam.getDeviceId(), historyParam.getAttrIds(), + dateTransfer(historyParam.getTimeFrom()), + dateTransfer(historyParam.getTimeTill())); + + List collect = latestDtos.stream().skip((historyParam.getPage() - 1) * historyParam.getMaxRow()) + .limit(historyParam.getMaxRow()).collect(Collectors.toList()); + + return new Pager<>(collect, latestDtos.size()); + } + + private long dateTransfer(String date) { + + LocalDateTime now = LocalDateTime.now(); + if (ToolUtil.isEmpty(date) || date.equals("now")) { + return LocalDateTimeUtils.getSecondsByTime(now); + } + + if (date.startsWith("now-")) { + String value = date.substring(date.indexOf("-") + 1, date.length() - 1); + String unit = date.substring(date.length() - 1); + switch (unit) { + case "m": + return LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(now, Integer.valueOf(value), ChronoUnit.MINUTES)); + case "d": + return LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(now, Integer.valueOf(value), ChronoUnit.DAYS)); + case "M": + return LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(now, Integer.valueOf(value), ChronoUnit.MONTHS)); + case "h": + return LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(now, Integer.valueOf(value), ChronoUnit.HOURS)); + case "y": + return LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(now, Integer.valueOf(value), ChronoUnit.YEARS)); + default: + return LocalDateTimeUtils.getSecondsByTime(now); + } + } else { + return LocalDateTimeUtils.getSecondsByStr(date); + } + } + + public List queryHistory(String deviceId, List attrIds, Long timeFrom, Long timeTill) { + //查询出设备 + Device one = new QDevice().deviceId.eq(deviceId).findOne(); + if (null == one || ToolUtil.isEmpty(one.getZbxId())) { + return Collections.emptyList(); + } + + //查询设备属性 + QProductAttribute query = new QProductAttribute().productId.eq(deviceId); + if (ToolUtil.isNotEmpty(attrIds)) { + query.attrId.in(attrIds); + } + + List list = query.findList(); + if (ToolUtil.isEmpty(list)) { + return Collections.emptyList(); + } + + //取出属性对应的ItemID + List zbxIds = list.parallelStream().map(ProductAttribute::getZbxId).collect(Collectors.toList()); + Map> valueTypeMap = list.parallelStream().collect(Collectors.groupingBy(ProductAttribute::getValueType)); + Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, o -> o, (a, b) -> a)); + List latestDtos = new ArrayList<>(); + if (null == timeFrom) { + timeFrom = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); + } + + //根据属性值类型 分组查询历史数据 + for (Map.Entry> map : valueTypeMap.entrySet()) { + latestDtos.addAll(queryHitoryData(one.getZbxId(), zbxIds, 1000, Integer.parseInt(map.getKey()), timeFrom, timeTill)); + } + + //处理值映射 + List valuemapids = list.parallelStream().filter(o -> null != o.getValuemapid()).map(ProductAttribute::getValuemapid).collect(Collectors.toList()); + Map> mappings = new ConcurrentHashMap<>(valuemapids.size()); + if (!CollectionUtils.isEmpty(valuemapids)) { + String res = zbxValueMap.valueMapGet(valuemapids.toString()); + List mappingList = JSONObject.parseArray(res, ValueMap.class); + if (!CollectionUtils.isEmpty(mappingList)) { + mappings = mappingList.stream().collect(Collectors.toMap(ValueMap::getValuemapid, ValueMap::getMappings, (a, b) -> a)); + } + } + + Map> finalMappings = mappings; + latestDtos.forEach(latestDto -> { + latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); + if (null != itemIdMap.get(latestDto.getItemid())) { + latestDto.setName(itemIdMap.get(latestDto.getItemid()).getName()); + latestDto.setAttrId(itemIdMap.get(latestDto.getItemid()).getAttrId()); + latestDto.setUnits(itemIdMap.get(latestDto.getItemid()).getUnits()); + + String valueMapid = itemIdMap.get(latestDto.getItemid()).getValuemapid(); + if (null != valueMapid) { + List mappingList = finalMappings.get(valueMapid); + if (!CollectionUtils.isEmpty(mappingList)) { + Map mappingMap = mappingList.parallelStream().collect(Collectors.toMap(Mapping::getValue, Mapping::getNewvalue, (a, b) -> a)); + latestDto.setValue(mappingMap.get(latestDto.getValue())); + } + } + } + }); + + return latestDtos; + } + + public List queryHitoryData(String hostId, List itemIds, int hisNum, Integer valueType, Long timeFrom, Long timeTill) { + String res = zbxHistoryGet.historyGet(hostId, itemIds, hisNum, valueType, timeFrom, timeTill); + return JSONObject.parseArray(res, LatestDto.class); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java new file mode 100644 index 00000000..846375df --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/HomeService.java @@ -0,0 +1,465 @@ +package com.zmops.iot.web.analyse.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.dtflys.forest.http.ForestResponse; +import com.zmops.iot.core.auth.context.LoginContextHolder; +import com.zmops.iot.domain.alarm.Problem; +import com.zmops.iot.domain.alarm.query.QProblem; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.DeviceOnlineReport; +import com.zmops.iot.domain.device.EventTriggerRecord; +import com.zmops.iot.domain.device.ServiceExecuteRecord; +import com.zmops.iot.domain.device.query.QDeviceOnlineReport; +import com.zmops.iot.domain.device.query.QEventTriggerRecord; +import com.zmops.iot.domain.device.query.QScenesTriggerRecord; +import com.zmops.iot.domain.device.query.QServiceExecuteRecord; +import com.zmops.iot.domain.product.query.QProduct; +import com.zmops.iot.enums.SeverityEnum; +import com.zmops.iot.enums.ValueType; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ParseUtil; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.alarm.dto.AlarmDto; +import com.zmops.iot.web.alarm.dto.param.AlarmParam; +import com.zmops.iot.web.alarm.service.AlarmService; +import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.iot.web.device.dto.TaosResponseData; +import com.zmops.iot.web.device.dto.param.DeviceParams; +import com.zmops.iot.web.device.service.DeviceService; +import com.zmops.zeus.driver.entity.ZbxItemInfo; +import com.zmops.zeus.driver.service.TDEngineRest; +import com.zmops.zeus.driver.service.ZbxHost; +import com.zmops.zeus.driver.service.ZbxItem; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 全局概览服务 + **/ +@Service +public class HomeService { + + @Autowired + private ZbxHost zbxHost; + + @Autowired + private ZbxItem zbxItem; + + @Autowired + HistoryService historyService; + + @Autowired + AlarmService alarmService; + + @Autowired + TDEngineRest tdEngineRest; + + @Autowired + DeviceService deviceService; + + private static String hostId = ""; + + private static final Map ITEM_Map = new ConcurrentHashMap<>(5); + + //Zbx 指标取数速率 key + private static final String KEY = "zabbix[wcache,values"; + + /** + * 服务器取数速率统计 + * + * @return + */ + public List> collectionRate(long timeFrom, long timeTill) { + if (ToolUtil.isEmpty(hostId)) { + if (ToolUtil.isEmpty(getZbxServerId())) { + return Collections.emptyList(); + } + } + if (ToolUtil.isEmpty(ITEM_Map)) { + if (ToolUtil.isEmpty(getItemMap())) { + return Collections.emptyList(); + } + } + + List latestDtos = new ArrayList<>(); + ITEM_Map.forEach((key, value) -> { + latestDtos.addAll(historyService.queryHitoryData(hostId, Collections.singletonList(key), 10000, 0, timeFrom, timeTill)); + }); + + latestDtos.forEach(latestDto -> { + latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd")); + if (null != ITEM_Map.get(latestDto.getItemid())) { + latestDto.setName(ITEM_Map.get(latestDto.getItemid())); + } + }); + + Map> collect = latestDtos.parallelStream().collect( + Collectors.groupingBy(LatestDto::getName, Collectors.groupingBy( + LatestDto::getClock, Collectors.averagingDouble(o -> Double.parseDouble(o.getValue())))) + ); + + List> collectList = new ArrayList<>(); + collect.forEach((key, value) -> { + Map collectMap = new HashMap<>(2); + List> tmpList = new ArrayList<>(); + value.forEach((date, val) -> { + Map valMap = new HashMap<>(2); + valMap.put("date", date); + valMap.put("val", val); + tmpList.add(valMap); + }); + List> dataList = tmpList.parallelStream().sorted( + Comparator.comparing(o -> o.get("date").toString())).collect(Collectors.toList()); + + collectMap.put("name", ValueType.getVal(key)); + collectMap.put("data", dataList); + collectList.add(collectMap); + }); + + return collectList; + } + + /** + * 获取服务器 hostid + * + * @return + */ + private String getZbxServerId() { + String response = zbxHost.hostGet("Zabbix server"); + List> ids = JSON.parseObject(response, List.class); + if (null != ids && ids.size() > 0) { + hostId = ids.get(0).get("hostid"); + return hostId; + } + return ""; + } + + /** + * 获取服务器 取数的ITEM + * + * @return + */ + private Map getItemMap() { + String itemList = zbxItem.getItemList(KEY, hostId); + List itemInfos = JSONObject.parseArray(itemList, ZbxItemInfo.class); + for (ZbxItemInfo itemInfo : itemInfos) { + ITEM_Map.put(itemInfo.getItemid(), formatName(itemInfo.getName())); + } + return ITEM_Map; + } + + /** + * 格式化显示的名称 + */ + private static String formatName(String name) { + if (name.length() < 53) { + return "avg"; + } + return name.substring(35, name.length() - 18); + } + + + /** + * 统计设备数量 + * + * @return + */ + public Map getDeviceNum(Integer timeFrom, Integer timeTill) { + Map deviceNumMap = new HashMap<>(4); + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + + List list = deviceService.deviceList(new DeviceParams()); + + deviceNumMap.put("total", list.size()); + deviceNumMap.put("disable", (int) list.parallelStream().filter(o -> "DISABLE".equals(o.getStatus())).count()); + deviceNumMap.put("online", (int) list.parallelStream().filter(o -> null != o.getOnline() && 1 == o.getOnline()).count()); + QProduct qProduct = new QProduct(); + if (tenantId != null) { + qProduct.tenantId.eq(tenantId); + } + deviceNumMap.put("product", qProduct.findCount()); + + QDeviceOnlineReport qDeviceOnlineReport = new QDeviceOnlineReport() + .createTime.ge(LocalDateTimeUtils.convertTimeToString(timeFrom, "yyyy-MM-dd")) + .createTime.lt(LocalDateTimeUtils.convertTimeToString(timeTill, "yyyy-MM-dd")); + if (tenantId != null) { + qDeviceOnlineReport.tenantId.eq(tenantId); + } + List onLineList = qDeviceOnlineReport.findList(); + + Map collect = onLineList.parallelStream() + .collect(Collectors.groupingBy(DeviceOnlineReport::getCreateTime, Collectors.summingLong(DeviceOnlineReport::getOnline))); + + List> trendsList = new ArrayList<>(); + + collect.forEach((key, value) -> { + Map map = new ConcurrentHashMap<>(2); + map.put("date", key); + map.put("val", value); + trendsList.add(map); + }); + List> result = trendsList.parallelStream() + .sorted(Comparator.comparing(o -> o.get("date").toString())).collect(Collectors.toList()); + deviceNumMap.put("trends", result); + + return deviceNumMap; + } + + /** + * 告警数量统计 + * + * @return + */ + private static final String[] severity = {"", "信息", "低级", "中级", "高级", "紧急"}; + + public Map getAlarmNum(long timeFrom, long timeTill) { + List alarmList = new QProblem().clock.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeFrom)) + .clock.lt(LocalDateTimeUtils.getLDTBySeconds((int) timeTill)).rClock.isNull().orderBy().clock.asc().findList(); + Map alarmMap = new ConcurrentHashMap<>(3); + + Map> initMap = new ConcurrentHashMap<>(5); + for (String s : severity) { + if (ToolUtil.isEmpty(s)) { + continue; + } + initMap.put(s, initMap(timeFrom, timeTill)); + } + + alarmMap.put("total", alarmList.size()); + Collections.reverse(alarmList); + //过滤出指定时间段内的告警 并顺序排序 + Map> tmpMap = alarmList.parallelStream() + .filter(o -> o.getSeverity() > 0).collect( + Collectors.groupingBy(o -> o.getSeverity() + "", Collectors.groupingBy( + o -> LocalDateTimeUtils.formatTime(o.getClock(), "yyyy-MM-dd"), Collectors.counting()))); + + List> trendsList = new ArrayList<>(); + initMap.forEach((key, value) -> { + Map trendsMap = new ConcurrentHashMap<>(2); + + List> list = new ArrayList<>(); + value.forEach((date, val) -> { + Map valMap = new ConcurrentHashMap<>(2); + valMap.put("date", date); + valMap.put("val", Optional.ofNullable(tmpMap.get(SeverityEnum.getVal(key))).map(o -> o.get(date)).orElse(val)); + list.add(valMap); + }); + list.sort(Comparator.comparing(o -> o.get("date").toString())); + trendsMap.put("name", key); + trendsMap.put("data", list); + trendsList.add(trendsMap); + }); + + alarmMap.put("trends", trendsList); + + + //今日开始时间 + Long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); + AlarmParam todayParam = new AlarmParam(); + todayParam.setTimeFrom(timeStart); + List todayAlarmList = alarmService.getAlarmList(todayParam); + Long todayAlarmNum = todayAlarmList.parallelStream().filter(o -> !o.getSeverity().equals("0")).count(); + alarmMap.put("today", todayAlarmNum); + + return alarmMap; + } + + /** + * 事件数量统计 + */ + public Map getEventNum(long timeFrom, long timeTill) { + List list = new QEventTriggerRecord().createTime.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeFrom)) + .createTime.lt(LocalDateTimeUtils.getLDTBySeconds((int) timeTill)).orderBy().createTime.asc().findList(); + + Map eventMap = new HashMap<>(3); + if (ToolUtil.isNotEmpty(list)) { + eventMap.put("total", list.size()); + Map initMap = initMap(timeFrom, timeTill); + Map tmpMap = list.parallelStream().collect( + Collectors.groupingBy(o -> LocalDateTimeUtils.formatTime(o.getCreateTime(), "yyyy-MM-dd"), Collectors.counting())); + + List> trendsList = new ArrayList<>(); + initMap.forEach((key, value) -> { + Map valMap = new ConcurrentHashMap<>(2); + valMap.put("date", key); + valMap.put("val", Optional.ofNullable(tmpMap.get(key)).orElse(value)); + trendsList.add(valMap); + }); + trendsList.sort(Comparator.comparing(o -> o.get("date").toString())); + eventMap.put("trends", trendsList); + } + + //今日开始时间 + long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); + long todayNum = new QEventTriggerRecord().createTime.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeStart)).findCount(); + + eventMap.put("today", todayNum); + + + return eventMap; + } + + /** + * 告警TOP统计 + */ + public List> getAlarmTop(long timeFrom, long timeTill) { + AlarmParam alarmParam = new AlarmParam(); + alarmParam.setTimeTill(timeTill); + alarmParam.setTimeFrom(timeFrom); + + List alarmList = alarmService.getAlarmList(alarmParam); + + Map tmpMap = new ConcurrentHashMap<>(); + + if (ToolUtil.isNotEmpty(alarmList)) { + tmpMap = alarmList.parallelStream().collect(Collectors.groupingBy(AlarmDto::getDeviceId, Collectors.counting())); + } + List> topList = new ArrayList<>(); + tmpMap.forEach((key, value) -> { + if (DefinitionsUtil.getDeviceName(key) == null) { + return; + } + Map alarmMap = new ConcurrentHashMap<>(2); + alarmMap.put("name", DefinitionsUtil.getDeviceName(key)); + alarmMap.put("value", value); + topList.add(alarmMap); + }); + topList.sort(Comparator.comparing(o -> Integer.parseInt(o.get("value").toString()))); + topList.subList(0, Math.min(topList.size(), 5)); + return topList; + } + + /** + * 服务调用统计 + */ + public Map serviceExecuteNum(long timeFrom, long timeTill) { + QServiceExecuteRecord query = new QServiceExecuteRecord().createTime.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeFrom)) + .createTime.lt(LocalDateTimeUtils.getLDTBySeconds((int) timeTill)); + + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + query.tenantId.eq(tenantId); + } + + List list = query.orderBy().createTime.asc().findList(); + Map executeMap = new ConcurrentHashMap<>(3); + if (ToolUtil.isNotEmpty(list)) { + executeMap.put("total", list.size()); + + Map initMap = initMap(timeFrom, timeTill); + Map tmpMap = list.parallelStream().collect(Collectors.groupingBy(o -> LocalDateTimeUtils.formatTime(o.getCreateTime(), + "yyyy-MM-dd"), Collectors.counting())); + + List> trendsList = new ArrayList<>(); + initMap.forEach((key, value) -> { + Map valMap = new ConcurrentHashMap<>(2); + valMap.put("date", key); + valMap.put("val", Optional.ofNullable(tmpMap.get(key)).orElse(value)); + trendsList.add(valMap); + }); + trendsList.sort(Comparator.comparing(o -> o.get("date").toString())); + executeMap.put("trends", trendsList); + } + //今日开始时间 + long timeStart = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now())); + + query = new QServiceExecuteRecord().createTime.ge(LocalDateTimeUtils.getLDTBySeconds((int) timeStart)); + if (null != tenantId) { + query.tenantId.eq(tenantId); + } + long todayNum = query.findCount(); + + executeMap.put("today", todayNum); + + return executeMap; + } + + /** + * 数据量统计 + */ + public Map dataLevel() { + + Map dataMap = new ConcurrentHashMap<>(4); + + dataMap.put("totalRecordNum", ParseUtil.getCommaFormat(getRecordNum() + "")); + dataMap.put("todayRecordNum", ParseUtil.getCommaFormat(getTodayRecordNum( + LocalDateTimeUtils.formatTime(LocalDateTimeUtils.getDayStart(LocalDateTime.now()))) + "")); + + QServiceExecuteRecord qServiceExecuteRecord = new QServiceExecuteRecord(); + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + qServiceExecuteRecord.tenantId.eq(tenantId); + } + + int serviceExecuteNum = qServiceExecuteRecord.findCount(); + dataMap.put("serviceExecuteNum", ParseUtil.getCommaFormat(serviceExecuteNum + "")); + + QScenesTriggerRecord qScenesTriggerRecord = new QScenesTriggerRecord(); + if (null != tenantId) { + qScenesTriggerRecord.tenantId.eq(tenantId); + } + int sceneTriggerNum = qScenesTriggerRecord.findCount(); + dataMap.put("sceneTriggerNum", ParseUtil.getCommaFormat(sceneTriggerNum + "")); + + return dataMap; + } + + private int getRecordNum() { + int totalRecord = 0; + String sql = "select count(1) from history"; + totalRecord += getRecordNum(sql); + + sql = "select count(1) from history_uint"; + totalRecord += getRecordNum(sql); + + return totalRecord; + } + + private int getTodayRecordNum(String time) { + int totalRecord = 0; + String sql = "select count(1) from history where clock>'" + time + "'"; + totalRecord += getRecordNum(sql); + + sql = "select count(1) from history_uint where clock>'" + time + "'"; + totalRecord += getRecordNum(sql); + + return totalRecord; + } + + private int getRecordNum(String sql) { + ForestResponse res_history = tdEngineRest.executeSql(sql); + + if (res_history.isError()) { + return 0; + } + + String res = res_history.getContent(); + + TaosResponseData taosResponseData = JSON.parseObject(res, TaosResponseData.class); + String[][] data_history = taosResponseData.getData(); + if (data_history.length > 0) { + return Integer.parseInt(data_history[0][0]); + } + return 0; + } + + private Map initMap(long start, long end) { + long l = LocalDateTimeUtils.betweenTwoTime(LocalDateTimeUtils.getLDTBySeconds((int) start), LocalDateTimeUtils.getLDTBySeconds((int) end), ChronoUnit.DAYS); + Map map = new HashMap<>((int) l); + map.put(LocalDateTimeUtils.formatTime(LocalDateTimeUtils.getLDTBySeconds((int) start), "yyyy-MM-dd"), 0L); + for (long i = 1; i <= l; i++) { + map.put(LocalDateTimeUtils.formatTime(LocalDateTimeUtils.plus(LocalDateTimeUtils.getLDTBySeconds((int) start), i, ChronoUnit.DAYS), "yyyy-MM-dd"), 0L); + } + return map; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java new file mode 100644 index 00000000..6f583b7d --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/LatestService.java @@ -0,0 +1,245 @@ +package com.zmops.iot.web.analyse.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.dtflys.forest.http.ForestResponse; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ParseUtil; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.iot.web.analyse.dto.Mapping; +import com.zmops.iot.web.analyse.dto.ValueMap; +import com.zmops.iot.web.analyse.dto.param.LatestParam; +import com.zmops.iot.web.device.dto.TaosResponseData; +import com.zmops.iot.web.init.BasicSettingsInit; +import com.zmops.zeus.driver.service.TDEngineRest; +import com.zmops.zeus.driver.service.ZbxHistoryGet; +import com.zmops.zeus.driver.service.ZbxValueMap; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 最新数据服务 + **/ +@Service +public class LatestService { + + @Autowired + ZbxHistoryGet zbxHistoryGet; + + @Autowired + ZbxValueMap zbxValueMap; + + @Autowired + TDEngineRest tdEngineRest; + + /** + * 查询最新数据 + * + * @param latestParam + * @return + */ + public Pager qeuryLatest(LatestParam latestParam) { + List latestDtos = qeuryLatest(latestParam.getDeviceId(), latestParam.getAttrIds()); + List collect = latestDtos.stream().skip((latestParam.getPage() - 1) * latestParam.getMaxRow()) + .limit(latestParam.getMaxRow()).collect(Collectors.toList()); + return new Pager<>(collect, latestDtos.size()); + } + + public List qeuryLatest(String deviceId, List attrIds) { + + //查询出设备 + Device one = new QDevice().deviceId.eq(deviceId).findOne(); + if (null == one || ToolUtil.isEmpty(one.getZbxId())) { + return Collections.emptyList(); + } + + //查询设备属性 + QProductAttribute query = new QProductAttribute().productId.eq(deviceId); + if (ToolUtil.isNotEmpty(attrIds)) { + query.attrId.in(attrIds); + } + + List list = query.findList(); + if (ToolUtil.isEmpty(list)) { + return Collections.emptyList(); + } + + Map> valueTypeMap = list.parallelStream().collect(Collectors.groupingBy(ProductAttribute::getValueType)); + Map itemIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getZbxId, o -> o, (a, b) -> a)); + List latestDtos; + if (checkTDengine()) { + latestDtos = queryLatestFromTD(deviceId, valueTypeMap); + } else { + latestDtos = queryLatestFromZbx(one.getZbxId(), valueTypeMap); + } + + + //处理值映射 + List valuemapids = list.parallelStream().filter(o -> null != o.getValuemapid()).map(ProductAttribute::getValuemapid).collect(Collectors.toList()); + Map> mappings = new ConcurrentHashMap<>(valuemapids.size()); + if (!CollectionUtils.isEmpty(valuemapids)) { + String res = zbxValueMap.valueMapGet(valuemapids.toString()); + List mappingList = JSONObject.parseArray(res, ValueMap.class); + if (!CollectionUtils.isEmpty(mappingList)) { + mappings = mappingList.stream().collect(Collectors.toMap(ValueMap::getValuemapid, ValueMap::getMappings, (a, b) -> a)); + } + } + + Map> finalMappings = mappings; + latestDtos.forEach(latestDto -> { +// latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); + latestDto.setOriginalValue(latestDto.getValue()); + if (null != itemIdMap.get(latestDto.getItemid())) { + latestDto.setName(itemIdMap.get(latestDto.getItemid()).getName()); + latestDto.setAttrId(itemIdMap.get(latestDto.getItemid()).getAttrId()); + latestDto.setUnits(itemIdMap.get(latestDto.getItemid()).getUnits()); + latestDto.setKey(itemIdMap.get(latestDto.getItemid()).getKey()); + + String valueMapid = itemIdMap.get(latestDto.getItemid()).getValuemapid(); + if (null != valueMapid) { + List mappingList = finalMappings.get(valueMapid); + if (!CollectionUtils.isEmpty(mappingList)) { + Map mappingMap = mappingList.parallelStream().collect(Collectors.toMap(Mapping::getValue, Mapping::getNewvalue, (a, b) -> a)); + latestDto.setValue(mappingMap.get(latestDto.getValue())); + } + } + } + }); + + return latestDtos; + } + + private boolean checkTDengine() { + String sql = String.format("select LAST_ROW(*) from history_uint where deviceid = 'Zabbix server';"); + + try { + ForestResponse resHistory = tdEngineRest.executeSql(sql); + + if (resHistory.isError()) { + return false; + } + } catch (Exception e) { + return false; + } + return true; + } + + //从TDengine取数 + public List queryLatestFromTD(String deviceId, Map> valueTypeMap) { + + List latestDtos = new ArrayList<>(); + //根据属性值类型 分组查询最新数据 + for (Map.Entry> map : valueTypeMap.entrySet()) { + //取出属性对应的ItemID + List itemIds = map.getValue().parallelStream().map(ProductAttribute::getZbxId).collect(Collectors.toList()); + latestDtos.addAll(queryLatestFromTD(deviceId, itemIds, Integer.parseInt(map.getKey()))); + } + return latestDtos; + } + + private List queryLatestFromTD(String deviceId, List itemIds, int unitType) { + String itemids = "'" + itemIds.parallelStream().collect(Collectors.joining("','")) + "'"; + String sql = String.format("select LAST_ROW(*) from %s where deviceid = '%s' and itemid in (%s) group by itemid;", getHistoryTableName(unitType), deviceId, itemids); + + ForestResponse resHistory = tdEngineRest.executeSql(sql); + + if (resHistory.isError()) { + return Collections.emptyList(); + } + + String res = resHistory.getContent(); + TaosResponseData taosResponseData = JSON.parseObject(res, TaosResponseData.class); + String[][] dataHistory = taosResponseData.getData(); + + List latestDtos = new ArrayList<>(); + if (dataHistory.length > 0) { + for (String[] data : dataHistory) { + LatestDto latestDto = new LatestDto(); + latestDto.setClock(LocalDateTimeUtils.formatTime(LocalDateTimeUtils.dateToStamp(data[0]))); + latestDto.setValue(ParseUtil.getFormatFloat(data[1])); + latestDto.setItemid(data[2]); + latestDtos.add(latestDto); + } + } + return latestDtos; + } + + private static String getHistoryTableName(int unitType) { + switch (unitType) { + case 0: + return "history"; + case 1: + return "history_str"; + case 3: + return "history_uint"; + case 4: + return "history_text"; + default: + throw new UnsupportedOperationException(); + } + } + + //从Zbx接口取数 + private List queryLatestFromZbx(String zbxId, Map> valueTypeMap) { + List latestDtos = new ArrayList<>(); + //根据属性值类型 分组查询最新数据 + for (Map.Entry> map : valueTypeMap.entrySet()) { + //取出属性对应的ItemID + List itemIds = map.getValue().parallelStream().map(ProductAttribute::getZbxId).collect(Collectors.toList()); + String res = zbxHistoryGet.historyGet(zbxId, itemIds, map.getValue().size(), Integer.parseInt(map.getKey()), null, null); + latestDtos.addAll(JSONObject.parseArray(res, LatestDto.class)); + } + + //根据itemid去重 + latestDtos = latestDtos.parallelStream().collect( + Collectors.collectingAndThen( + Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(LatestDto::getItemid))), + ArrayList::new) + ); + latestDtos.forEach(latestDto -> latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss"))); + + return latestDtos; + } + + /** + * 取事件属性 最新数据 + * + * @return List + */ + public List queryEventLatest(String hostid, List zbxIds, int valueType) { + + //根据属性值类型 查询最新数据 + + String res = zbxHistoryGet.historyGetWithNoAuth(hostid, zbxIds, 1, valueType, BasicSettingsInit.zbxApiToken); + List latestDtos = JSONObject.parseArray(res, LatestDto.class); + + latestDtos.forEach(latestDto -> { + latestDto.setClock(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(latestDto.getClock()), "yyyy-MM-dd HH:mm:ss")); + latestDto.setOriginalValue(latestDto.getValue()); + }); + + return latestDtos; + } + + + public Map queryMap(String deviceId) { + List latestDtos = qeuryLatest(deviceId, Collections.emptyList()); + if (ToolUtil.isEmpty(latestDtos)) { + return new HashMap<>(0); + } + return latestDtos.parallelStream().collect(Collectors.toMap(LatestDto::getKey, LatestDto::getValue, (a, b) -> a)); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java new file mode 100644 index 00000000..8c646178 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/SelfMonitorService.java @@ -0,0 +1,209 @@ +package com.zmops.iot.web.analyse.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ObjectUtils; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.iot.web.analyse.enums.CpuLoadEnum; +import com.zmops.iot.web.analyse.enums.MemoryUtilizationEnum; +import com.zmops.iot.web.analyse.enums.ProcessEnum; +import com.zmops.iot.web.product.dto.ZbxTriggerInfo; +import com.zmops.zeus.driver.entity.ZbxItemInfo; +import com.zmops.zeus.driver.service.ZbxHistoryGet; +import com.zmops.zeus.driver.service.ZbxHost; +import com.zmops.zeus.driver.service.ZbxItem; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Service +public class SelfMonitorService { + + @Autowired + ZbxHistoryGet zbxHistoryGet; + + @Autowired + ZbxHost zbxHost; + + @Autowired + ZbxItem zbxItem; + + @Autowired + HistoryService historyService; + + private static Map itemMap = new HashMap<>(); + + private static Map hostIdMap = new HashMap<>(); + + + public Map getMemInfo() { + Map resMap = new HashMap<>(3); + + getItemValue(getHostId("Zabbix server"), MemoryUtilizationEnum.utilization.getCode(), MemoryUtilizationEnum.utilization.getMessage(), 0, "%", resMap); + getItemValue(getHostId("Zabbix server"), MemoryUtilizationEnum.total.getCode(), MemoryUtilizationEnum.total.getMessage(), 3, "B", resMap); + getItemValue(getHostId("Zabbix server"), MemoryUtilizationEnum.available.getCode(), MemoryUtilizationEnum.available.getMessage(), 3, "B", resMap); + + resMap.put("trends", getTrendsData(getHostId("Zabbix server"), itemMap.get(MemoryUtilizationEnum.utilization.getMessage()), 0, "%")); + return resMap; + } + + public Map getCpuLoadInfo() { + Map resMap = new HashMap<>(3); + + getItemValue(getHostId("Zabbix server"), CpuLoadEnum.avg1.getCode(), CpuLoadEnum.avg1.getMessage(), 0, "%", resMap); + getItemValue(getHostId("Zabbix server"), CpuLoadEnum.avg5.getCode(), CpuLoadEnum.avg5.getMessage(), 0, "%", resMap); + getItemValue(getHostId("Zabbix server"), CpuLoadEnum.avg15.getCode(), CpuLoadEnum.avg15.getMessage(), 0, "%", resMap); + + resMap.put("trends", getTrendsData(getHostId("Zabbix server"), itemMap.get(CpuLoadEnum.avg1.getMessage()), 0, "%")); + return resMap; + } + + public Map getProcessInfo() { + Map resMap = new HashMap<>(3); + + getItemValue(getHostId("Zabbix server"), ProcessEnum.num.getCode(), ProcessEnum.num.getMessage(), 3, "个", resMap); + getItemValue(getHostId("Zabbix server"), ProcessEnum.run.getCode(), ProcessEnum.run.getMessage(), 3, "个", resMap); + getItemValue(getHostId("Zabbix server"), ProcessEnum.max.getCode(), ProcessEnum.max.getMessage(), 3, "个", resMap); + + resMap.put("trends", getTrendsData(getHostId("Zabbix server"), itemMap.get(ProcessEnum.run.getMessage()), 3, "个")); + return resMap; + } + + + public List> getCpuUtilization() { + String itemId = getItemId(getHostId("Zabbix server"), "CpuUtilization", "system.cpu.util"); + if (ToolUtil.isEmpty(itemId)) { + return Collections.emptyList(); + } + return getTrendsData(getHostId("Zabbix server"), itemId, 0, "%"); + } + + + /** + * 获取趋势数据 + * + * @param hostId 主机ID + * @param itemId 监控项ID + * @param itemValueType 监控项值类型 + * @return + */ + private List> getTrendsData(String hostId, String itemId, int itemValueType, String unit) { + long timeTill = LocalDateTimeUtils.getSecondsByTime(LocalDateTime.now()); + long timeFrom = LocalDateTimeUtils.getSecondsByTime(LocalDateTimeUtils.minu(LocalDateTime.now(), 1L, ChronoUnit.HOURS)); + + List latestDtos = historyService.queryHitoryData(hostId, Collections.singletonList(itemId), 20, itemValueType, timeFrom, timeTill); + + return latestDtos.stream().map(o -> { + Map tmpMap = new HashMap<>(2); + tmpMap.put("date", LocalDateTimeUtils.convertTimeToString(Integer.parseInt(o.getClock()), "yyyy-MM-dd HH:mm:ss")); + String value = ObjectUtils.convertUnits(o.getValue(), unit); + tmpMap.put("val", value); + return tmpMap; + }).collect(Collectors.toList()); + } + + /** + * 获取监控项最新值 + * + * @param hostId 主机ID + * @param key 监控项key + * @param name 监控项名称 + * @param itemValueType 监控项值类型 + * @param resMap map + */ + private void getItemValue(String hostId, String key, String name, int itemValueType, String unit, Map resMap) { + String itemId = getItemId(hostId, name, key); + + if (ToolUtil.isEmpty(itemId)) { + return; + } + String res = zbxHistoryGet.historyGet(null, Collections.singletonList(itemId), 1, itemValueType, null, null); + List latestDtos = JSONObject.parseArray(res, LatestDto.class); + + if (ToolUtil.isNotEmpty(latestDtos)) { + String value = ObjectUtils.convertUnits(latestDtos.get(0).getValue(), unit); + resMap.put(name, value); + } + } + + /** + * 从缓存取 hostId + * + * @param host 主机名称 + * @return hostId + */ + private String getHostId(String host) { + String hostId = hostIdMap.get(host); + if (ToolUtil.isEmpty(hostId)) { + hostId = getHostIdByName(host); + hostIdMap.put(host, hostId); + } + return hostId; + } + + /** + * 从Zbx取 hostId + * + * @param host 主机名称 + * @return hostId + */ + private String getHostIdByName(String host) { + String s = zbxHost.hostGet(host); + List hosts = JSON.parseArray(s, ZbxTriggerInfo.Host.class); + if (ToolUtil.isNotEmpty(hosts)) { + return hosts.get(0).getHostid(); + } + return ""; + } + + /** + * 从缓存取 itemId + * + * @param hostId 主机ID + * @param name 监控项名称 + * @param key 监控项key + * @return itemId + */ + private String getItemId(String hostId, String name, String key) { + String itemId = itemMap.get(name); + if (ToolUtil.isEmpty(itemId)) { + itemId = getItemIdByName(hostId, key); + itemMap.put(name, itemId); + } + return itemId; + } + + /** + * 从Zbx取 itemId + * + * @param hostId 主机ID + * @param key 监控项key + * @return itemId + */ + private String getItemIdByName(String hostId, String key) { + if (ToolUtil.isEmpty(key) || ToolUtil.isEmpty(hostId)) { + return ""; + } + + String item = zbxItem.getItemList(key, hostId); + List itemInfos = JSON.parseArray(item, ZbxItemInfo.class); + if (ToolUtil.isNotEmpty(itemInfos)) { + return itemInfos.get(0).getItemid(); + } + return ""; + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java new file mode 100644 index 00000000..0f39cc84 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/analyse/service/ZbxChartsService.java @@ -0,0 +1,188 @@ +package com.zmops.iot.web.analyse.service; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ToolUtil; +import com.zmops.zeus.driver.entity.ZbxItemInfo; +import com.zmops.zeus.driver.service.ZbxItem; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.PostMethod; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.List; + +/** + * @author yefei + *

+ * 全局概览服务 + **/ +@Service +public class ZbxChartsService { + + @Value("${forest.variables.zbxServerIp}") + private String zbxServerIp; + + @Value("${forest.variables.zbxServerPort}") + private String zbxServerPort; + + private static String COOKIE = ""; + + private static LocalDateTime COOKIE_TIME; + + @Autowired + ZbxItem zbxItem; + + /** + * 获取 数据图形展示 + * + * @param response http响应 + * @param from 开始时间 + * @param to 结束时间 + * @param attrIds 设备属性ID + * @param width 图表宽度 + * @param height 图表高度 + */ + public void getCharts(HttpServletResponse response, + String from, String to, + List attrIds, String width, String height) { + OutputStream out = null; + if (ToolUtil.isEmpty(COOKIE) || + LocalDateTimeUtils.betweenTwoTime(COOKIE_TIME, LocalDateTime.now(), ChronoUnit.DAYS) >= 30) { + getCookie(); + } + + List itemids = getItemIds(attrIds); + if (!validItemInfo(itemids)) { + try { + ClassPathResource classPathResource = new ClassPathResource("/nodata.jpg"); + InputStream inputStream = classPathResource.getInputStream(); + + response.setContentType("image/jpeg"); + + out = response.getOutputStream(); + out.write(toByteArray(inputStream)); + + out.flush(); + } catch (IOException ioException) { + ioException.printStackTrace(); + } finally { + try { + if (null != out) { + out.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return; + } + + HttpClient client = new HttpClient(); + PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + + "/zabbix/chart.php?type=0&profileIdx=web.item.graph.filter"); + + NameValuePair[] nameValuePairs = new NameValuePair[itemids.size() + 4]; + nameValuePairs[0] = new NameValuePair("from", from); + nameValuePairs[1] = new NameValuePair("to", to); + nameValuePairs[2] = new NameValuePair("width", width); + nameValuePairs[3] = new NameValuePair("height", height); + + for (int index = 0; index < itemids.size(); index++) { + nameValuePairs[4 + index] = new NameValuePair("itemids[" + index + "]", itemids.get(index)); + } + + postMethod.setRequestBody(nameValuePairs); + postMethod.setRequestHeader("Content_Type", "application/json-rpc"); + postMethod.setRequestHeader("Cookie", COOKIE); + + try { + client.executeMethod(postMethod); + InputStream responseBody = postMethod.getResponseBodyAsStream(); + response.setContentType("image/jpeg"); + + out = response.getOutputStream(); + out.write(toByteArray(responseBody)); + + out.flush(); + } catch (IOException ioException) { + ioException.printStackTrace(); + } finally { + try { + if (null != out) { + out.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + private boolean validItemInfo(List itemids) { + if (ToolUtil.isEmpty(itemids)) { + return false; + } + + List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(itemids.toString(), null), ZbxItemInfo.class); + if (ToolUtil.isEmpty(itemInfos)) { + return false; + } + return true; + } + + private static byte[] toByteArray(InputStream input) throws IOException { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + + byte[] buffer = new byte[4096]; + int n = 0; + + while (-1 != (n = input.read(buffer))) { + output.write(buffer, 0, n); + } + + return output.toByteArray(); + } + + + private List getItemIds(List attrIds) { + return new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(attrIds).zbxId.isNotNull().findSingleAttributeList(); + } + + /** + * 用户访客 获取cookie + */ + private void getCookie() { + HttpClient client = new HttpClient(); + PostMethod postMethod = new PostMethod("http://" + zbxServerIp + ":" + zbxServerPort + "/zabbix/index.php"); + + //TODO 使用了一个只读权限的访客用户 + NameValuePair namePair = new NameValuePair("name", "cookie"); + NameValuePair pwdPair = new NameValuePair("password", "cookie"); + NameValuePair autologinPair = new NameValuePair("autologin", "1"); + NameValuePair enterPair = new NameValuePair("enter", "Sign in"); + + postMethod.setRequestBody(new NameValuePair[]{namePair, pwdPair, autologinPair, enterPair}); + postMethod.setRequestHeader("Content_Type", "application/json"); + + try { + client.executeMethod(postMethod); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + COOKIE = postMethod.getResponseHeader("Set-Cookie").getValue(); + COOKIE_TIME = LocalDateTime.now(); + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java index 135d38df..d5397498 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/AuthService.java @@ -2,6 +2,7 @@ import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.convert.Convert; +import com.zmops.iot.constant.ConstantsContext; import com.zmops.iot.core.auth.cache.SessionManager; import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.core.auth.exception.AuthException; @@ -10,10 +11,11 @@ import com.zmops.iot.core.auth.jwt.payload.JwtPayLoad; import com.zmops.iot.core.auth.model.LoginUser; import com.zmops.iot.core.util.HttpContext; -import com.zmops.iot.core.util.RsaUtil; import com.zmops.iot.core.util.SaltUtil; import com.zmops.iot.domain.sys.SysUser; import com.zmops.iot.domain.sys.query.QSysUser; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.message.handler.MessageEventHandler; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.web.constant.state.ManagerStatus; import com.zmops.iot.web.exception.enums.BizExceptionEnum; @@ -24,6 +26,8 @@ import com.zmops.zeus.driver.service.ZbxUser; import io.ebean.DB; import io.ebean.SqlRow; +import org.apache.commons.codec.DecoderException; +import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -49,6 +53,8 @@ public class AuthService { @Autowired private ZbxUser zbxUser; + @Autowired + MessageEventHandler messageEventHandler; /** * 用户名 和 密码 登陆 @@ -58,6 +64,7 @@ public class AuthService { * @return */ public LoginUserDto login(String username, String password) { + SysUser user = new QSysUser().account.eq(username).findOne(); // 账号不存在 @@ -72,13 +79,13 @@ public LoginUserDto login(String username, String password) { //验证账号密码是否正确 try { - password = RsaUtil.decryptPwd(password); - } catch (Exception e) { + password = new String(Hex.decodeHex(password)); + } catch (DecoderException e) { throw new AuthException(AuthExceptionEnum.USERNAME_PWD_ERROR); } String requestMd5 = SaltUtil.md5Encrypt(password, user.getSalt()); - String dbMd5 = user.getPassword(); + String dbMd5 = user.getPassword(); if (dbMd5 == null || !dbMd5.equalsIgnoreCase(requestMd5)) { throw new AuthException(AuthExceptionEnum.USERNAME_PWD_ERROR); } @@ -91,12 +98,13 @@ public LoginUserDto login(String username, String password) { if (i == 0) { throw new ServiceException(BizExceptionEnum.ZBX_TOKEN_SAVE_ERROR); } - - + //单点登录 + if (CommonStatus.ENABLE.getCode().equals(ConstantsContext.getConstntsMap().get("ZEUS_SIGN_IN"))) { + messageEventHandler.sendDisconnectMsg(user.getUserId() + ""); + } return LoginUserDto.buildLoginUser(user, login(user)); } - /** * 用户名 登陆 * @@ -106,7 +114,7 @@ public LoginUserDto login(String username, String password) { public String login(SysUser user) { //记录登录日志 - LogManager.me().executeLog(LogTaskFactory.loginLog(user.getUserId(), getIp())); + LogManager.me().executeLog(LogTaskFactory.loginLog(user.getUserId(), getIp(), user.getTenantId())); //TODO key的作用 JwtPayLoad payLoad = new JwtPayLoad(user.getUserId(), user.getAccount(), "xxxx"); @@ -148,7 +156,8 @@ public void logout() { public void logout(String token) { //记录退出日志 - LogManager.me().executeLog(LogTaskFactory.exitLog(LoginContextHolder.getContext().getUser().getId(), getIp())); + LoginUser loginUser = LoginContextHolder.getContext().getUser(); + LogManager.me().executeLog(LogTaskFactory.exitLog(loginUser.getId(), getIp(), loginUser.getTenantId())); //删除Auth相关cookies Cookie[] cookies = HttpContext.getRequest().getCookies(); @@ -245,7 +254,7 @@ public boolean check(String[] roleNames) { return false; } ArrayList objects = CollectionUtil.newArrayList(roleNames); - String join = CollectionUtil.join(objects, ","); + String join = CollectionUtil.join(objects, ","); if (LoginContextHolder.getContext().hasAnyRoles(join)) { return true; } @@ -255,11 +264,11 @@ public boolean check(String[] roleNames) { public boolean checkAll(String code) { HttpServletRequest request = HttpContext.getRequest(); - LoginUser user = LoginContextHolder.getContext().getUser(); + LoginUser user = LoginContextHolder.getContext().getUser(); if (null == user) { return false; } - String sql = "select * from sys_menu where code = :code and menu_id in (SELECT menu_id from sys_role_menu where role_id = :roleId)"; + String sql = "select * from sys_menu where code = :code and menu_id in (SELECT menu_id from sys_role_menu where role_id = :roleId)"; List list = DB.sqlQuery(sql).setParameter("code", code).setParameter("roleId", user.getRoleList().get(0)).findList(); if (list.size() > 0) { return true; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/LoginContextSpringSecutiryImpl.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/LoginContextSpringSecutiryImpl.java index 4384c0ad..57eb1d76 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/LoginContextSpringSecutiryImpl.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/LoginContextSpringSecutiryImpl.java @@ -6,6 +6,7 @@ import com.zmops.iot.core.auth.exception.enums.AuthExceptionEnum; import com.zmops.iot.core.auth.model.LoginUser; import com.zmops.iot.core.auth.util.TokenUtil; +import com.zmops.iot.web.init.BasicSettingsInit; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; @@ -21,6 +22,12 @@ public class LoginContextSpringSecutiryImpl implements LoginContext { @Override public LoginUser getUser() { + + if (null == SecurityContextHolder.getContext().getAuthentication()) { + //默认 Admin + return new LoginUser(1L, BasicSettingsInit.zbxApiToken); + } + if (SecurityContextHolder.getContext().getAuthentication().getPrincipal() instanceof String) { throw new AuthException(AuthExceptionEnum.NOT_LOGIN_ERROR); } else { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/PermissionAop.java b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/PermissionAop.java index dac8d361..1cc3d57f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/auth/PermissionAop.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/auth/PermissionAop.java @@ -47,11 +47,11 @@ private void cutPermission() { @Around("cutPermission()") public Object doPermission(ProceedingJoinPoint point) throws Throwable { - MethodSignature ms = (MethodSignature) point.getSignature(); - Method method = ms.getMethod(); - Permission permission = method.getAnnotation(Permission.class); - String[] permissions = permission.value(); - String code = permission.code(); + MethodSignature ms = (MethodSignature) point.getSignature(); + Method method = ms.getMethod(); + Permission permission = method.getAnnotation(Permission.class); + String[] permissions = permission.value(); + String code = permission.code(); if (permissions.length == 0 && StringUtils.isNotBlank(code)) { //检查全体角色 boolean result = authService.checkAll(code); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceApiController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceApiController.java new file mode 100644 index 00000000..155a9ca6 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceApiController.java @@ -0,0 +1,73 @@ +package com.zmops.iot.web.device.controller; + +import com.zmops.iot.domain.device.ApiParam; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.proxy.Proxy; +import com.zmops.iot.domain.proxy.query.QProxy; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.zeus.driver.entity.ItemParam; +import com.zmops.zeus.driver.entity.SendParam; +import com.zmops.zeus.driver.service.ZbxConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +/** + * @author yefei + **/ +@RequestMapping("/device/api") +@RestController +public class DeviceApiController { + + @Autowired + ZbxConfig zbxConfig; + + //@Value("${forest.variables.zeusServerIp}") + private String IOT_SERVER_IP = "127.0.0.1"; + + @RequestMapping("/sendData") + public ResponseData sendData(@Validated @RequestBody ApiParam apiParam) { + Device device = new QDevice().deviceId.eq(apiParam.getDeviceId()).findOne(); + if (null == device) { + throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); + } + if (null != device.getProxyId()) { + Proxy proxy = new QProxy().id.eq(device.getProxyId()).findOne(); + IOT_SERVER_IP = proxy.getAddress(); + } + + List valueList = new ArrayList<>(); + if (ToolUtil.isNotEmpty(apiParam.getParams())) { + apiParam.getParams().forEach(params -> { + if (ToolUtil.isEmpty(params.getDeviceAttrKey()) || ToolUtil.isEmpty(params.getDeviceAttrValue())) { + return; + } + ItemParam itemParam = new ItemParam(); + itemParam.setHost(apiParam.getDeviceId()); + itemParam.setClock(LocalDateTimeUtils.getSecondsByTime(LocalDateTime.now())); + + itemParam.setKey(params.getDeviceAttrKey()); + itemParam.setValue(params.getDeviceAttrValue()); + valueList.add(itemParam); + }); + } + if (ToolUtil.isEmpty(valueList)) { + throw new ServiceException(BizExceptionEnum.ZBX_DEVICE_API_HASNOT_KEY); + } + SendParam sendParam = new SendParam(); + sendParam.setParams(valueList); + zbxConfig.sendData(IOT_SERVER_IP, sendParam); + return ResponseData.success(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java index 4391e72a..d78095f5 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceController.java @@ -1,5 +1,6 @@ package com.zmops.iot.web.device.controller; +import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.device.Device; @@ -8,8 +9,10 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.device.dto.param.DeviceParam; +import com.zmops.iot.web.device.dto.param.DeviceParams; import com.zmops.iot.web.device.service.DeviceService; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductTag; @@ -37,73 +40,120 @@ public class DeviceController { * * @return */ - @RequestMapping("/getDeviceByPage") + @Permission(code = "dev_list") + @PostMapping("/getDeviceByPage") public Pager devicePageList(@RequestBody DeviceParam deviceParam) { return deviceService.devicePageList(deviceParam); } + /** + * 设备列表 + * + * @return + */ + @Permission(code = "dev_list") + @PostMapping("/list") + public ResponseData deviceList(@RequestBody DeviceParams deviceParams) { + return ResponseData.success(deviceService.deviceList(deviceParams)); + } /** * 设备创建 */ + @Permission(code = "dev_add") @RequestMapping("/create") public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody DeviceDto deviceDto) { + if (ToolUtil.validDeviceName(deviceDto.getName())) { + throw new ServiceException(BizExceptionEnum.DEVICE_NAME_HAS_INCOREECT_CHARACTER); + } int count = new QDevice().name.eq(deviceDto.getName()).findCount(); if (count > 0) { throw new ServiceException(BizExceptionEnum.DEVICE_EXISTS); } + if (ToolUtil.isNotEmpty(deviceDto.getDeviceId())) { + count = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.DEVICE_ID_EXISTS); + } + } else { + deviceDto.setDeviceId(IdUtil.getSnowflake().nextId() + ""); + } + deviceDto.setEdit("false"); deviceService.checkProductExist(deviceDto); - - return ResponseData.success(deviceService.create(deviceDto)); + String deviceId = deviceService.create(deviceDto); + deviceDto.setDeviceId(deviceId); + return ResponseData.success(deviceDto); } /** * 设备创建 */ + @Permission(code = "dev_update") @RequestMapping("/update") public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody DeviceDto deviceDto) { + if (ToolUtil.validDeviceName(deviceDto.getName())) { + throw new ServiceException(BizExceptionEnum.DEVICE_NAME_HAS_INCOREECT_CHARACTER); + } int count = new QDevice().deviceId.ne(deviceDto.getDeviceId()).name.eq(deviceDto.getName()).findCount(); if (count > 0) { throw new ServiceException(BizExceptionEnum.DEVICE_EXISTS); } - + deviceDto.setEdit("true"); deviceService.checkProductExist(deviceDto); + deviceService.update(deviceDto); - - return ResponseData.success(deviceService.update(deviceDto)); + return ResponseData.success(deviceDto); } /** * 设备删除 */ + @Permission(code = "dev_delete") @RequestMapping("/delete") public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody DeviceDto deviceDto) { return ResponseData.success(deviceService.delete(deviceDto)); } + /** + * 设备启用、禁用 + */ + @Permission(code = "dev_update") + @RequestMapping("/status/update") + public ResponseData status(@Validated(BaseEntity.Status.class) @RequestBody DeviceDto deviceDto) { + Device device = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findOne(); + if (null == device) { + throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); + } + deviceService.status(deviceDto.getStatus(), deviceDto.getDeviceId(), device.getZbxId()); + return ResponseData.success(); + } + /** * 设备详情 */ + @Permission(code = "dev_detail") @GetMapping("/detail") - public ResponseData prodDetail(@RequestParam("deviceId") Long deviceId) { + public ResponseData prodDetail(@RequestParam("deviceId") String deviceId) { return ResponseData.success(deviceService.deviceDetail(deviceId)); } /** * 设备标签列表 */ + @Permission(code = "dev") @GetMapping("/tag/list") - public ResponseData prodTagList(@RequestParam("deviceId") Long deviceId) { + public ResponseData prodTagList(@RequestParam("deviceId") String deviceId) { return ResponseData.success(deviceService.deviceTagList(deviceId)); } /** * 设备值映射列表 */ + @Permission(code = "dev") @GetMapping("/valueMap/list") - public ResponseData valueMapList(@RequestParam("deviceId") Long deviceId) { + public ResponseData valueMapList(@RequestParam("deviceId") String deviceId) { return ResponseData.success(deviceService.valueMapList(deviceId)); } @@ -112,17 +162,18 @@ public ResponseData valueMapList(@RequestParam("deviceId") Long deviceId) { * * @return */ + @Permission(code = "dev") @PostMapping("/tag/update") public ResponseData deviceTagCreate(@RequestBody @Valid ProductTag productTag) { - Long deviceId = productTag.getProductId(); - Device device = new QDevice().deviceId.eq(deviceId).findOne(); + String deviceId = productTag.getProductId(); + Device device = new QDevice().deviceId.eq(deviceId).findOne(); if (null == device) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); } - deviceService.deviceTagCreate(productTag,device.getZbxId()); + deviceService.deviceTagCreate(productTag, device.getZbxId()); return ResponseData.success(productTag); } @@ -134,14 +185,15 @@ public ResponseData deviceTagCreate(@RequestBody @Valid ProductTag productTag) { * @param valueMap * @return */ - @PostMapping("/valuemap/update") + @Permission(code = "dev") + @PostMapping("/valueMap/update") public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create.class) ValueMap valueMap) { Device device = new QDevice().deviceId.eq(valueMap.getProductId()).findOne(); if (null == device) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); } - String response = ""; + String response; if (ToolUtil.isEmpty(valueMap.getValuemapid())) { response = deviceService.valueMapCreate(device.getZbxId(), valueMap.getValueMapName(), valueMap.getValueMaps()); } else { @@ -158,9 +210,10 @@ public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create * @param valueMap * @return */ - @PostMapping("/valuemap/delete") + @Permission(code = "dev") + @PostMapping("/valueMap/delete") public ResponseData prodValueMapDelete(@RequestBody @Validated(BaseEntity.Delete.class) ValueMap valueMap) { - String response = deviceService.valueMapDelete(valueMap.getValuemapid()); + String response = deviceService.valueMapDelete(valueMap.getValuemapid()); return ResponseData.success(JSONObject.parseObject(response).getJSONArray("valuemapids").get(0)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java new file mode 100644 index 00000000..f7e5a939 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceEventTriggerController.java @@ -0,0 +1,250 @@ +package com.zmops.iot.web.device.controller; + +import cn.hutool.core.util.IdUtil; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.domain.product.query.QProductEventExpression; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.enums.InheritStatus; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceEventRule; +import com.zmops.iot.web.device.service.DeviceEventRuleService; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import io.ebean.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 设备告警规则 + **/ +@RestController +@RequestMapping("/device/event/trigger") +public class DeviceEventTriggerController { + + @Autowired + DeviceEventRuleService deviceEventRuleService; + + @Autowired + private ZbxTrigger zbxTrigger; + + private static final String ALARM_TAG_NAME = "__alarm__"; + private static final String EXECUTE_TAG_NAME = "__execute__"; + private static final String EVENT_TAG_NAME = "__event__"; + private static final String EVENT_TYPE_NAME = "事件"; + + /** + * 触发器 详情 + * + * @param eventRuleId + * @return + */ + + @GetMapping("/detail") + public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @RequestParam("deviceId") String deviceId) { + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); + if (null == productEvent) { + throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); + } + return ResponseData.success(deviceEventRuleService.detail(productEvent, eventRuleId, deviceId)); + } + + /** + * 创建 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/create") + public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) + DeviceEventRule eventRule) { + //检查是否有重复动作服务 + deviceEventRuleService.checkService(eventRule.getDeviceServices()); + + Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name + + deviceEventRuleService.createDeviceEventRule(eventRuleId, eventRule); + + //step 1: 先创建 zbx 触发器 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + + //step 2: zbx 保存触发器 + String[] triggerIds = deviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + + //step 4: zbx 触发器创建 Tag + Map tags = new ConcurrentHashMap<>(3); + if (ToolUtil.isNotEmpty(eventRule.getTags())) { + tags = eventRule.getTags().stream() + .collect(Collectors.toMap(DeviceEventRule.Tag::getTag, DeviceEventRule.Tag::getValue, (k1, k2) -> k2)); + } + if (!tags.containsKey(ALARM_TAG_NAME)) { + tags.put(ALARM_TAG_NAME, "{HOST.HOST}"); + } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); + } +// Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); +// if (any.isPresent()) { +// tags.put(EVENT_TAG_NAME, eventRuleId + ""); +// } + for (String triggerId : triggerIds) { + zbxTrigger.triggerTagCreate(triggerId, tags); + } + + //step 5: 更新 zbxId + deviceEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); + + // 返回触发器ID + return ResponseData.success(eventRuleId); + } + + /** + * 修改 触发器状态 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @PostMapping("/status") + public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) DeviceEventRule eventRule) { + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getDeviceId()).asUpdate() + .set("status", eventRule.getStatus()).update(); + + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()) + .relationId.eq(eventRule.getDeviceId()).findOne(); + + if (null != productEventRelation && null != productEventRelation.getZbxId()) { + zbxTrigger.triggerStatusUpdate(productEventRelation.getZbxId(), eventRule.getStatus().equals(CommonStatus.ENABLE.getCode()) ? "0" : "1"); + } + + return ResponseData.success(); + } + + /** + * 修改 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/update") + public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) DeviceEventRule eventRule) { + int count = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()) + .findCount(); + if (count == 0) { + throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); + } + + //检查是否有重复动作服务 + deviceEventRuleService.checkService(eventRule.getDeviceServices()); + + //来自产品的告警规则 只能修改备注 + count = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).inherit.eq(InheritStatus.YES.getCode()) + .findCount(); + if (count > 0) { + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getDeviceId()) + .asUpdate().set("remark", eventRule.getRemark()).update(); + + return ResponseData.success(eventRule.getEventRuleId()); + } + + //step 1: 删除原有的 关联关系 + deviceEventRuleService.updateDeviceEventRule(eventRule.getEventRuleId(), eventRule); + + //step 1: 先创建 zbx 触发器 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + + //step 2: zbx 保存触发器 + String[] triggerIds = deviceEventRuleService.updateZbxTrigger(eventRule.getZbxId(), expression, eventRule.getEventLevel()); + + //step 4: zbx 触发器创建 Tag + Map tags = eventRule.getTags().stream() + .collect(Collectors.toMap(DeviceEventRule.Tag::getTag, DeviceEventRule.Tag::getValue, (k1, k2) -> k2)); + if (ToolUtil.isEmpty(tags)) { + tags = new HashMap<>(2); + } + if (!tags.containsKey(ALARM_TAG_NAME)) { + tags.put(ALARM_TAG_NAME, "{HOST.HOST}"); + } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); + } +// Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); +// if (any.isPresent()) { +// tags.put(EVENT_TAG_NAME, eventRule.getEventRuleId() + ""); +// } + for (String triggerId : triggerIds) { + zbxTrigger.triggerTagCreate(triggerId, tags); + } + + //step 5: 更新 zbxId 反写 + deviceEventRuleService.updateProductEventRuleZbxId(eventRule.getEventRuleId(), triggerIds); + + // 返回触发器ID + return ResponseData.success(eventRule.getEventRuleId()); + } + + + /** + * 删除 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/delete") + public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) DeviceEventRule eventRule) { + + ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(eventRule.getDeviceId()) + .eventRuleId.eq(eventRule.getEventRuleId()).findOne(); + + if (productEventRelation != null && InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { + throw new ServiceException(BizExceptionEnum.EVENT_PRODUCT_CANNOT_DELETE); + } + + //step 01:删除 zbx触发器 + if (productEventRelation != null && ToolUtil.isNotEmpty(productEventRelation.getZbxId())) { + List triggers = JSONObject.parseArray( + zbxTrigger.triggerGet(productEventRelation.getZbxId()), DeviceEventRuleService.Triggers.class); + + if (ToolUtil.isNotEmpty(triggers)) { + zbxTrigger.triggerDelete(productEventRelation.getZbxId()); + } + } + + //step 1:删除 与设备的关联 + new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 2:删除 关联的执行服务 + new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 3:删除 关联的表达式 + new QProductEventExpression().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 4:删除 触发器 + new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + return ResponseData.success(); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceGroupController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceGroupController.java index a18ffd42..eda11759 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceGroupController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceGroupController.java @@ -34,7 +34,7 @@ public class DeviceGroupController { * @return */ @PostMapping("/getDeviceGrpByPage") - public Pager getDeviceGrpByPage(@RequestBody DeviceGroupParam devGroupParam) { + public Pager getDeviceGrpByPage(@RequestBody DeviceGroupParam devGroupParam) { return deviceGroupService.deviceGroupPageList(devGroupParam); } @@ -55,7 +55,7 @@ public ResponseData deviceGroupList(@RequestBody DeviceGroupParam devGroupParam) */ @PostMapping("/create") @BussinessLog(value = "创建设备组") - public ResponseData createDeviceGroup(@Valid @RequestBody DeviceGroupDto deviceGroupDto) { + public ResponseData createDeviceGroup(@Validated(BaseEntity.Create.class) @RequestBody DeviceGroupParam deviceGroupDto) { return ResponseData.success(deviceGroupService.createDeviceGroup(deviceGroupDto)); } @@ -67,7 +67,7 @@ public ResponseData createDeviceGroup(@Valid @RequestBody DeviceGroupDto deviceG */ @PostMapping("/update") @BussinessLog(value = "更新设备组") - public ResponseData updateDeviceGroup(@Validated(BaseEntity.Update.class) @RequestBody DeviceGroupDto deviceGroupDto) { + public ResponseData updateDeviceGroup(@Validated(BaseEntity.Update.class) @RequestBody DeviceGroupParam deviceGroupDto) { return ResponseData.success(deviceGroupService.updateDeviceGroup(deviceGroupDto)); } @@ -78,7 +78,7 @@ public ResponseData updateDeviceGroup(@Validated(BaseEntity.Update.class) @Reque */ @PostMapping("/delete") @BussinessLog(value = "删除设备组") - public ResponseData deleteDeviceGroup(@Valid @RequestBody DeviceGroupParam deviceGroupParam) { + public ResponseData deleteDeviceGroup(@Validated(BaseEntity.Delete.class) @RequestBody DeviceGroupParam deviceGroupParam) { deviceGroupService.deleteDeviceGroup(deviceGroupParam); return ResponseData.success(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java new file mode 100644 index 00000000..85383e53 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceLogController.java @@ -0,0 +1,38 @@ +package com.zmops.iot.web.device.controller; + +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.dto.DeviceLogDto; +import com.zmops.iot.web.device.dto.param.DeviceLogParam; +import com.zmops.iot.web.device.service.DeviceLogService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + **/ +@RestController +@RequestMapping("/device/log") +public class DeviceLogController { + + @Autowired + DeviceLogService deviceLogService; + + @RequestMapping("list") + public ResponseData list(@RequestParam(value = "deviceId") String deviceId, + @RequestParam(value = "logType", required = false) String logType, + @RequestParam(value = "timeFrom", required = false) Long timeFrom, + @RequestParam(value = "timeTill", required = false) Long timeTill) { + + return ResponseData.success(deviceLogService.list(deviceId, logType, timeFrom, timeTill)); + } + + @RequestMapping("getLogByPage") + public Pager getLogByPage(@RequestBody DeviceLogParam deviceLogParam) { + + return deviceLogService.getLogByPage(deviceLogParam); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java index b3c045c5..1350f03b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceModelController.java @@ -3,6 +3,7 @@ import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSON; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; @@ -23,7 +24,7 @@ /** * @author yefei *

- * 设备物模型 + * 设备属性 */ @RestController @@ -34,6 +35,8 @@ public class DeviceModelController { @Autowired private DeviceModelService deviceModelService; + //依赖属性类型 + private static final String ATTR_SOURCE_DEPEND = "18"; /** * 设备物模型 分页列表 @@ -41,7 +44,7 @@ public class DeviceModelController { * @return ResponseData */ @RequestMapping("/getAttrTrapperByPage") - public Pager prodModelAttributeList(@RequestBody ProductAttrParam productAttr) { + public Pager prodModelAttributeList(@Validated(BaseEntity.Get.class) @RequestBody ProductAttrParam productAttr) { return deviceModelService.prodModelAttributeList(productAttr); } @@ -77,11 +80,22 @@ public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity. throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); } + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + if (productAttr.getDepAttrId() == null) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); + } + ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getDepAttrId()).findOne(); + if (null == productAttribute) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); + } + productAttr.setMasterItemId(productAttribute.getZbxId()); + } + Long attrId = IdUtil.getSnowflake().nextId(); productAttr.setAttrId(attrId); String response = deviceModelService.createTrapperItem(productAttr); - String zbxId = JSON.parseObject(response, TemplateIds.class).getItemids()[0]; + String zbxId = JSON.parseObject(response, TemplateIds.class).getItemids()[0]; deviceModelService.createProductAttr(productAttr, zbxId); @@ -101,6 +115,17 @@ public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity. throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); } + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + if (productAttr.getDepAttrId() == null) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); + } + ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getDepAttrId()).findOne(); + if (null == productAttribute) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); + } + productAttr.setMasterItemId(productAttribute.getZbxId()); + } + return ResponseData.success(deviceModelService.updateTrapperItem(productAttr)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceServiceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceServiceController.java new file mode 100644 index 00000000..b1ec4941 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/DeviceServiceController.java @@ -0,0 +1,29 @@ +package com.zmops.iot.web.device.controller; + +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.dto.ServiceExecuteDto; +import com.zmops.iot.web.device.service.DeviceSvrService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + **/ +@RestController +@CrossOrigin +@RequestMapping("/device/service") +public class DeviceServiceController { + + @Autowired + DeviceSvrService deviceSvrService; + + @RequestMapping("/execute") + public ResponseData execute(@Validated @RequestBody ServiceExecuteDto serviceExecuteDto) { + deviceSvrService.execute(serviceExecuteDto.getDeviceId(), serviceExecuteDto.getServiceId(), serviceExecuteDto.getServiceParams()); + return ResponseData.success(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java new file mode 100644 index 00000000..bdfbe6df --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/controller/MultipleDeviceEventTriggerController.java @@ -0,0 +1,303 @@ +package com.zmops.iot.web.device.controller; + +import cn.hutool.core.util.IdUtil; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.core.auth.context.LoginContextHolder; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.*; +import com.zmops.iot.domain.schedule.Task; +import com.zmops.iot.domain.schedule.query.QTask; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.MultipleDeviceEventDto; +import com.zmops.iot.web.device.dto.MultipleDeviceEventRule; +import com.zmops.iot.web.device.dto.param.MultipleDeviceEventParm; +import com.zmops.iot.web.device.service.MultipleDeviceEventRuleService; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import io.ebean.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +import static com.zmops.iot.web.device.service.MultipleDeviceEventRuleService.*; + +/** + * @author yefei + *

+ * 设备 场景 联动 + **/ +@RestController +@RequestMapping("/multiple/device/event/trigger") +public class MultipleDeviceEventTriggerController { + + @Autowired + MultipleDeviceEventRuleService multipleDeviceEventRuleService; + + @Autowired + private ZbxTrigger zbxTrigger; + + /** + * 场景 分页列表 + * + * @param eventParm + * @return + */ + @PostMapping("/getEventByPage") + public Pager getEventByPage(@RequestBody MultipleDeviceEventParm eventParm) { + return multipleDeviceEventRuleService.getEventByPage(eventParm); + } + + /** + * 场景 列表 + * + * @param eventParm + * @return + */ + @PostMapping("/list") + public ResponseData list(@RequestBody MultipleDeviceEventParm eventParm) { + return ResponseData.success(multipleDeviceEventRuleService.list(eventParm)); + } + + /** + * 设备联动 详情 + * + * @param eventRuleId + * @return + */ + + @GetMapping("/detail") + public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId) { + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); + if (null == productEvent) { + throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); + } + return ResponseData.success(multipleDeviceEventRuleService.detail(productEvent, eventRuleId)); + } + + /** + * 创建 设备联动 + * + * @param eventRule 设备联动规则 + * @return 设备联动ID + */ + @Transactional + @PostMapping("/create") + public ResponseData createDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) + MultipleDeviceEventRule eventRule) { + + int count = new QProductEvent().eventRuleName.eq(eventRule.getEventRuleName()).classify.eq("1").findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.SCENE_EXISTED); + } + + multipleDeviceEventRuleService.checkParam(eventRule); + + Long eventRuleId = IdUtil.getSnowflake().nextId(); + + eventRule.setEventRuleId(eventRuleId); + multipleDeviceEventRuleService.createDeviceEventRule(eventRule); + + if (TRIGGER_TYPE_CONDITION == eventRule.getTriggerType()) { + //step 1: 先创建 zbx 触发器 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + //时间区间表达式 + if (ToolUtil.isNotEmpty(eventRule.getTimeIntervals())) { + String timeExpression = eventRule.getTimeIntervals().parallelStream().map(Objects::toString).collect(Collectors.joining(" or ")); + expression = "(" + expression + ") and (" + timeExpression + ")"; + } + //step 2: zbx 保存触发器 + String[] triggerIds = multipleDeviceEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + + //step 4: zbx 触发器创建 Tag + Map tags = new ConcurrentHashMap<>(1); + if (ToolUtil.isNotEmpty(eventRule.getTags())) { + tags = eventRule.getTags().stream() + .collect(Collectors.toMap(MultipleDeviceEventRule.Tag::getTag, MultipleDeviceEventRule.Tag::getValue, (k1, k2) -> k2)); + } + + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(SCENE_TAG_NAME)) { + tags.put(SCENE_TAG_NAME, eventRuleId + ""); + } + + for (String triggerId : triggerIds) { + zbxTrigger.triggerTagCreate(triggerId, tags); + } + + //step 5: 更新 zbxId + multipleDeviceEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); + } + // 返回触发器ID + return ResponseData.success(eventRuleId); + } + + /** + * 修改 设备联动 状态 + * + * @param eventRule 设备联动规则 + */ + @PostMapping("/status") + public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) MultipleDeviceEventRule eventRule) { + + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); + if (null == productEvent) { + throw new ServiceException(BizExceptionEnum.SCENE_NOT_EXISTS); + } + + if (TRIGGER_TYPE_SCHEDULE == productEvent.getTriggerType()) { + DB.update(Task.class).where().eq("taskId", productEvent.getTaskId()).asUpdate() + .set("triggerStatus", eventRule.getStatus()).update(); + } else { + + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).asUpdate() + .set("status", eventRule.getStatus()).update(); + + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); + + if (null != productEventRelation && null != productEventRelation.getZbxId()) { + zbxTrigger.triggerStatusUpdate(productEventRelation.getZbxId(), eventRule.getStatus().equals(CommonStatus.ENABLE.getCode()) ? "0" : "1"); + } + } + + return ResponseData.success(); + } + + /** + * 修改 设备联动 + * + * @param eventRule 设备联动规则 + * @return 设备联动ID + */ + @Transactional + @PostMapping("/update") + public ResponseData updateDeviceEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) MultipleDeviceEventRule eventRule) { + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()) + .findOne(); + if (null == productEvent) { + throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); + } + int count = new QProductEvent().eventRuleName.eq(eventRule.getEventRuleName()).eventRuleId.ne(eventRule.getEventRuleId()).classify.eq("1").findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.SCENE_EXISTED); + } + + //检查参数 + multipleDeviceEventRuleService.checkParam(eventRule); + + //step 1: 删除原有的 关联关系 并重新建立 关联关系 + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).setMaxRows(1).findOne(); + eventRule.setTaskId(productEvent.getTaskId()); + if (null != productEventRelation) { + eventRule.setZbxId(productEventRelation.getZbxId()); + } + multipleDeviceEventRuleService.updateDeviceEventRule(eventRule); + + if (TRIGGER_TYPE_CONDITION == eventRule.getTriggerType()) { + + //step 1: 先创建 zbx 触发器 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + //时间区间表达式 + if (ToolUtil.isNotEmpty(eventRule.getTimeIntervals())) { + String timeExpression = eventRule.getTimeIntervals().parallelStream().map(Objects::toString).collect(Collectors.joining(" or ")); + expression = "(" + expression + ") and (" + timeExpression + ")"; + } + //step 2: zbx 保存触发器 + String[] triggerIds = multipleDeviceEventRuleService.createZbxTrigger(eventRule.getEventRuleId() + "", expression, eventRule.getEventLevel()); + + //step 4: zbx 触发器创建 Tag + Map tags = new ConcurrentHashMap<>(1); + if (ToolUtil.isNotEmpty(eventRule.getTags())) { + tags = eventRule.getTags().stream() + .collect(Collectors.toMap(MultipleDeviceEventRule.Tag::getTag, MultipleDeviceEventRule.Tag::getValue, (k1, k2) -> k2)); + } + + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(SCENE_TAG_NAME)) { + tags.put(SCENE_TAG_NAME, eventRule.getEventRuleId() + ""); + } + + for (String triggerId : triggerIds) { + zbxTrigger.triggerTagCreate(triggerId, tags); + } + + //step 5: 更新 zbxId 反写 + multipleDeviceEventRuleService.updateProductEventRuleZbxId(eventRule.getEventRuleId(), triggerIds); + } + // 返回触发器ID + return ResponseData.success(eventRule.getEventRuleId()); + } + + + /** + * 删除 设备联动 + * + * @param eventRule 设备联动规则 + */ + @Transactional + @PostMapping("/delete") + public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) MultipleDeviceEventRule eventRule) { + + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); + if (null == productEvent) { + throw new ServiceException(BizExceptionEnum.SCENE_NOT_EXISTS); + } + if (TRIGGER_TYPE_CONDITION == eventRule.getTriggerType()) { + List productEventRelationList = new QProductEventRelation() + .eventRuleId.eq(eventRule.getEventRuleId()).findList(); + + //step 01:删除 zbx触发器 + if (ToolUtil.isNotEmpty(productEventRelationList) && ToolUtil.isNotEmpty(productEventRelationList.get(0).getZbxId())) { + List triggers = JSONObject.parseArray( + zbxTrigger.triggerGet(productEventRelationList.get(0).getZbxId()), MultipleDeviceEventRuleService.Triggers.class); + + if (ToolUtil.isNotEmpty(triggers)) { + zbxTrigger.triggerDelete(productEventRelationList.get(0).getZbxId()); + } + } + + //step 1:删除 与设备的关联 + new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 2:删除 关联的表达式 + new QProductEventExpression().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 3:删除 关联的时间表达式 + new QProductEventTimeInterval().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + } else { + //step 1:删除 定时器 + new QTask().id.eq(productEvent.getTaskId()).delete(); + } + + //step 3:删除 关联的执行服务 + new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 4:删除 触发器 + new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + return ResponseData.success(); + } + + @RequestMapping("/execute") + public ResponseData execute(@RequestParam("eventRuleId") Long eventRuleId) { + int count = new QProductEvent().eventRuleId.eq(eventRuleId).classify.eq("1").findCount(); + if (count <= 0) { + throw new ServiceException(BizExceptionEnum.SCENE_NOT_EXISTS); + } + multipleDeviceEventRuleService.execute(eventRuleId, "手动", LoginContextHolder.getContext().getUser().getId()); + return ResponseData.success(); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java index 719e67ea..ec4eaf77 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceDto.java @@ -1,14 +1,15 @@ package com.zmops.iot.web.device.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.domain.BaseDto; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; import com.zmops.iot.model.cache.filter.DicType; +import com.zmops.zeus.driver.entity.Interface; import lombok.Data; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.time.LocalDateTime; import java.util.List; @@ -18,10 +19,12 @@ **/ @Data @JsonSerialize(using = CachedValueFilter.class) -public class DeviceDto implements BaseDto { +public class DeviceDto { - @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class}) - private Long deviceId; + @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Delete.class, BaseEntity.Status.class}) + private String deviceId; + + private String edit; @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private String name; @@ -31,24 +34,29 @@ public class DeviceDto implements BaseDto { private String productName; - @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + @NotEmpty(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private List deviceGroupIds; + @CachedValue(value = "STATUS", fieldName = "statusName") + @NotBlank(groups = {BaseEntity.Status.class}) private String status; - @CachedValue(value = "DEVICE_TYPE") + @CachedValue(value = "DEVICE_TYPE", fieldName = "typeName") private String type; private String remark; + @CachedValue(type = DicType.Tenant, fieldName = "tenantName") + private Long tenantId; + private LocalDateTime createTime; private LocalDateTime updateTime; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") private Long createUser; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") private Long updateUser; private Long oldProductId; @@ -59,4 +67,19 @@ public class DeviceDto implements BaseDto { private String groupName; + private String addr; + + private String position; + + private Integer online; + + private Long proxyId; + + private Interface deviceInterface; + + private LocalDateTime latestOnline; + + private String productCode; + + private String method; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRelationDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRelationDto.java new file mode 100644 index 00000000..4435e582 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRelationDto.java @@ -0,0 +1,18 @@ +package com.zmops.iot.web.device.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class DeviceEventRelationDto { + private Long id; + private Long eventRuleId; + private String relationId; + private String zbxId; + private String inherit; + private String status; + private String remark; + private String triggerDevice; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java new file mode 100644 index 00000000..0f3a8305 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceEventRule.java @@ -0,0 +1,143 @@ +package com.zmops.iot.web.device.dto; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.util.ToolUtil; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang.StringUtils; + +import javax.validation.Valid; +import javax.validation.constraints.Max; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author nantian created at 2021/9/14 14:47 + *

+ * 告警规则 + */ + +@Getter +@Setter +public class DeviceEventRule { + + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class, BaseEntity.Status.class}) + private Long eventRuleId; + + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private Byte eventNotify; // 0 否 1 是,默认 1 + + // 告警规则名称 + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String eventRuleName; + + // 告警规则级别 + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private Byte eventLevel; + + // 表达式列表 + @Valid + @NotEmpty(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private List expList; + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String expLogic; // and or + + private String remark; + + private List deviceServices; + + private List tags; + + @NotNull(groups = BaseEntity.Update.class) + private String zbxId; + + @NotBlank(groups = {BaseEntity.Status.class, BaseEntity.Delete.class}) + private String deviceId; + + @NotBlank(groups = BaseEntity.Status.class) + private String status; + + private String classify = "0"; + + @Data + public static class Tag { + + @Max(20) + private String tag; + + @Max(50) + private String value; + } + + @Getter + @Setter + // 告警表达式 构成 + public static class Expression { + + private Long eventExpId; + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String function; // last avg max min sum change nodata + + private String scope; // s m h T + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String condition; // > < = <> >= <= + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String value; + + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String productAttrKey; // 产品属性 Key + + private String deviceId; // 设备ID + + private String unit; + + private Long productAttrId; + + private String productAttrType; + + private String attrValueType; + + private String period; + + @Override + public String toString() { + StringBuilder expression = new StringBuilder(); + expression.append(function); + expression.append("(/"); + expression.append(deviceId); + expression.append("/"); + expression.append(productAttrKey); + + if (StringUtils.isNotBlank(scope)) { + expression.append(", "); + expression.append(scope); + } + expression.append(") ").append(condition).append(" ").append(ToolUtil.addQuotes(value)); + return expression.toString(); + } + } + + + @Setter + @Getter + public static class DeviceService { + + private String deviceId; + + private String executeDeviceId; + + private Long serviceId; + } + +} + + + + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java index 6a3b495d..c6339b5a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceGroupDto.java @@ -1,25 +1,15 @@ -/** - * Copyright 2018-2020 stylefeng & fengshuonan (https://gitee.com/stylefeng) - *

- * 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 - *

- * http://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.zmops.iot.web.device.dto; -import com.zmops.iot.domain.BaseEntity; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; /** * 设备组传输bean @@ -27,14 +17,25 @@ * @author yefei */ @Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonSerialize(using = CachedValueFilter.class) public class DeviceGroupDto { - @NotNull(groups = BaseEntity.Update.class) private Long deviceGroupId; - @NotBlank private String name; private String remark; + @CachedValue(type = DicType.Tenant, fieldName = "tenantName") + private Long tenantId; + + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + private Long createUser; + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + private Long updateUser; + private LocalDateTime createTime; + private LocalDateTime updateTime; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java new file mode 100644 index 00000000..fd767706 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceLogDto.java @@ -0,0 +1,54 @@ +package com.zmops.iot.web.device.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * @author yefei + **/ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@JsonSerialize(using = CachedValueFilter.class) +public class DeviceLogDto { + + private String logType; + + private String triggerTime; + + private String content; + + @CachedValue(type = DicType.Device, fieldName = "deviceName") + private String deviceId; + + @CachedValue(value = "EVENT_LEVEL", fieldName = "severityName") + private String severity; + + private String param; + + private String status; + + private String triggerType; + + private String triggerBody; + + private String key; + + private Long eventRuleId; + + private Long userId; + + private List triggerDevice; + + private List executeDevice; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceRelationDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceRelationDto.java new file mode 100644 index 00000000..932ee553 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/DeviceRelationDto.java @@ -0,0 +1,17 @@ +package com.zmops.iot.web.device.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class DeviceRelationDto { + + private String deviceId; + + private String name; + + private Long eventRuleId; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java new file mode 100644 index 00000000..fc9a81a1 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventDto.java @@ -0,0 +1,69 @@ +package com.zmops.iot.web.device.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.iot.domain.product.ProductEventService; +import com.zmops.iot.domain.product.ProductEventTimeInterval; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import java.util.List; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class MultipleDeviceEventDto { + + private Long eventRuleId; + + private Byte eventNotify; + + private String eventRuleName; + + @CachedValue(value = "EVENT_LEVEL", fieldName = "eventLevelName") + private String eventLevel; + + @CachedValue(value = "STATUS", fieldName = "statusName") + private String status; + + private String inherit; + + private String remark; + private String classify; + private String expLogic; + + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + private Long createUser; + private String createTime; + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + private Long updateUser; + + private String updateTime; + + private String triggerDevice; + + private String executeDevice; + + @CachedValue(type = DicType.Tenant, fieldName = "tenantName") + private Long tenantId; + + private Integer taskId; + + @CachedValue(value = "triggerType", fieldName = "triggerTypeName") + private String triggerType; + + private String scheduleConf; + + private List expList; + + private List deviceServices; + + private List tags; + + private List timeExpList; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java new file mode 100644 index 00000000..71b5a329 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceEventRule.java @@ -0,0 +1,169 @@ +package com.zmops.iot.web.device.dto; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.util.ToolUtil; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang.StringUtils; + +import javax.validation.constraints.Max; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author nantian created at 2021/9/14 14:47 + *

+ * 告警规则 + */ + +@Getter +@Setter +public class MultipleDeviceEventRule { + + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class, BaseEntity.Status.class}) + private Long eventRuleId; + + private Byte eventNotify = 0; + + // 名称 + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String eventRuleName; + + private Byte eventLevel = 1; + + // 表达式列表 + private List expList; + + private String expLogic = "and"; // and or + + private String remark; + + @NotEmpty(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private List deviceServices; + + private List tags; + + private String zbxId; + + private String deviceId; + + @NotBlank(groups = BaseEntity.Status.class) + private String status; + + private String classify = "1"; + + private Long tenantId; + + private String scheduleConf; + + @NotNull + private Integer triggerType = 0; + + private Integer taskId; + + private List timeIntervals; + + @Data + public static class Tag { + + @Max(20) + private String tag; + + @Max(50) + private String value; + } + + @Getter + @Setter + // 告警表达式 构成 + public static class Expression { + + private Long eventExpId; + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String function; // last avg max min sum change nodata + + private String scope; // s m h T + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String condition; // > < = <> >= <= + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String value; + + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String productAttrKey; // 产品属性 Key + + private String deviceId; // 设备ID + + private String unit; + + private Long productAttrId; + + private String productAttrType; + + private String attrValueType; + + private String period; + + @Override + public String toString() { + StringBuilder expression = new StringBuilder(); + expression.append(function); + expression.append("(/"); + expression.append(deviceId); + expression.append("/"); + expression.append(productAttrKey); + + if (StringUtils.isNotBlank(scope)) { + expression.append(", "); + expression.append(scope); + } + expression.append(") ").append(condition).append(" ").append(ToolUtil.addQuotes(value)); + return expression.toString(); + } + } + + + @Setter + @Getter + public static class DeviceService { + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String executeDeviceId; + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private Long serviceId; + + } + + @Getter + @Setter + public static class TimeInterval { + private String dayOfWeeks; + private String startTime; + private String endTime; + + @Override + public String toString() { + String weekExpression = ""; + if (ToolUtil.isNotEmpty(dayOfWeeks)) { + weekExpression = Arrays.asList(dayOfWeeks.split(",")).parallelStream().map(day -> "dayofweek()=" + day).collect(Collectors.joining(" or ")); + } + if (ToolUtil.isNotEmpty(weekExpression)) { + return "((" + weekExpression + ") and time()>= " + startTime + " and " + " time()< " + endTime + " )"; + } + return "(time()>= " + startTime + " and " + " time()< " + endTime + " )"; + } + } + +} + + + + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceServiceDto.java new file mode 100644 index 00000000..21e2b0de --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/MultipleDeviceServiceDto.java @@ -0,0 +1,16 @@ +package com.zmops.iot.web.device.dto; + +import lombok.Data; + + +/** + * @author yefei + **/ +@Data +public class MultipleDeviceServiceDto { + + private Long eventRuleId; + + private String executeDevice; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/ServiceExecuteDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/ServiceExecuteDto.java new file mode 100644 index 00000000..c2e446c3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/ServiceExecuteDto.java @@ -0,0 +1,29 @@ +package com.zmops.iot.web.device.dto; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class ServiceExecuteDto { + + @NotBlank + private String deviceId; + @NotNull + private Long serviceId; + + private List serviceParams; + + @Data + public static class ServiceParam { + @NotBlank + private String key; + @NotBlank + private String value; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/TaosResponseData.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/TaosResponseData.java new file mode 100644 index 00000000..94396507 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/TaosResponseData.java @@ -0,0 +1,21 @@ +package com.zmops.iot.web.device.dto; + +import lombok.Data; + +/** + * @author nantian created at 2021/8/2 16:59 + */ + +@Data +public class TaosResponseData { + + private String status; + + private String[] head; + + private String[][] column_meta; + + private String[][] data; + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceGroupParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceGroupParam.java index f99bc958..fde2e6b6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceGroupParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceGroupParam.java @@ -1,23 +1,10 @@ -/** - * Copyright 2018-2020 stylefeng & fengshuonan (https://gitee.com/stylefeng) - *

- * 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 - *

- * http://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.zmops.iot.web.device.dto.param; +import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.web.sys.dto.param.BaseQueryParam; import lombok.Data; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.util.List; @@ -29,8 +16,16 @@ @Data public class DeviceGroupParam extends BaseQueryParam { + @NotNull(groups = BaseEntity.Update.class) + private Long deviceGroupId; + + @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String name; - @NotNull + private String remark; + + @NotNull(groups = BaseEntity.Delete.class) private List deviceGroupIds; + + private Long tenantId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java new file mode 100644 index 00000000..f442b06e --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceLogParam.java @@ -0,0 +1,30 @@ +package com.zmops.iot.web.device.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class DeviceLogParam extends BaseQueryParam { + + private String logType; + + private String deviceId; + + private String content; + + private Long timeFrom; + + private Long timeTill; + + private String triggerType; + + private Long triggerUser; + + private Long eventRuleId; + + private String triggerDeviceId; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParam.java index a9102f34..e821b397 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParam.java @@ -3,8 +3,6 @@ import com.zmops.iot.web.sys.dto.param.BaseQueryParam; import lombok.Data; -import java.util.List; - /** * @author yefei **/ diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParams.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParams.java new file mode 100644 index 00000000..561cbc16 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/DeviceParams.java @@ -0,0 +1,27 @@ +package com.zmops.iot.web.device.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class DeviceParams extends BaseQueryParam { + + private String name; + private String deviceId; + + private List productIds; + + private List deviceGroupIds; + + private List prodTypes; + + private String tag; + + private String tagVal; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/MultipleDeviceEventParm.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/MultipleDeviceEventParm.java new file mode 100644 index 00000000..8ffe6a5a --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/dto/param/MultipleDeviceEventParm.java @@ -0,0 +1,20 @@ +package com.zmops.iot.web.device.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class MultipleDeviceEventParm extends BaseQueryParam { + + private String eventRuleName; + + private List deviceIds; + + private List deviceGrpIds; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java new file mode 100644 index 00000000..3ff2f39c --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/DeviceOnlineReprotSchedule.java @@ -0,0 +1,61 @@ +package com.zmops.iot.web.device.schedule; + +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.DeviceOnlineReport; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.util.LocalDateTimeUtils; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@EnableScheduling +@Component +@Slf4j +public class DeviceOnlineReprotSchedule { + + @Scheduled(cron = "0 59 23 1/1 * ? ") + public void report() { + log.info("开始查询设备在线情况"); + + //统计出 当前 设备在线情况 + List deviceList = new QDevice().findList(); + + Map> onLinemap = deviceList.parallelStream() + .collect(Collectors.groupingBy(o -> Optional.ofNullable(o.getTenantId()).orElse(0L), Collectors.groupingBy(o -> Optional.ofNullable(o.getOnline()).orElse(0), Collectors.counting()))); + + List list = new ArrayList<>(); + AtomicLong onLine = new AtomicLong(); + AtomicLong offLine = new AtomicLong(); + onLinemap.forEach((key, val) -> { + onLine.addAndGet(Optional.ofNullable(val.get(1)).orElse(0L)); + offLine.addAndGet(Optional.ofNullable(val.get(0)).orElse(0L)); + if (key == 0) { + return; + } + list.add(DeviceOnlineReport.builder().tenantId(key) + .createTime(LocalDateTimeUtils.formatTimeDate(LocalDateTime.now())) + .online(Optional.ofNullable(val.get(1)).orElse(0L)) + .offline(Optional.ofNullable(val.get(0)).orElse(0L)).build()); + }); + list.add(DeviceOnlineReport.builder() + .createTime(LocalDateTimeUtils.formatTimeDate(LocalDateTime.now())) + .online(onLine.get()) + .offline(offLine.get()).build()); + //插入 在线情况表 + DB.saveAll(list); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java new file mode 100644 index 00000000..c3c12114 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/schedule/SyncTaosTagSchedule.java @@ -0,0 +1,121 @@ +package com.zmops.iot.web.device.schedule; + +import com.alibaba.fastjson.JSON; +import com.dtflys.forest.http.ForestResponse; +import com.zmops.iot.domain.device.Tag; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.device.query.QTag; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.TaosResponseData; +import com.zmops.zeus.driver.service.TDEngineRest; +import com.zmops.zeus.driver.service.ZbxItem; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@EnableScheduling +@Component +@Slf4j +public class SyncTaosTagSchedule { + + @Autowired + ZbxItem zbxItem; + + @Autowired + TDEngineRest tdEngineRest; + + @Scheduled(cron = "0 55 23 1/1 * ? ") +// @Scheduled(cron = "0 0/1 * * * ? ") + public void sync() { + List deviceIds = new QDevice().select(QDevice.alias().deviceId).findSingleAttributeList(); + List tagList = new QTag().sid.in(deviceIds).findList(); + if (ToolUtil.isEmpty(tagList)) { + return; + } + Map> tagMap = tagList.parallelStream().collect(Collectors.groupingBy(Tag::getSid)); + + ForestResponse res_history = tdEngineRest.executeSql("DESCRIBE history;"); + if (res_history.isError()) { + return; + } + + String describe = res_history.getContent(); + + TaosResponseData taosResponseData = JSON.parseObject(describe, TaosResponseData.class); + String[][] data = taosResponseData.getData(); + + List taosTagNames = new ArrayList<>(); + for (String[] datum : data) { + if (ToolUtil.isNotEmpty(datum[3]) && "TAG".equals(datum[3])) { + taosTagNames.add(datum[0]); + } + } + + if (ToolUtil.isEmpty(taosTagNames)) { + return; + } + + List tagNames = tagList.parallelStream().map(Tag::getTag).collect(Collectors.toList()); + //新增taos没有的标签 + addTaosTag(tagNames, taosTagNames); + //删除taos标签 + delTaosTag(taosTagNames, tagNames); + + //更新子表 标签值 + tagMap.forEach((deviceId, tags) -> { + //根据deviceId 找到 设备下所有itemId + List itemIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).productId.eq(deviceId).zbxId.isNotNull().findSingleAttributeList(); + if (ToolUtil.isEmpty(itemIds)) { + return; + } + itemIds.forEach(itemId -> { + tags.forEach(tag -> { + tdEngineRest.executeSql("ALTER TABLE h_" + itemId + " SET TAG " + tag.getTag() + "='" + tag.getValue() + "'"); + }); + }); + + }); + } + + private void delTaosTag(List list1, List list2) { + + list1.removeAll(list2); + + if (ToolUtil.isEmpty(list1)) { + return; + } + + list1.forEach(tagName -> { + if ("deviceid".equals(tagName) || "itemid".equals(tagName)) { + return; + } + tdEngineRest.executeSql("ALTER STABLE history_uint DROP TAG '" + tagName + "'"); + tdEngineRest.executeSql("ALTER STABLE history DROP TAG '" + tagName + "'"); + }); + } + + private void addTaosTag(List list1, List list2) { + + list1.removeAll(list2); + if (ToolUtil.isEmpty(list1)) { + return; + } + + list1.forEach(tagName -> { + tdEngineRest.executeSql("ALTER STABLE history_uint ADD TAG " + tagName + " NCHAR(16)"); + tdEngineRest.executeSql("ALTER STABLE history ADD TAG " + tagName + " NCHAR(16)"); + }); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventPublisher.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventPublisher.java new file mode 100644 index 00000000..3b4cb0ad --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventPublisher.java @@ -0,0 +1,28 @@ +package com.zmops.iot.web.device.service; + +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceDeleteEvent; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import com.zmops.iot.web.event.applicationEvent.dto.DeviceDeleteEventData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +@Component +@EnableAsync +public class DeviceEventPublisher { + + @Autowired + ApplicationEventPublisher publisher; + + @Async + public void DeviceSaveEventPublish(DeviceDto deviceDto) { + publisher.publishEvent(new DeviceSaveEvent(this, deviceDto)); + } + + public void DeviceDeleteEventPublish(String deviceId, String zbxId) { + publisher.publishEvent(new DeviceDeleteEvent(this, DeviceDeleteEventData.builder().deviceId(deviceId).zbxId(zbxId).build())); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java new file mode 100644 index 00000000..48a4727e --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceEventRuleService.java @@ -0,0 +1,321 @@ +package com.zmops.iot.web.device.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventExpression; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.enums.InheritStatus; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceEventRule; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductEventRuleDto; +import com.zmops.iot.web.product.service.ProductEventRuleService; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import io.ebean.annotation.Transactional; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Service +public class DeviceEventRuleService { + + @Autowired + private ZbxTrigger zbxTrigger; + + @Autowired + ProductEventRuleService productEventRuleService; + + /** + * 保存触发器 + * + * @param eventRuleId 触发器ID + * @param eventRule 告警规则 + */ + @Transactional(rollbackFor = Exception.class) + public void createDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { + // step 1: 保存产品告警规则 + ProductEvent event = initEventRule(eventRule); + event.setEventRuleId(eventRuleId); + DB.save(event); + + //step 2: 保存 表达式,方便回显 + List expList = new ArrayList<>(); + + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = initEventExpression(i); + exp.setEventRuleId(eventRuleId); + expList.add(exp); + }); + DB.saveAll(expList); + + //step 3: 保存触发器 调用 动作服务 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + List deviceIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + deviceIds.forEach(deviceId -> { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) " + + "values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("deviceId", deviceId) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + }); + } + + //step 4: 保存关联关系 + List relationIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + if (ToolUtil.isEmpty(relationIds)) { + throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + } + List productEventRelationList = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setRelationId(relationId); + productEventRelation.setInherit(InheritStatus.NO.getCode()); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setRemark(eventRule.getRemark()); + productEventRelationList.add(productEventRelation); + }); + DB.saveAll(productEventRelationList); + + //更新缓存 + productEventRuleService.updateProductEvent(); + } + + @Transactional(rollbackFor = Exception.class) + public void updateDeviceEventRule(Long eventRuleId, DeviceEventRule eventRule) { + + //step 1: 函数表达式 + DB.sqlUpdate("delete from product_event_expression where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + + //step 2: 删除服务方法调用 + DB.sqlUpdate("delete from product_event_service where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + + // 删除和所有设备的关联关系 + new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + // step 3: 保存产品告警规则 + ProductEvent event = initEventRule(eventRule); + event.setEventRuleId(eventRuleId); + event.update(); + + //step 4: 保存 表达式,方便回显 + List expList = new ArrayList<>(); + + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = initEventExpression(i); + exp.setEventRuleId(eventRuleId); + expList.add(exp); + }); + + DB.saveAll(expList); + + //step 5: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + List deviceIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + deviceIds.forEach(deviceId -> { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("deviceId", deviceId) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + }); + } + + // step 6: 保存关联关系 + List relationIds = eventRule.getExpList().parallelStream().map(DeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + if (ToolUtil.isEmpty(relationIds)) { + throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + } + List productEventRelationList = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRuleId); + productEventRelation.setRelationId(relationId); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setRemark(eventRule.getRemark()); + productEventRelationList.add(productEventRelation); + }); + DB.saveAll(productEventRelationList); + + //更新缓存 + productEventRuleService.updateProductEvent(); + } + + + private ProductEvent initEventRule(DeviceEventRule eventRule) { + ProductEvent event = new ProductEvent(); + event.setEventLevel(eventRule.getEventLevel().toString()); + event.setExpLogic(eventRule.getExpLogic()); + event.setEventNotify(eventRule.getEventNotify().toString()); + event.setClassify(eventRule.getClassify()); + event.setEventRuleName(eventRule.getEventRuleName()); + return event; + } + + private ProductEventExpression initEventExpression(DeviceEventRule.Expression exp) { + ProductEventExpression eventExpression = new ProductEventExpression(); + eventExpression.setEventExpId(exp.getEventExpId()); + eventExpression.setCondition(exp.getCondition()); + eventExpression.setFunction(exp.getFunction()); + eventExpression.setScope(exp.getScope()); + eventExpression.setValue(exp.getValue()); + eventExpression.setDeviceId(exp.getDeviceId()); + eventExpression.setProductAttrKey(exp.getProductAttrKey()); + eventExpression.setProductAttrId(exp.getProductAttrId()); + eventExpression.setProductAttrType(exp.getProductAttrType()); + eventExpression.setPeriod(exp.getPeriod()); + eventExpression.setUnit(exp.getUnit()); + eventExpression.setAttrValueType(exp.getAttrValueType()); + return eventExpression; + } + + /** + * 更新 触发器规则 zbxId + * + * @param triggerId 规则ID + * @param zbxId triggerId + */ + public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { + +// List triggers = JSONObject.parseArray(zbxTrigger.triggerGet(Arrays.toString(zbxId)), Triggers.class); +// +// Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid)); +// +// List productEventRelationList = new QProductEventRelation().eventRuleId.eq(triggerId).findList(); + +// productEventRelationList.forEach(productEventRelation -> { +// if (null != map.get(productEventRelation.getRelationId())) { + DB.update(ProductEventRelation.class).where().eq("eventRuleId", triggerId) + .asUpdate().set("zbxId", zbxId[0]).update(); +// } +// }); + } + + /** + * 获取产品事件规则详情 + * + * @param productEvent + * @param eventRuleId + * @param deviceId + * @return + */ + public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, String deviceId) { + ProductEventRuleDto productEventRuleDto = new ProductEventRuleDto(); + ToolUtil.copyProperties(productEvent, productEventRuleDto); + + List expList = new QProductEventExpression().eventRuleId.eq(eventRuleId).findList(); + expList.forEach(productEventExpression -> { + if (ToolUtil.isEmpty(productEventExpression.getDeviceId())) { + productEventExpression.setDeviceId(deviceId); + } + }); + productEventRuleDto.setExpList(expList); + productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.eq(deviceId).findList()); + + ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(deviceId).eventRuleId.eq(eventRuleId).findOne(); + productEventRuleDto.setStatus(productEventRelation.getStatus()); + productEventRuleDto.setRemark(productEventRelation.getRemark()); + productEventRuleDto.setInherit(productEventRelation.getInherit()); + if (InheritStatus.YES.getCode().equals(productEventRelation.getInherit())) { + ProductEventRelation one = new QProductEventRelation().eventRuleId.eq(eventRuleId).inherit.eq(InheritStatus.NO.getCode()).findOne(); + productEventRuleDto.setInheritProductId(one.getRelationId()); + } + + + if (null != productEventRelation) { + JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); + + productEventRuleDto.setZbxId(productEventRelation.getZbxId()); + productEventRuleDto.setTags(tagList.stream() + .filter(s -> !s.getTag().equals("__execute__") && !s.getTag().equals("__alarm__") && !s.getTag().equals("__event__")) + .collect(Collectors.toList())); + } + return productEventRuleDto; + } + + /** + * 创建 触发器 + * + * @param triggerName 触发器名称 + * @param expression 表达式 + * @param level 告警等级 + * @return 触发器ID + */ + public String[] createZbxTrigger(String triggerName, String expression, Byte level) { + String res = zbxTrigger.triggerCreate(triggerName, expression, level,0); + return JSON.parseObject(res, TriggerIds.class).getTriggerids(); + } + + /** + * 更新 触发器 + * + * @param triggerId + * @param expression + * @param level + * @return + */ + public String[] updateZbxTrigger(String triggerId, String expression, Byte level) { + String res = zbxTrigger.triggerUpdate(triggerId, expression, level); + return JSON.parseObject(res, TriggerIds.class).getTriggerids(); + } + + /** + * 检查动作服务是否重复 + * + * @param deviceServices + */ + public void checkService(List deviceServices) { + if (ToolUtil.isEmpty(deviceServices)) { + return; + } + long count = deviceServices.parallelStream().map(DeviceEventRule.DeviceService::getServiceId).distinct().count(); + if (count < deviceServices.size()) { + throw new ServiceException(BizExceptionEnum.SERVICE_HAS_DUPLICATE); + } + } + + @Data + static class TriggerIds { + private String[] triggerids; + } + + @Data + public static class Triggers { + private String triggerid; + private String description; + private List hosts; + } + + @Data + public static class Hosts { + private String hostid; + private String host; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java index 1143146a..34e5d249 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceGroupService.java @@ -3,6 +3,8 @@ import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.core.auth.context.LoginContextHolder; +import com.zmops.iot.core.auth.model.LoginUser; import com.zmops.iot.domain.device.DeviceGroup; import com.zmops.iot.domain.device.query.QDeviceGroup; import com.zmops.iot.domain.device.query.QDevicesGroups; @@ -13,6 +15,7 @@ import com.zmops.iot.web.device.dto.DeviceGroupDto; import com.zmops.iot.web.device.dto.param.DeviceGroupParam; import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.zeus.driver.entity.ZbxHostGrpInfo; import com.zmops.zeus.driver.service.ZbxHostGroup; import io.ebean.DB; import io.ebean.PagedList; @@ -21,6 +24,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -40,17 +45,27 @@ public class DeviceGroupService { * @param devGroupParam * @return */ - public Pager deviceGroupPageList(DeviceGroupParam devGroupParam) { + public Pager deviceGroupPageList(DeviceGroupParam devGroupParam) { + List devGroupIds = getDevGroupIds(); + if (ToolUtil.isEmpty(devGroupIds)) { + return new Pager<>(); + } QDeviceGroup qDeviceGroup = new QDeviceGroup(); + + qDeviceGroup.deviceGroupId.in(devGroupIds); + if (ToolUtil.isNotEmpty(devGroupParam.getName())) { qDeviceGroup.name.contains(devGroupParam.getName()); } qDeviceGroup.order().createTime.desc() .setFirstRow((devGroupParam.getPage() - 1) * devGroupParam.getMaxRow()) .setMaxRows(devGroupParam.getMaxRow()); + PagedList pagedList = qDeviceGroup.orderBy(" create_time desc").findPagedList(); - return new Pager<>(pagedList.getList(), pagedList.getTotalCount()); + + List deviceGroupDtos = ToolUtil.convertBean(pagedList.getList(), DeviceGroupDto.class); + return new Pager<>(deviceGroupDtos, pagedList.getTotalCount()); } /** @@ -60,8 +75,12 @@ public Pager deviceGroupPageList(DeviceGroupParam devGroupParam) { * @return */ public List deviceGroupList(DeviceGroupParam devGroupParam) { - + List devGroupIds = getDevGroupIds(); + if (ToolUtil.isEmpty(devGroupIds)) { + return Collections.emptyList(); + } QDeviceGroup qDeviceGroup = new QDeviceGroup(); + qDeviceGroup.deviceGroupId.in(devGroupIds); if (ToolUtil.isNotEmpty(devGroupParam.getName())) { qDeviceGroup.name.contains(devGroupParam.getName()); } @@ -69,13 +88,37 @@ public List deviceGroupList(DeviceGroupParam devGroupParam) { return qDeviceGroup.findList(); } + /** + * 获取当前登录用户绑定的主机组ID + * + * @return + */ + public List getDevGroupIds() { + LoginUser user = LoginContextHolder.getContext().getUser(); + Long curUserGrpId = user.getUserGroupId(); + Long tenantId = user.getTenantId(); + + List devGroupIds = new ArrayList<>(); + if (null != curUserGrpId) { + devGroupIds = new QSysUserGrpDevGrp().select(QSysUserGrpDevGrp.alias().deviceGroupId).userGroupId.eq(curUserGrpId).findSingleAttributeList(); + } + + if (ToolUtil.isEmpty(devGroupIds) && null != curUserGrpId) { + QDeviceGroup qDeviceGroup = new QDeviceGroup().select(QDeviceGroup.alias().deviceGroupId); + if (null != tenantId) { + qDeviceGroup.tenantId.eq(tenantId); + } + devGroupIds = qDeviceGroup.findSingleAttributeList(); + } + return devGroupIds; + } /** * 添加设备組 */ - public DeviceGroup createDeviceGroup(DeviceGroupDto deviceGroup) { + public DeviceGroup createDeviceGroup(DeviceGroupParam deviceGroup) { // 判断设备组是否重复 - checkByGroupName(deviceGroup.getName(), -1L); + checkByGroupName(deviceGroup.getName(), -1L, deviceGroup.getTenantId()); //获取ID long devGrpId = IdUtil.getSnowflake().nextId(); // 先在ZBX 添加主机组 @@ -85,10 +128,9 @@ public DeviceGroup createDeviceGroup(DeviceGroupDto deviceGroup) { newDeviceGroup.setDeviceGroupId(devGrpId); //回填 ZBX主机组ID JSONObject result = JSONObject.parseObject(zbxHostGroup.hostGroupCreate(String.valueOf(devGrpId))); - JSONArray grpids = result.getJSONArray("groupids"); + JSONArray grpids = result.getJSONArray("groupids"); newDeviceGroup.setZbxId(grpids.get(0).toString()); DB.save(newDeviceGroup); - return newDeviceGroup; } @@ -98,9 +140,9 @@ public DeviceGroup createDeviceGroup(DeviceGroupDto deviceGroup) { * @param deviceGroup * @return DeviceGroup */ - public DeviceGroup updateDeviceGroup(DeviceGroupDto deviceGroup) { + public DeviceGroup updateDeviceGroup(DeviceGroupParam deviceGroup) { // 判断设备组是否重复 - checkByGroupName(deviceGroup.getName(), deviceGroup.getDeviceGroupId()); + checkByGroupName(deviceGroup.getName(), deviceGroup.getDeviceGroupId(), deviceGroup.getTenantId()); DeviceGroup newDeviceGroup = new DeviceGroup(); BeanUtils.copyProperties(deviceGroup, newDeviceGroup); @@ -114,12 +156,12 @@ public DeviceGroup updateDeviceGroup(DeviceGroupDto deviceGroup) { * * @param groupName */ - private void checkByGroupName(String groupName, long deviceGroupId) { + private void checkByGroupName(String groupName, long deviceGroupId, Long tenantId) { int count; if (deviceGroupId >= 0) { - count = new QDeviceGroup().name.equalTo(groupName).deviceGroupId.ne(deviceGroupId).findCount(); + count = new QDeviceGroup().name.equalTo(groupName).tenantId.eq(tenantId).deviceGroupId.ne(deviceGroupId).findCount(); } else { - count = new QDeviceGroup().name.equalTo(groupName).findCount(); + count = new QDeviceGroup().name.equalTo(groupName).tenantId.eq(tenantId).findCount(); } if (count > 0) { throw new ServiceException(BizExceptionEnum.DEVICEGROUP_HAS_EXIST); @@ -146,7 +188,12 @@ public void deleteDeviceGroup(DeviceGroupParam deviceGroupParam) { //删除ZBX中主机组 List zbxHostGrpIds = list.parallelStream().map(DeviceGroup::getZbxId).collect(Collectors.toList()); - zbxHostGroup.hostGroupDelete(zbxHostGrpIds); + if (ToolUtil.isNotEmpty(zbxHostGrpIds)) { + List zbxHostGrpInfos = JSONObject.parseArray(zbxHostGroup.getHostGroup(zbxHostGrpIds.toString()), ZbxHostGrpInfo.class); + if (ToolUtil.isNotEmpty(zbxHostGrpInfos)) { + zbxHostGroup.hostGroupDelete(zbxHostGrpInfos.parallelStream().map(ZbxHostGrpInfo::getGroupid).collect(Collectors.toList())); + } + } // 删除 与用户组关联 diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java new file mode 100644 index 00000000..46f918be --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceLogService.java @@ -0,0 +1,343 @@ +package com.zmops.iot.web.device.service; + + +import com.zmops.iot.core.auth.context.LoginContextHolder; +import com.zmops.iot.domain.device.EventTriggerRecord; +import com.zmops.iot.domain.device.ScenesTriggerRecord; +import com.zmops.iot.domain.device.ServiceExecuteRecord; +import com.zmops.iot.domain.device.query.QEventTriggerRecord; +import com.zmops.iot.domain.device.query.QScenesTriggerRecord; +import com.zmops.iot.domain.device.query.QServiceExecuteRecord; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.alarm.dto.AlarmDto; +import com.zmops.iot.web.alarm.dto.param.AlarmParam; +import com.zmops.iot.web.alarm.service.AlarmService; +import com.zmops.iot.web.device.dto.DeviceLogDto; +import com.zmops.iot.web.device.dto.DeviceRelationDto; +import com.zmops.iot.web.device.dto.param.DeviceLogParam; +import com.zmops.iot.web.event.applicationEvent.DeviceSceneLogEvent; +import com.zmops.iot.web.event.applicationEvent.DeviceServiceLogEvent; +import com.zmops.iot.web.event.applicationEvent.dto.LogEventData; +import io.ebean.DB; +import io.ebean.PagedList; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Service +public class DeviceLogService { + + private static final String LOG_TYPE_ALARM = "告警日志"; + private static final String LOG_TYPE_EVENT = "事件日志"; + private static final String LOG_TYPE_SERVICE = "服务日志"; + private static final String LOG_TYPE_SCENES = "联动日志"; + + @Autowired + AlarmService alarmService; + + @Autowired + ApplicationEventPublisher publisher; + + public List list(String deviceId, String logType, Long timeFrom, Long timeTill) { + List deviceLogDtoList = new ArrayList<>(); + if (ToolUtil.isEmpty(logType) || (ToolUtil.isNotEmpty(logType) && LOG_TYPE_ALARM.equals(logType))) { + AlarmParam alarmParam = new AlarmParam(); + alarmParam.setDeviceId(deviceId); + alarmParam.setTimeFrom(timeFrom); + alarmParam.setTimeTill(timeTill); + List alarmList = alarmService.getAlarmList(alarmParam); + if (ToolUtil.isNotEmpty(alarmList)) { + alarmList.forEach(alarm -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) + .triggerTime(LocalDateTimeUtils.formatTime(alarm.getClock())) + .status(null == alarm.getRClock() ? "未解决" : "已解决").build()); + }); + } + } + + if (ToolUtil.isEmpty(logType) || (ToolUtil.isNotEmpty(logType) && LOG_TYPE_EVENT.equals(logType))) { + QEventTriggerRecord query = new QEventTriggerRecord().deviceId.eq(deviceId); + if (null != timeFrom) { + query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(timeFrom * 1000)); + } + if (null != timeTill) { + query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(timeTill * 1000)); + } + List list = query.findList(); + if (ToolUtil.isNotEmpty(list)) { + list.forEach(service -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_EVENT).content(service.getEventName()) + .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())) + .param(service.getEventName()).build()); + }); + } + } + + if (ToolUtil.isEmpty(logType) || (ToolUtil.isNotEmpty(logType) && LOG_TYPE_SERVICE.equals(logType))) { + QServiceExecuteRecord query = new QServiceExecuteRecord().deviceId.eq(deviceId); + if (null != timeFrom) { + query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(timeFrom * 1000)); + } + if (null != timeTill) { + query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(timeTill * 1000)); + } + List list = query.findList(); + if (ToolUtil.isNotEmpty(list)) { + list.forEach(service -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_SERVICE).content(service.getServiceName()) + .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())) + .param(service.getParam()).build()); + }); + } + } + deviceLogDtoList.sort(Comparator.comparing(DeviceLogDto::getTriggerTime)); + return deviceLogDtoList; + } + + + public Pager getLogByPage(DeviceLogParam deviceLogParam) { + + String logType = deviceLogParam.getLogType(); + + if (ToolUtil.isNotEmpty(logType) && LOG_TYPE_SERVICE.equals(logType)) { + + return getServiceLog(deviceLogParam); + + } else if (ToolUtil.isNotEmpty(logType) && LOG_TYPE_SCENES.equals(logType)) { + + return getScenesLog(deviceLogParam); + + } else { + + return getEventLog(deviceLogParam); + + } + + } + + /** + * 告警日志 + * + * @param deviceId + * @param timeFrom + * @param timeTill + * @param content + * @return + */ + private List getAlarmLog(String deviceId, Long timeFrom, Long timeTill, String content) { + List deviceLogDtoList = new ArrayList<>(); + AlarmParam alarmParam = new AlarmParam(); + if (ToolUtil.isNotEmpty(deviceId)) { + alarmParam.setDeviceId(deviceId); + } + alarmParam.setTimeFrom(timeFrom); + alarmParam.setTimeTill(timeTill); + List alarmList = alarmService.getAlarmList(alarmParam); + if (ToolUtil.isNotEmpty(alarmList)) { + alarmList.forEach(alarm -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_ALARM).content(alarm.getName()) + .triggerTime(LocalDateTimeUtils.formatTime(alarm.getClock())) + .status(null == alarm.getRClock() ? "未解决" : "已解决").severity(alarm.getSeverity()) + .deviceId(alarm.getDeviceId()).build()); + }); + } + return deviceLogDtoList; + } + + /** + * 事件日志 + * + * @param deviceLogParam + * @return + */ + private Pager getEventLog(DeviceLogParam deviceLogParam) { + List deviceLogDtoList = new ArrayList<>(); + + QEventTriggerRecord query = new QEventTriggerRecord(); + + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + query.tenantId.eq(tenantId); + } + if (ToolUtil.isNotEmpty(deviceLogParam.getDeviceId())) { + query.deviceId.eq(deviceLogParam.getDeviceId()); + } + if (ToolUtil.isNotEmpty(deviceLogParam.getContent())) { + query.eventName.eq(deviceLogParam.getContent()); + } + if (null != deviceLogParam.getTimeFrom()) { + query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(deviceLogParam.getTimeFrom())); + } + if (null != deviceLogParam.getTimeTill()) { + query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(deviceLogParam.getTimeTill())); + } + query.orderBy().createTime.desc(); + + PagedList pagedList = query.setFirstRow((deviceLogParam.getPage() - 1) * deviceLogParam.getMaxRow()) + .setMaxRows(deviceLogParam.getMaxRow()).findPagedList(); + + if (ToolUtil.isNotEmpty(pagedList.getList())) { + pagedList.getList().forEach(service -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_EVENT).content(service.getEventName()) + .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())).deviceId(service.getDeviceId()) + .key(service.getKey()) + .param(service.getEventValue()).build()); + }); + } + return new Pager<>(deviceLogDtoList, pagedList.getTotalCount()); + } + + /** + * 服务日志 + * + * @param deviceLogParam + * @return + */ + private Pager getServiceLog(DeviceLogParam deviceLogParam) { + List deviceLogDtoList = new ArrayList<>(); + + QServiceExecuteRecord query = new QServiceExecuteRecord(); + + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + query.tenantId.eq(tenantId); + } + if (ToolUtil.isNotEmpty(deviceLogParam.getDeviceId())) { + query.deviceId.eq(deviceLogParam.getDeviceId()); + } + if (ToolUtil.isNotEmpty(deviceLogParam.getContent())) { + query.serviceName.eq(deviceLogParam.getContent()); + } + if (ToolUtil.isNotEmpty(deviceLogParam.getTriggerType())) { + query.executeType.eq(deviceLogParam.getTriggerType()); + } + if (ToolUtil.isNotEmpty(deviceLogParam.getTriggerUser())) { + query.executeUser.eq(deviceLogParam.getTriggerUser()); + } + if (ToolUtil.isNotEmpty(deviceLogParam.getEventRuleId())) { + query.executeRuleId.eq(deviceLogParam.getEventRuleId()); + } + if (null != deviceLogParam.getTimeFrom()) { + query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(deviceLogParam.getTimeFrom())); + } + if (null != deviceLogParam.getTimeTill()) { + query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(deviceLogParam.getTimeTill())); + } + query.orderBy().createTime.desc(); + + PagedList pagedList = query.setFirstRow((deviceLogParam.getPage() - 1) * deviceLogParam.getMaxRow()) + .setMaxRows(deviceLogParam.getMaxRow()).findPagedList(); + + if (ToolUtil.isNotEmpty(pagedList.getList())) { + pagedList.getList().forEach(service -> { + + String triggerBody = null != service.getExecuteUser() ? + DefinitionsUtil.getSysUserName(service.getExecuteUser()) : DefinitionsUtil.getTriggerName(service.getExecuteRuleId()); + + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_SERVICE).content(service.getServiceName()).eventRuleId(service.getExecuteRuleId()) + .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())).deviceId(service.getDeviceId()).userId(service.getExecuteUser()) + .param(service.getParam()).triggerType(service.getExecuteType()).triggerBody(triggerBody).build()); + }); + } + return new Pager<>(deviceLogDtoList, pagedList.getTotalCount()); + } + + /** + * 场景日志 + * + * @param deviceLogParam + * @return + */ + private Pager getScenesLog(DeviceLogParam deviceLogParam) { + List deviceLogDtoList = new ArrayList<>(); + + QScenesTriggerRecord query = new QScenesTriggerRecord(); + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + query.tenantId.eq(tenantId); + } + if (null != deviceLogParam.getEventRuleId()) { + query.ruleId.eq(deviceLogParam.getEventRuleId()); + } + if (ToolUtil.isNotEmpty(deviceLogParam.getTriggerType())) { + query.triggerType.eq(deviceLogParam.getTriggerType()); + } + if (null != deviceLogParam.getTriggerUser()) { + query.triggerUser.eq(deviceLogParam.getTriggerUser()); + } + if (null != deviceLogParam.getTimeFrom()) { + query.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(deviceLogParam.getTimeFrom())); + } + if (null != deviceLogParam.getTimeTill()) { + query.createTime.lt(LocalDateTimeUtils.getLDTByMilliSeconds(deviceLogParam.getTimeTill())); + } + + if (ToolUtil.isNotEmpty(deviceLogParam.getTriggerDeviceId())) { + List triggerRuleIds = new QProductEventRelation().select(QProductEventRelation.alias().eventRuleId).relationId.eq(deviceLogParam.getTriggerDeviceId()).findSingleAttributeList(); + if (ToolUtil.isEmpty(triggerRuleIds)) { + return new Pager<>(Collections.emptyList(), 0); + } + query.ruleId.in(triggerRuleIds); + } + + if (ToolUtil.isNotEmpty(deviceLogParam.getDeviceId())) { + List executeRuleIds = new QProductEventService().select(QProductEventService.alias().eventRuleId).executeDeviceId.eq(deviceLogParam.getDeviceId()).findSingleAttributeList(); + if (ToolUtil.isEmpty(executeRuleIds)) { + return new Pager<>(Collections.emptyList(), 0); + } + query.ruleId.in(executeRuleIds); + } + + query.orderBy().createTime.desc(); + PagedList pagedList = query.setFirstRow((deviceLogParam.getPage() - 1) * deviceLogParam.getMaxRow()) + .setMaxRows(deviceLogParam.getMaxRow()).findPagedList(); + + if (ToolUtil.isEmpty(pagedList.getList())) { + return new Pager<>(deviceLogDtoList, pagedList.getTotalCount()); + } + //关联触发设备 + List eventRuleIds = pagedList.getList().parallelStream().map(ScenesTriggerRecord::getRuleId).collect(Collectors.toList()); + String sql = "select distinct d.device_id,d.name,p.event_rule_id from product_event_relation p LEFT JOIN device d on d.device_id = p.relation_id where p.event_rule_id in (:eventRuleIds)"; + + List triggerDeviceDtos = DB.findDto(DeviceRelationDto.class, sql).setParameter("eventRuleIds", eventRuleIds).findList(); + Map> triggerDeviceMap = triggerDeviceDtos.parallelStream() + .collect(Collectors.groupingBy(DeviceRelationDto::getEventRuleId)); + + //关联 执行设备 + sql = "select distinct d.device_id,d.name,p.event_rule_id from product_event_service p LEFT JOIN device d on d.device_id = p.execute_device_id where p.event_rule_id in (:eventRuleIds)"; + List executeDeviceDtos = DB.findDto(DeviceRelationDto.class, sql).setParameter("eventRuleIds", eventRuleIds).findList(); + Map> executeDeviceMap = executeDeviceDtos.parallelStream() + .collect(Collectors.groupingBy(DeviceRelationDto::getEventRuleId)); + + pagedList.getList().forEach(service -> { + deviceLogDtoList.add(DeviceLogDto.builder().logType(LOG_TYPE_SCENES).content(service.getRuleName()).eventRuleId(service.getRuleId()) + .triggerTime(LocalDateTimeUtils.formatTime(service.getCreateTime())).triggerType(service.getTriggerType()) + .triggerBody(Optional.ofNullable(service.getTriggerUser()).map(DefinitionsUtil::getSysUserName).orElse("-")) + .triggerDevice(triggerDeviceMap.get(service.getRuleId())).executeDevice(executeDeviceMap.get(service.getRuleId())) + .build()); + }); + return new Pager<>(deviceLogDtoList, pagedList.getTotalCount()); + } + + /** + * 记录场景日志 + */ + public void recordSceneLog(Long eventRuleId, String type, Long userId) { + + publisher.publishEvent(new DeviceServiceLogEvent(this, LogEventData.builder().eventRuleId(eventRuleId).triggerType("自动".equals(type) ? "场景联动" : type).triggerUser(userId).build())); + + publisher.publishEvent(new DeviceSceneLogEvent(this, LogEventData.builder().eventRuleId(eventRuleId).triggerType(type).triggerUser(userId).build())); + + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java index f33d59b0..b55f43cd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceModelService.java @@ -4,19 +4,24 @@ import com.alibaba.fastjson.JSONObject; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.query.QDevice; -import com.zmops.iot.domain.product.Product; import com.zmops.iot.domain.product.ProductAttribute; -import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.domain.product.query.QProductEventExpression; +import com.zmops.iot.enums.CommonTimeUnit; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.iot.web.analyse.service.LatestService; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductAttrDto; import com.zmops.iot.web.product.dto.ProductTag; import com.zmops.iot.web.product.dto.param.ProductAttrParam; +import com.zmops.zeus.driver.entity.Interface; +import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.entity.ZbxProcessingStep; +import com.zmops.zeus.driver.service.ZbxInterface; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; import org.springframework.beans.factory.annotation.Autowired; @@ -36,6 +41,14 @@ public class DeviceModelService { @Autowired private ZbxItem zbxItem; + @Autowired + LatestService latestService; + + @Autowired + ZbxInterface zbxInterface; + + private static final String ATTR_SOURCE_AGENT = "0"; + /** * 设备属性分页列表 * @@ -45,9 +58,8 @@ public class DeviceModelService { public Pager prodModelAttributeList(ProductAttrParam productAttr) { QProductAttribute qProductAttribute = new QProductAttribute(); - if (null != productAttr.getProdId()) { - qProductAttribute.productId.eq(productAttr.getProdId()); - } + qProductAttribute.productId.eq(productAttr.getProdId()); + if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { qProductAttribute.name.contains(productAttr.getAttrName()); } @@ -57,6 +69,39 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr List pagedList = qProductAttribute.setFirstRow((productAttr.getPage() - 1) * productAttr.getMaxRow()) .setMaxRows(productAttr.getMaxRow()).orderBy(" create_time desc").asDto(ProductAttrDto.class).findList(); + + if (ToolUtil.isEmpty(pagedList)) { + return new Pager<>(); + } + //查询最新数据 + List attrIds = pagedList.parallelStream().map(ProductAttrDto::getAttrId).collect(Collectors.toList()); + List latestDtos = latestService.qeuryLatest(productAttr.getProdId(), attrIds); + Map map = latestDtos.parallelStream().distinct().collect(Collectors.toMap(LatestDto::getAttrId, o -> o, (a, b) -> b)); + + //查询zbx item 信息 + List zbxIds = pagedList.parallelStream().map(ProductAttrDto::getZbxId).collect(Collectors.toList()); + + String itemInfo = zbxItem.getItemInfo(zbxIds.toString(), null); + List itemInfos = JSONObject.parseArray(itemInfo, ZbxItemInfo.class); + Map errorMap = itemInfos.parallelStream().collect(Collectors.toMap(ZbxItemInfo::getItemid, o -> Optional.ofNullable(o.getError()).orElse(""))); + + pagedList.forEach(productAttrDto -> { + if (null != map.get(productAttrDto.getAttrId())) { + productAttrDto.setClock(map.get(productAttrDto.getAttrId()).getClock()); + productAttrDto.setValue(map.get(productAttrDto.getAttrId()).getValue()); + + String delayName = ""; + if (null != productAttrDto.getDelay()) { + delayName = productAttrDto.getDelay() + CommonTimeUnit.getDescription(productAttrDto.getUnit()); + } + productAttrDto.setOriginalValue(map.get(productAttrDto.getAttrId()).getOriginalValue()); + productAttrDto.setDelayName(delayName); + } + if (null != errorMap.get(productAttrDto.getZbxId())) { + productAttrDto.setError(errorMap.get(productAttrDto.getZbxId())); + } + }); + int count = qProductAttribute.findCount(); return new Pager<>(pagedList, count); } @@ -67,7 +112,7 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr * @param productAttr * @return */ - public List list(ProductAttrParam productAttr) { + public List list(ProductAttrParam productAttr) { QProductAttribute qProductAttribute = new QProductAttribute(); if (null != productAttr.getProdId()) { qProductAttribute.productId.eq(productAttr.getProdId()); @@ -78,7 +123,32 @@ public List list(ProductAttrParam productAttr) { if (ToolUtil.isNotEmpty(productAttr.getKey())) { qProductAttribute.key.contains(productAttr.getKey()); } - return qProductAttribute.findList(); + List list = qProductAttribute.findList(); + return ToolUtil.convertBean(list, ProductAttrDto.class); +// StringBuilder sql = new StringBuilder("select * from product_attribute where 1=1"); +// if (null != productAttr.getProdId()) { +// sql.append(" and product_id = :productId"); +// } +// if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { +// sql.append(" and name like :attrName"); +// } +// if (ToolUtil.isNotEmpty(productAttr.getKey())) { +// sql.append(" and key like :key"); +// } +// sql.append(" order by create_time desc"); +// DtoQuery dto = DB.findDto(ProductAttrDto.class, sql.toString()); +// +// if (null != productAttr.getProdId()) { +// dto.setParameter("productId", productAttr.getProdId()); +// } +// if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { +// dto.setParameter("attrName", "%" + productAttr.getAttrName() + "%"); +// } +// if (ToolUtil.isNotEmpty(productAttr.getKey())) { +// dto.setParameter("key", "%" + productAttr.getKey() + "%"); +// } +// +// return dto.findList(); } /** @@ -90,16 +160,19 @@ public List list(ProductAttrParam productAttr) { public ProductAttrDto detail(Long attrId) { ProductAttrDto attr = new QProductAttribute().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); - if (null == attr.getZbxId()) { + if (attr == null || ToolUtil.isEmpty(attr.getZbxId())) { return attr; } JSONArray itemInfo = JSONObject.parseArray(zbxItem.getItemInfo(attr.getZbxId(), null)); + if (itemInfo.size() == 0) { + return attr; + } attr.setTags(JSONObject.parseArray(itemInfo.getJSONObject(0).getString("tags"), ProductTag.Tag.class)); attr.setProcessStepList(formatProcessStep(itemInfo.getJSONObject(0).getString("preprocessing"))); - String valuemap = itemInfo.getJSONObject(0).getString("valuemap"); - if (ToolUtil.isNotEmpty(valuemap) && !"[]".equals(valuemap)) { - attr.setValuemapid(JSONObject.parseObject(valuemap).getString("valuemapid")); - } +// String valuemap = itemInfo.getJSONObject(0).getString("valuemap"); +// if (ToolUtil.isNotEmpty(valuemap) && !"[]".equals(valuemap)) { +// attr.setValuemapid(JSONObject.parseObject(valuemap).getString("valuemapid")); +// } return attr; } @@ -108,7 +181,7 @@ private List formatProcessStep(String preprocessing) return Collections.emptyList(); } List processingSteps = new ArrayList<>(); - JSONArray jsonArray = JSONObject.parseArray(preprocessing); + JSONArray jsonArray = JSONObject.parseArray(preprocessing); for (Object object : jsonArray) { ProductAttr.ProcessingStep processingStep = new ProductAttr.ProcessingStep(); processingStep.setType(((JSONObject) object).getString("type")); @@ -132,15 +205,21 @@ public void createProductAttr(ProductAttr productAttr, String zbxId) { } private ProductAttribute buildProdAttribute(ProductAttribute prodAttribute, ProductAttr productAttr) { + if (null == prodAttribute.getTemplateId()) { + prodAttribute.setName(productAttr.getAttrName()); + prodAttribute.setKey(productAttr.getKey()); + prodAttribute.setSource(productAttr.getSource()); + prodAttribute.setUnits(productAttr.getUnits()); + prodAttribute.setDepAttrId(productAttr.getDepAttrId()); + prodAttribute.setValueType(productAttr.getValueType()); + prodAttribute.setDelay(productAttr.getDelay()); + prodAttribute.setUnit(productAttr.getUnit()); + prodAttribute.setValuemapid(productAttr.getValuemapid()); + } prodAttribute.setProductId(productAttr.getProductId()); - prodAttribute.setName(productAttr.getAttrName()); - prodAttribute.setKey(productAttr.getKey()); - prodAttribute.setSource(productAttr.getSource()); - prodAttribute.setUnits(productAttr.getUnits()); prodAttribute.setRemark(productAttr.getRemark()); - prodAttribute.setValueType(productAttr.getValueType()); prodAttribute.setAttrId(productAttr.getAttrId()); - prodAttribute.setDepAttrId(productAttr.getDepAttrId()); + return prodAttribute; } @@ -166,7 +245,7 @@ public String createTrapperItem(ProductAttr productAttr) { ZbxProcessingStep step = new ZbxProcessingStep(); step.setType(i.getType()); - step.setParams(i.getParams()); + step.setParams(i.getParams().replaceAll("\n","").replaceAll("\"", "\\\\\\\\\"")); processingSteps.add(step); }); @@ -176,9 +255,20 @@ public String createTrapperItem(ProductAttr productAttr) { tagMap = productAttr.getTags().stream() .collect(Collectors.toMap(ProductTag.Tag::getTag, ProductTag.Tag::getValue, (k1, k2) -> k2)); } - + String delay = ""; + if (null != productAttr.getDelay()) { + delay = productAttr.getDelay() + productAttr.getUnit(); + } + String interfaceid = null; + if (ATTR_SOURCE_AGENT.equals(productAttr.getSource())) { + String interfaceInfo = zbxInterface.hostinterfaceGet(device.getZbxId()); + List interfaces = JSONObject.parseArray(interfaceInfo, Interface.class); + if (ToolUtil.isNotEmpty(interfaces)) { + interfaceid = interfaces.get(0).getInterfaceid(); + } + } return zbxItem.createTrapperItem(itemName, productAttr.getKey(), - hostId, productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(), delay, productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap, interfaceid); } /** @@ -194,15 +284,15 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { if (null == device) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); } - String hostId = device.getZbxId(); + String hostId = device.getZbxId(); + List processingSteps = new ArrayList<>(); + if (ToolUtil.isNotEmpty(productAttr.getProcessStepList())) { productAttr.getProcessStepList().forEach(i -> { ZbxProcessingStep step = new ZbxProcessingStep(); - step.setType(i.getType()); - step.setParams(i.getParams()); - + step.setParams(i.getParams().replaceAll("\n","").replaceAll("\"", "\\\\\\\\\"")); processingSteps.add(step); }); } @@ -212,10 +302,20 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { tagMap = productAttr.getTags().stream() .collect(Collectors.toMap(ProductTag.Tag::getTag, ProductTag.Tag::getValue, (k1, k2) -> k2)); } - - + String delay = ""; + if (null != productAttr.getDelay()) { + delay = productAttr.getDelay() + productAttr.getUnit(); + } + String interfaceid = null; + if (ATTR_SOURCE_AGENT.equals(productAttr.getSource())) { + String interfaceInfo = zbxInterface.hostinterfaceGet(device.getZbxId()); + List interfaces = JSONObject.parseArray(interfaceInfo, Interface.class); + if (ToolUtil.isNotEmpty(interfaces)) { + interfaceid = interfaces.get(0).getInterfaceid(); + } + } zbxItem.updateTrapperItem(productAttribute.getZbxId(), productAttr.getAttrId() + "", productAttr.getKey(), - hostId, productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(), delay, productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap, interfaceid); DB.update(productAttribute); @@ -230,9 +330,26 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { */ public void deleteTrapperItem(ProductAttr productAttr) { - List zbxIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); + //检查是否有属性依赖 + int count = new QProductAttribute().depAttrId.in(productAttr.getAttrIds()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED); + } + + //检查属性是否被告警规则引入 + count = new QProductEventExpression().productAttrId.in(productAttr.getAttrIds()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_EVENT_HASDEPTED); + } + + List zbxIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(productAttr.getAttrIds()).zbxId.isNotNull().findSingleAttributeList(); //删除zbx item - zbxItem.deleteTrapperItem(zbxIds); + if (ToolUtil.isNotEmpty(zbxIds)) { + List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(zbxIds.toString(), null), ZbxItemInfo.class); + if (ToolUtil.isNotEmpty(itemInfos)) { + zbxItem.deleteTrapperItem(itemInfos.parallelStream().map(ZbxItemInfo::getItemid).collect(Collectors.toList())); + } + } //删除 属性 new QProductAttribute().attrId.in(productAttr.getAttrIds()).delete(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java index 39b96be6..0a4f1dd1 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceService.java @@ -2,8 +2,6 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.Tag; import com.zmops.iot.domain.device.query.QDevice; @@ -11,57 +9,98 @@ import com.zmops.iot.domain.device.query.QTag; import com.zmops.iot.domain.product.Product; import com.zmops.iot.domain.product.query.QProduct; -import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.enums.CommonStatus; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.device.dto.DeviceDto; import com.zmops.iot.web.device.dto.param.DeviceParam; -import com.zmops.iot.web.device.service.work.*; +import com.zmops.iot.web.device.dto.param.DeviceParams; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductTag; +import com.zmops.zeus.driver.entity.Interface; import com.zmops.zeus.driver.service.ZbxHost; +import com.zmops.zeus.driver.service.ZbxInterface; import com.zmops.zeus.driver.service.ZbxValueMap; import io.ebean.DB; import io.ebean.DtoQuery; import io.ebean.Query; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Service; import java.util.*; +import java.util.stream.Collectors; /** * @author yefei **/ @Service -public class DeviceService { +public class DeviceService implements CommandLineRunner { @Autowired - private SaveDeviceWorker saveDeviceWorker; + private ZbxHost zbxHost; @Autowired - private SaveAttributeWorker saveAttributeWorker; + private ZbxValueMap zbxValueMap; @Autowired - private SaveDeviceGrpWorker saveDeviceGrpWorker; + DeviceGroupService deviceGroupService; @Autowired - private SaveTagWorker saveTagWorker; + ZbxInterface zbxInterface; @Autowired - private SaveZbxHostWorker saveZbxHostWorker; + DeviceEventPublisher deviceEventPublisher; - @Autowired - private UpdateAttrZbxIdWorker updateAttrZbxIdWorker; + /** + * 设备列表 + * + * @param deviceParams + * @return + */ + public List deviceList(DeviceParams deviceParams) { + List deviceIds = getDeviceIds(); + if (ToolUtil.isEmpty(deviceIds)) { + return Collections.emptyList(); + } + QDevice qDevice = new QDevice(); - @Autowired - private UpdateDeviceZbxIdWorker updateDeviceZbxIdWorker; + qDevice.deviceId.in(deviceIds); - @Autowired - private ZbxHost zbxHost; + if (ToolUtil.isNotEmpty(deviceParams.getName())) { + qDevice.name.contains(deviceParams.getName()); + } + if (ToolUtil.isNotEmpty(deviceParams.getDeviceId())) { + qDevice.deviceId.eq(deviceParams.getDeviceId()); + } + if (ToolUtil.isNotEmpty(deviceParams.getProductIds())) { + qDevice.productId.in(deviceParams.getProductIds()); + } + if (ToolUtil.isEmpty(deviceParams.getProductIds()) && ToolUtil.isNotEmpty(deviceParams.getProdTypes())) { + List productIdList = new QProduct().select(QProduct.Alias.productId).groupId.in( + deviceParams.getProdTypes()).findSingleAttributeList(); + qDevice.productId.in(productIdList); + } + if (ToolUtil.isNotEmpty(deviceParams.getDeviceGroupIds())) { + List deviceList = new QDevicesGroups().select(QDevicesGroups.Alias.deviceId).deviceGroupId.in( + deviceParams.getDeviceGroupIds()).findSingleAttributeList(); + qDevice.deviceId.in(deviceList); + } + return qDevice.findList(); + } - @Autowired - private ZbxValueMap zbxValueMap; + /** + * 获取当前用户 绑定的设备ID + * + * @return + */ + public List getDeviceIds() { + List devGroupIds = deviceGroupService.getDevGroupIds(); + return new QDevicesGroups().select(QDevicesGroups.alias().deviceId).deviceGroupId.in(devGroupIds) + .findSingleAttributeList(); + } /** * 设备分页列表 @@ -70,13 +109,16 @@ public class DeviceService { * @return */ public Pager devicePageList(DeviceParam deviceParam) { + //根据当前用户所属用户组 取出绑定的主机组 + List devGroupIds = deviceGroupService.getDevGroupIds(); + if (ToolUtil.isEmpty(devGroupIds)) { + return new Pager<>(); + } + //组装查询SQL StringBuilder sql = generateBaseSql(); + sql.append(" where 1=1"); - if (null != deviceParam.getDeviceGroupId()) { - sql.append(" where ds.groupIds like :deviceGroupId"); - } else { - sql.append(" where 1=1 "); - } + //根据标签过滤 List sids = new ArrayList<>(); if (ToolUtil.isNotEmpty(deviceParam.getTag())) { QTag qTag = new QTag().select(QTag.Alias.sid).templateId.isNull(); @@ -89,6 +131,7 @@ public Pager devicePageList(DeviceParam deviceParam) { sql.append(" and d.device_id in ( :deviceIds )"); } } + if (ToolUtil.isNotEmpty(deviceParam.getProdType())) { sql.append(" and d.type = :prodType "); } @@ -98,6 +141,7 @@ public Pager devicePageList(DeviceParam deviceParam) { if (ToolUtil.isNotEmpty(deviceParam.getName())) { sql.append(" and d.name like :name "); } + //用于查询总记录数 Query count = DB.findNative(Device.class, sql.toString()); sql.append(" order by d.create_time desc "); @@ -123,6 +167,17 @@ public Pager devicePageList(DeviceParam deviceParam) { dto.setParameter("name", "%" + deviceParam.getName() + "%"); count.setParameter("name", "%" + deviceParam.getName() + "%"); } + if (null != deviceParam.getDeviceGroupId()) { + if (devGroupIds.contains(deviceParam.getDeviceGroupId())) { + dto.setParameter("deviceGroupIds", deviceParam.getDeviceGroupId()); + count.setParameter("deviceGroupIds", deviceParam.getDeviceGroupId()); + } else { + return new Pager<>(); + } + } else { + dto.setParameter("deviceGroupIds", devGroupIds); + count.setParameter("deviceGroupIds", devGroupIds); + } List list = dto.setFirstRow((deviceParam.getPage() - 1) * deviceParam.getMaxRow()) .setMaxRows(deviceParam.getMaxRow()).findList(); @@ -131,6 +186,7 @@ public Pager devicePageList(DeviceParam deviceParam) { } private StringBuilder generateBaseSql() { + return new StringBuilder("SELECT " + " d.device_id," + " d.NAME, " + @@ -142,13 +198,22 @@ private StringBuilder generateBaseSql() { " d.update_time, " + " d.update_user, " + " d.TYPE, " + + " d.addr, " + + " d.position, " + + " d.online," + + " d.zbx_id," + + " d.latest_online," + + " d.tenant_id," + + " d.proxy_id," + " P.NAME product_name, " + + " P.product_code product_code, " + " ds.group_name, " + - " ds.groupIds " + + " ds.groupIds," + + " m.method " + "FROM " + " device d ") .append(" LEFT JOIN product P ON P.product_id = d.product_id ") - .append(" LEFT JOIN ( " + + .append(" INNER JOIN ( " + " SELECT " + " d.device_id, " + " array_to_string( ARRAY_AGG ( dg.NAME ), ',' ) group_name, " + @@ -157,8 +222,10 @@ private StringBuilder generateBaseSql() { " device d " + " LEFT JOIN devices_groups dgs ON dgs.device_id = d.device_id " + " LEFT JOIN device_group dg ON dg.device_group_id = dgs.device_group_id " + + " where dg.device_group_id in (:deviceGroupIds) " + " GROUP BY d.device_id " + - " ) ds ON ds.device_id = d.device_id "); + " ) ds ON ds.device_id = d.device_id ") + .append(" left join device_service_method m on m.device_id = d.device_id "); } /** @@ -167,44 +234,18 @@ private StringBuilder generateBaseSql() { * @param deviceDto * @return */ - public Object create(DeviceDto deviceDto) { + public String create(DeviceDto deviceDto) { - WorkerWrapper saveTagWork = WorkerWrapper.builder().id("saveTagWork") - .worker(saveTagWorker).param(deviceDto).build(); + Device device = new Device(); + ToolUtil.copyProperties(deviceDto, device); - WorkerWrapper saveAttributeWork = WorkerWrapper.builder().id("saveAttributeWork") - .worker(saveAttributeWorker).param(deviceDto).build(); + device.setStatus(CommonStatus.ENABLE.getCode()); + DB.insert(device); - WorkerWrapper saveDeviceGrpWork = WorkerWrapper.builder().id("saveDeviceGrpWork") - .worker(saveDeviceGrpWorker).param(deviceDto) - .build(); + deviceEventPublisher.DeviceSaveEventPublish(deviceDto); - WorkerWrapper updateAttrZbxIdWork = WorkerWrapper.builder().id("updateAttrZbxIdWork") - .worker(updateAttrZbxIdWorker) - .build(); - - WorkerWrapper updateDeviceZbxIdWork = WorkerWrapper.builder().id("updateDeviceZbxIdWork") - .worker(updateDeviceZbxIdWorker) - .build(); - - WorkerWrapper saveZbxHostWork = WorkerWrapper.builder().id("saveZbxHostWork") - .worker(saveZbxHostWorker).param(deviceDto) - .nextOf(updateAttrZbxIdWork, updateDeviceZbxIdWork) - .build(); - - WorkerWrapper deviceWork = WorkerWrapper.builder().id("saveDvice") - .worker(saveDeviceWorker).param(deviceDto) - .nextOf(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveZbxHostWork) - .build(); - - try { - - Async.work(3000, deviceWork).awaitFinish(); - } catch (Exception e) { - e.printStackTrace(); - } - - return deviceWork.getWorkResult().getResult(); + updateDeviceNameCache(deviceDto.getDeviceId(), deviceDto.getName()); + return deviceDto.getDeviceId(); } /** @@ -213,46 +254,21 @@ public Object create(DeviceDto deviceDto) { * @param deviceDto * @return */ - public Device update(DeviceDto deviceDto) { + public String update(DeviceDto deviceDto) { Device device = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findOne(); if (null == device) { throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); } + ToolUtil.copyProperties(deviceDto, device); deviceDto.setOldProductId(device.getProductId()); deviceDto.setZbxId(device.getZbxId()); - WorkerWrapper saveTagWork = WorkerWrapper.builder().id("saveTagWork") - .worker(saveTagWorker).param(deviceDto).build(); - - WorkerWrapper saveAttributeWork = WorkerWrapper.builder().id("saveAttributeWork") - .worker(saveAttributeWorker).param(deviceDto).build(); - - WorkerWrapper saveDeviceGrpWork = WorkerWrapper.builder().id("saveDeviceGrpWork") - .worker(saveDeviceGrpWorker).param(deviceDto) - .build(); - - WorkerWrapper updateAttrZbxIdWork = WorkerWrapper.builder().id("updateAttrZbxIdWork") - .worker(updateAttrZbxIdWorker) - .build(); + DB.update(device); - WorkerWrapper saveZbxHostWork = WorkerWrapper.builder().id("saveZbxHostWork") - .worker(saveZbxHostWorker).param(deviceDto) - .nextOf(updateAttrZbxIdWork) - .build(); + deviceEventPublisher.DeviceSaveEventPublish(deviceDto); - WorkerWrapper deviceWork = WorkerWrapper.builder().id("saveDvice") - .worker(saveDeviceWorker).param(deviceDto) - .nextOf(saveTagWork, saveAttributeWork, saveDeviceGrpWork, saveZbxHostWork) - .build(); - - try { - - Async.work(3000, deviceWork).awaitFinish(); - } catch (Exception e) { - e.printStackTrace(); - } - - return deviceWork.getWorkResult().getResult(); + updateDeviceNameCache(deviceDto.getDeviceId(), deviceDto.getName()); + return deviceDto.getDeviceId(); } /** @@ -268,50 +284,17 @@ public void checkProductExist(DeviceDto deviceDto) { deviceDto.setType(product.getType()); } - public Long delete(DeviceDto deviceDto) { + public String delete(DeviceDto deviceDto) { Device device = new QDevice().deviceId.eq(deviceDto.getDeviceId()).findOne(); if (null == device) { return deviceDto.getDeviceId(); } String zbxId = device.getZbxId(); - WorkerWrapper delTagWork = WorkerWrapper.builder().id("delTagWork") - .worker((deviceId, allWrappers) -> { - new QTag().sid.eq(deviceId).delete(); - return true; - }).param(deviceDto.getDeviceId()).build(); - - WorkerWrapper delAttrWork = WorkerWrapper.builder().id("delAttrWork") - .worker((deviceId, allWrappers) -> { - new QProductAttribute().productId.eq(deviceId).delete(); - return true; - }).param(deviceDto.getDeviceId()).build(); - - WorkerWrapper delGropusWork = WorkerWrapper.builder().id("delGropusWork") - .worker((deviceId, allWrappers) -> { - new QDevicesGroups().deviceId.eq(deviceId).delete(); - return true; - }).param(deviceDto.getDeviceId()).build(); - - WorkerWrapper delZbxWork = WorkerWrapper.builder().id("delZbxWork") - .worker((zbxid, allWrappers) -> { - zbxHost.hostDelete(Collections.singletonList(zbxid)); - return true; - }).param(zbxId).build(); - - WorkerWrapper delDeviceWork = WorkerWrapper.builder().id("delDeviceWork") - .worker((deviceId, allWrappers) -> { - new QDevice().deviceId.eq(deviceId).delete(); - return true; - }).param(deviceDto.getDeviceId()) - .nextOf(delTagWork, delAttrWork, delGropusWork, delZbxWork).build(); - - try { - - Async.work(3000, delDeviceWork).awaitFinish(); - } catch (Exception e) { - e.printStackTrace(); - } + deviceEventPublisher.DeviceDeleteEventPublish(device.getDeviceId(), zbxId); + + //更新设备名称缓存 + removeDeviceNameCache(deviceDto.getDeviceId()); return deviceDto.getDeviceId(); } @@ -326,21 +309,27 @@ public void deviceTagCreate(ProductTag productTag, String zbxId) { if (ToolUtil.isEmpty(productTag.getProductTag())) { return; } + + //先删除 之前的标签 new QTag().sid.eq(productTag.getProductId()).delete(); + List tags = new ArrayList<>(); + for (ProductTag.Tag tag : productTag.getProductTag()) { - tags.add( - Tag.builder().sid(productTag.getProductId()) - .tag(tag.getTag()).value(tag.getValue()) - .build()); + tags.add(Tag.builder().sid(productTag.getProductId()).tag(tag.getTag()).value(tag.getValue()).build()); } + DB.saveAll(tags); if (ToolUtil.isEmpty(zbxId)) { return; } - List list = new QTag().sid.eq(productTag.getProductId()).findList(); + + //同步到Zbx + List list = new QTag().sid.eq(productTag.getProductId()).findList(); + Map tagMap = new HashMap<>(list.size()); + for (Tag tag : list) { tagMap.put(tag.getTag(), tag.getValue()); } @@ -390,10 +379,30 @@ public String valueMapDelete(String valueMapId) { * @param deviceId * @return */ - public DeviceDto deviceDetail(Long deviceId) { + public DeviceDto deviceDetail(String deviceId) { + List devGroupIds = deviceGroupService.getDevGroupIds(); + if (ToolUtil.isEmpty(devGroupIds)) { + return new DeviceDto(); + } StringBuilder sql = generateBaseSql(); sql.append(" where d.device_id=:deviceId"); - DeviceDto deviceDto = DB.findDto(DeviceDto.class, sql.toString()).setParameter("deviceId", deviceId).findOne(); + DeviceDto deviceDto = DB.findDto(DeviceDto.class, sql.toString()).setParameter("deviceId", deviceId) + .setParameter("deviceGroupIds", devGroupIds).findOne(); + + if (deviceDto == null) { + throw new ServiceException(BizExceptionEnum.DEVICE_NOT_EXISTS); + } + + if (ToolUtil.isEmpty(deviceDto.getZbxId())) { + return deviceDto; + } + + String interfaceInfo = zbxInterface.hostinterfaceGet(deviceDto.getZbxId()); + List interfaces = JSONObject.parseArray(interfaceInfo, Interface.class); + if (ToolUtil.isNotEmpty(interfaces)) { + deviceDto.setDeviceInterface(interfaces.get(0)); + } + return deviceDto; } @@ -403,7 +412,7 @@ public DeviceDto deviceDetail(Long deviceId) { * @param deviceId * @return */ - public List deviceTagList(Long deviceId) { + public List deviceTagList(String deviceId) { QTag tag = QTag.alias(); return new QTag().select(tag.id, tag.sid, tag.tag, tag.value).sid.eq(deviceId).findList(); } @@ -414,7 +423,7 @@ public List deviceTagList(Long deviceId) { * @param deviceId * @return */ - public JSONArray valueMapList(Long deviceId) { + public JSONArray valueMapList(String deviceId) { JSONArray zbxTemplateInfo = getZbxHostInfo(deviceId); if (zbxTemplateInfo.size() == 0) { return new JSONArray(); @@ -423,11 +432,59 @@ public JSONArray valueMapList(Long deviceId) { return JSONObject.parseArray(zbxTemplateInfo.getJSONObject(0).getString("valuemaps")); } - private JSONArray getZbxHostInfo(Long deviceId) { + private JSONArray getZbxHostInfo(String deviceId) { String zbxId = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(deviceId).findSingleAttribute(); if (null == zbxId) { return new JSONArray(); } return JSONObject.parseArray(zbxHost.hostDetail(zbxId)); } + + /** + * 修改设备状态 + * + * @param status + * @param deviceId + * @return + */ + public void status(String status, String deviceId, String zbxId) { + if (ToolUtil.isNotEmpty(zbxId)) { + zbxHost.hostStatusUpdate(zbxId, "ENABLE".equals(status) ? "0" : "1"); + } + DB.update(Device.class).where().eq("device_id", deviceId).asUpdate().set("status", status).setNull("online") + .update(); + } + + /** + * 更新设备名称缓存 + */ + private void updateDeviceCache() { + List deviceList = new QDevice().select(QDevice.Alias.deviceId, QDevice.Alias.name).findList(); + Map map = deviceList.parallelStream() + .collect(Collectors.toMap(Device::getDeviceId, Device::getName, (a, b) -> a)); + DefinitionsUtil.updateDeviceCache(map); + } + + /** + * 更新设备名称缓存 + */ + private void updateDeviceNameCache(String deviceId, String name) { + Map all = DefinitionsUtil.getDeviceCache().getAll(); + all.put(deviceId, name); + DefinitionsUtil.updateDeviceCache(all); + } + + /** + * 更新设备名称缓存 + */ + private void removeDeviceNameCache(String deviceId) { + Map all = DefinitionsUtil.getDeviceCache().getAll(); + all.remove(deviceId); + DefinitionsUtil.updateDeviceCache(all); + } + + @Override + public void run(String... args) throws Exception { + updateDeviceCache(); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java new file mode 100644 index 00000000..37f09230 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/DeviceSvrService.java @@ -0,0 +1,102 @@ +package com.zmops.iot.web.device.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.dtflys.forest.Forest; +import com.zmops.iot.core.auth.context.LoginContextHolder; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.ServiceExecuteRecord; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductService; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.domain.product.query.QProductService; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.ServiceExecuteDto.ServiceParam; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import io.ebean.DB; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 设备服务 + **/ +@Service +public class DeviceSvrService { + + /** + * 执行指定设备的某个服务 + * + * @param deviceId 设备ID + * @param serviceId 服务ID + */ + public void execute(String deviceId, Long serviceId, List serviceParams) { + + //封装执行参数 + List> body = new ArrayList<>(); + + Map map = new ConcurrentHashMap<>(2); + + map.put("device", deviceId); + + List> serviceList = new ArrayList<>(); + Map serviceMap = new ConcurrentHashMap<>(2); + ProductService productService = new QProductService().id.eq(serviceId).findOne(); + if (null == productService) { + throw new ServiceException(BizExceptionEnum.SERVICE_NOT_EXISTS); + } + serviceMap.put("name", productService.getName()); + + List paramList = DefinitionsUtil.getServiceParam(serviceId); + Map paramStr = null; + if (ToolUtil.isNotEmpty(paramList)) { + paramStr = paramList.parallelStream().filter(o -> deviceId.equals(o.getDeviceId())).collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue, (a, b) -> a)); + + if (ToolUtil.isNotEmpty(serviceParams)) { + Map userParam = serviceParams.parallelStream().collect(Collectors.toMap(ServiceParam::getKey, ServiceParam::getValue, (a, b) -> a)); + for (Map.Entry param : paramStr.entrySet()) { + if (userParam.get(param.getKey()) != null) { + param.setValue(userParam.get(param.getKey())); + } + } + } + + serviceMap.put("param", paramStr); + } + + serviceList.add(serviceMap); + map.put("service", serviceList); + body.add(map); + + //下发命令 执行 + Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(body)).execute(); + + //记录服务日志 + ServiceExecuteRecord serviceExecuteRecord = new ServiceExecuteRecord(); + serviceExecuteRecord.setDeviceId(deviceId); + if (ToolUtil.isNotEmpty(paramStr)) { + serviceExecuteRecord.setParam(JSONObject.toJSONString(paramStr)); + } + serviceExecuteRecord.setServiceName(DefinitionsUtil.getServiceName(serviceId)); + + Device device = new QDevice().deviceId.eq(deviceId).findOne(); + if (null != device) { + serviceExecuteRecord.setTenantId(device.getTenantId()); + } + + serviceExecuteRecord.setCreateTime(LocalDateTime.now()); + serviceExecuteRecord.setExecuteType("手动"); + serviceExecuteRecord.setExecuteUser(LoginContextHolder.getContext().getUserId()); + + DB.insert(serviceExecuteRecord); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java new file mode 100644 index 00000000..5f674f23 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/MultipleDeviceEventRuleService.java @@ -0,0 +1,585 @@ +package com.zmops.iot.web.device.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.dtflys.forest.Forest; +import com.zmops.iot.core.auth.context.LoginContextHolder; +import com.zmops.iot.domain.device.query.QDevicesGroups; +import com.zmops.iot.domain.product.*; +import com.zmops.iot.domain.product.query.*; +import com.zmops.iot.domain.schedule.Task; +import com.zmops.iot.domain.schedule.query.QTask; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.enums.InheritStatus; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceEventRelationDto; +import com.zmops.iot.web.device.dto.MultipleDeviceEventDto; +import com.zmops.iot.web.device.dto.MultipleDeviceEventRule; +import com.zmops.iot.web.device.dto.MultipleDeviceServiceDto; +import com.zmops.iot.web.device.dto.param.MultipleDeviceEventParm; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.task.dto.TaskDto; +import com.zmops.iot.web.task.service.TaskService; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import io.ebean.annotation.Transactional; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + * + * 设备 场景 联动 服务 + **/ +@Service +public class MultipleDeviceEventRuleService { + + @Autowired + private ZbxTrigger zbxTrigger; + + private static final String EVENT_CLASSIFY = "1"; + + public static final int TRIGGER_TYPE_SCHEDULE = 1; + + public static final int TRIGGER_TYPE_CONDITION = 0; + + public static final String SCENE_TAG_NAME = "__scene__"; + + @Autowired + TaskService taskService; + + @Autowired + DeviceLogService deviceLogService; + + /** + * 场景列表 + * + * @param eventParam + * @return + */ + public List list(MultipleDeviceEventParm eventParam) { + QProductEvent query = new QProductEvent(); + + if (ToolUtil.isNotEmpty(eventParam.getEventRuleName())) { + query.eventRuleName.contains(eventParam.getEventRuleName()); + } + + if (LoginContextHolder.getContext().getUser().getTenantId() != null) { + query.tenantId.eq(LoginContextHolder.getContext().getUser().getTenantId()); + } + + query.classify.eq(EVENT_CLASSIFY); + + return query.orderBy(" create_time desc").asDto(MultipleDeviceEventDto.class).findList(); + } + + /** + * 设备联动 分页列表 + * + * @param eventParam 查询参数 + * @return MultipleDeviceEventDto + */ + public Pager getEventByPage(MultipleDeviceEventParm eventParam) { + QProductEvent query = new QProductEvent(); + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + query.tenantId.eq(tenantId); + } + if (ToolUtil.isNotEmpty(eventParam.getEventRuleName())) { + query.eventRuleName.contains(eventParam.getEventRuleName()); + } + if (ToolUtil.isNotEmpty(eventParam.getDeviceIds())) { + List eventIds = new QProductEventService().select(QProductEventService.alias().eventRuleId).executeDeviceId.isNotNull().executeDeviceId.in(eventParam.getDeviceIds()).findSingleAttributeList(); + query.eventRuleId.in(eventIds); + } else if (ToolUtil.isNotEmpty(eventParam.getDeviceGrpIds())) { + List deviceIds = new QDevicesGroups().select(QDevicesGroups.alias().deviceId).deviceId.isNotNull().deviceGroupId.in(eventParam.getDeviceGrpIds()).findSingleAttributeList(); + List eventIds = new QProductEventService().select(QProductEventService.alias().eventRuleId).executeDeviceId.isNotNull().executeDeviceId.in(deviceIds).findSingleAttributeList(); + query.eventRuleId.in(eventIds); + } + query.classify.eq(EVENT_CLASSIFY); + + List list = query.setFirstRow((eventParam.getPage() - 1) * eventParam.getMaxRow()) + .setMaxRows(eventParam.getMaxRow()).orderBy(" create_time desc").asDto(MultipleDeviceEventDto.class).findList(); + + if (ToolUtil.isEmpty(list)) { + return new Pager<>(list, 0); + } + + //关联状态 备注 触发设备 + List eventRuleIds = list.parallelStream().map(MultipleDeviceEventDto::getEventRuleId).collect(Collectors.toList()); + String sql = "SELECT " + + " pr.event_rule_id, " + + " array_to_string( ARRAY_AGG ( d.NAME ), ',' ) triggerDevice, " + + " pr.status," + + " pr.remark " + + "FROM " + + " product_event_relation pr " + + " LEFT JOIN device d ON pr.relation_id = d.device_id " + + "WHERE " + + " pr.event_rule_id IN (:eventRuleIds) " + + "GROUP BY " + + " pr.event_rule_id,pr.status,pr.remark"; + List deviceEventRelationDtos = DB.findDto(DeviceEventRelationDto.class, sql).setParameter("eventRuleIds", eventRuleIds).findList(); + Map productEventRelationMap = deviceEventRelationDtos.parallelStream() + .collect(Collectors.toConcurrentMap(DeviceEventRelationDto::getEventRuleId, o -> o)); + + //关联 执行设备 + sql = "SELECT " + + " ps.event_rule_id, " + + " array_to_string( ARRAY_AGG ( d.NAME ), ',' ) executeDevice " + + "FROM " + + " product_event_service ps " + + " LEFT JOIN device d ON ps.execute_device_id = d.device_id " + + "WHERE " + + " ps.event_rule_id IN (:eventRuleIds) " + + "GROUP BY " + + " ps.event_rule_id"; + + List deviceServiceDtos = DB.findDto(MultipleDeviceServiceDto.class, sql).setParameter("eventRuleIds", eventRuleIds).findList(); + + Map deviceServiceMap = deviceServiceDtos.parallelStream() + .collect(Collectors.toConcurrentMap(MultipleDeviceServiceDto::getEventRuleId, o -> o)); + + list.forEach(productEventDto -> { + DeviceEventRelationDto deviceEventRelationDto = productEventRelationMap.get(productEventDto.getEventRuleId()); + if (null != deviceEventRelationDto) { + String status = deviceEventRelationDto.getStatus(); + String remark = deviceEventRelationDto.getRemark(); + String triggerDevice = deviceEventRelationDto.getTriggerDevice(); + productEventDto.setStatus(status); + productEventDto.setRemark(remark); + productEventDto.setTriggerDevice(triggerDevice); + } + MultipleDeviceServiceDto deviceServiceDto = deviceServiceMap.get(productEventDto.getEventRuleId()); + if (null != deviceServiceDto) { + productEventDto.setExecuteDevice(deviceServiceDto.getExecuteDevice()); + } + }); + + return new Pager<>(list, query.findCount()); + } + + private String generateExecuteParam(MultipleDeviceEventRule eventRule) { + Map param = new HashMap<>(2); + param.put("eventRuleId", eventRule.getEventRuleId()); + + List> list = new ArrayList<>(); + Map> collect = eventRule.getDeviceServices().parallelStream().collect(Collectors.groupingBy(MultipleDeviceEventRule.DeviceService::getExecuteDeviceId)); + + collect.forEach((key, value) -> { + Map map = new ConcurrentHashMap<>(2); + map.put("device", key); + + List> serviceList = new ArrayList<>(); + value.forEach(val -> { + Map serviceMap = new ConcurrentHashMap<>(2); + serviceMap.put("name", DefinitionsUtil.getServiceName(val.getServiceId())); + + List paramList = DefinitionsUtil.getServiceParam(val.getServiceId()); + if (ToolUtil.isNotEmpty(paramList)) { + serviceMap.put("param", paramList.parallelStream().filter(o->key.equals(o.getDeviceId())).collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue, (a, b) -> a))); + } + serviceList.add(serviceMap); + }); + map.put("service", serviceList); + list.add(map); + }); + param.put("executeParam", list); + return JSON.toJSONString(param); + } + + /** + * 保存设备联动 + * + * @param eventRule 设备联动规则 + */ + @Transactional(rollbackFor = Exception.class) + public void createDeviceEventRule(MultipleDeviceEventRule eventRule) { + + //setp 0: 创建任务 + Integer taskId = null; + if (eventRule.getTriggerType() == TRIGGER_TYPE_SCHEDULE) { + TaskDto taskDto = new TaskDto(); + taskDto.setScheduleConf(eventRule.getScheduleConf()); + taskDto.setExecutorParam(generateExecuteParam(eventRule)); + taskDto.setRemark(eventRule.getRemark()); + taskId = taskService.createTask(taskDto); + } + + // step 1: 保存产品告警规则 + ProductEvent event = initEventRule(eventRule); + event.setEventRuleId(eventRule.getEventRuleId()); + event.setTaskId(taskId); + DB.save(event); + + //step 2: 保存 表达式,方便回显 + if (TRIGGER_TYPE_CONDITION == eventRule.getTriggerType()) { + List expList = new ArrayList<>(); + + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = initEventExpression(i); + exp.setEventRuleId(eventRule.getEventRuleId()); + expList.add(exp); + }); + + DB.saveAll(expList); + + //step 3: 保存关联关系 + List relationIds = eventRule.getExpList().parallelStream().map(MultipleDeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + if (ToolUtil.isEmpty(relationIds)) { + throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + } + List productEventRelationList = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRule.getEventRuleId()); + productEventRelation.setRelationId(relationId); + productEventRelation.setInherit(InheritStatus.NO.getCode()); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setRemark(eventRule.getRemark()); + productEventRelationList.add(productEventRelation); + }); + DB.saveAll(productEventRelationList); + + //step 4: 保存时间区间 + if (ToolUtil.isNotEmpty(eventRule.getTimeIntervals())) { + List timeExpList = new ArrayList<>(); + eventRule.getTimeIntervals().forEach(i -> { + ProductEventTimeInterval timeExp = new ProductEventTimeInterval(); + timeExp.setEventRuleId(eventRule.getEventRuleId()); + timeExp.setStartTime(i.getStartTime()); + timeExp.setEndTime(i.getEndTime()); + timeExp.setDayOfWeeks(i.getDayOfWeeks()); + timeExpList.add(timeExp); + }); + DB.insertAll(timeExpList); + } + } + + //step 5: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, execute_device_id, service_id) " + + "values (:eventRuleId, :executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + } + + } + + @Transactional(rollbackFor = Exception.class) + public void updateDeviceEventRule(MultipleDeviceEventRule eventRule) { + + //setp 0: 创建任务 + if (TRIGGER_TYPE_SCHEDULE == eventRule.getTriggerType()) { + TaskDto taskDto = new TaskDto(); + taskDto.setScheduleConf(eventRule.getScheduleConf()); + taskDto.setExecutorParam(generateExecuteParam(eventRule)); + taskDto.setRemark(eventRule.getRemark()); + if (ToolUtil.isEmpty(eventRule.getTaskId())) { + int taskId = taskService.createTask(taskDto); + eventRule.setTaskId(taskId); + } else { + taskDto.setId(eventRule.getTaskId()); + taskService.updateTask(taskDto); + } + } + + //setp 1: 删除zbx触发器 + if (ToolUtil.isNotEmpty(eventRule.getZbxId())) { + zbxTrigger.triggerDelete(eventRule.getZbxId()); + } + + //step 2: 删除函数表达式 + DB.sqlUpdate("delete from product_event_expression where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + + //step 3: 删除服务方法调用 + DB.sqlUpdate("delete from product_event_service where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + + //step : 删除时间区间函数表达式 + DB.sqlUpdate("delete from product_event_time_interval where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + + // 删除和所有设备的关联关系 + new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + // step 4: 保存产品告警规则 + ProductEvent event = initEventRule(eventRule); + event.setEventRuleId(eventRule.getEventRuleId()); + event.setTaskId(eventRule.getTaskId()); + event.update(); + + //step 5: 保存 表达式,方便回显 + if (TRIGGER_TYPE_CONDITION == eventRule.getTriggerType()) { + List expList = new ArrayList<>(); + + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = initEventExpression(i); + exp.setEventExpId(i.getEventExpId()); + exp.setEventRuleId(eventRule.getEventRuleId()); + expList.add(exp); + }); + + DB.saveAll(expList); + + // step 6: 保存关联关系 + List relationIds = eventRule.getExpList().parallelStream().map(MultipleDeviceEventRule.Expression::getDeviceId).distinct().collect(Collectors.toList()); + if (ToolUtil.isEmpty(relationIds)) { + throw new ServiceException(BizExceptionEnum.EVENT_HAS_NOT_DEVICE); + } + List productEventRelationList = new ArrayList<>(); + relationIds.forEach(relationId -> { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRule.getEventRuleId()); + productEventRelation.setRelationId(relationId); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setRemark(eventRule.getRemark()); + productEventRelationList.add(productEventRelation); + }); + DB.saveAll(productEventRelationList); + + //step 7: 保存时间区间 + if (ToolUtil.isNotEmpty(eventRule.getTimeIntervals())) { + List timeExpList = new ArrayList<>(); + eventRule.getTimeIntervals().forEach(i -> { + ProductEventTimeInterval timeExp = new ProductEventTimeInterval(); + timeExp.setEventRuleId(eventRule.getEventRuleId()); + timeExp.setStartTime(i.getStartTime()); + timeExp.setEndTime(i.getEndTime()); + timeExp.setDayOfWeeks(i.getDayOfWeeks()); + timeExpList.add(timeExp); + }); + DB.insertAll(timeExpList); + } + } + + //step 8: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id,execute_device_id, service_id) values (:eventRuleId, :executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + } + + } + + + private ProductEvent initEventRule(MultipleDeviceEventRule eventRule) { + ProductEvent event = new ProductEvent(); + event.setEventLevel(eventRule.getEventLevel().toString()); + event.setExpLogic(eventRule.getExpLogic()); + event.setEventNotify(eventRule.getEventNotify().toString()); + event.setClassify(eventRule.getClassify()); + event.setEventRuleName(eventRule.getEventRuleName()); + event.setTenantId(eventRule.getTenantId()); + event.setStatus(CommonStatus.ENABLE.getCode()); + event.setRemark(eventRule.getRemark()); + event.setTriggerType(eventRule.getTriggerType()); + return event; + } + + private ProductEventExpression initEventExpression(MultipleDeviceEventRule.Expression exp) { + ProductEventExpression eventExpression = new ProductEventExpression(); + eventExpression.setCondition(exp.getCondition()); + eventExpression.setFunction(exp.getFunction()); + eventExpression.setScope(exp.getScope()); + eventExpression.setValue(exp.getValue()); + eventExpression.setDeviceId(exp.getDeviceId()); + eventExpression.setProductAttrKey(exp.getProductAttrKey()); + eventExpression.setProductAttrId(exp.getProductAttrId()); + eventExpression.setProductAttrType(exp.getProductAttrType()); + eventExpression.setPeriod(exp.getPeriod()); + eventExpression.setUnit(exp.getUnit()); + eventExpression.setAttrValueType(exp.getAttrValueType()); + return eventExpression; + } + + /** + * 更新 设备联动规则 zbxId + * + * @param triggerId 设备联动ID + * @param zbxId triggerId + */ + public void updateProductEventRuleZbxId(Long triggerId, String[] zbxId) { + DB.update(ProductEventRelation.class).where().eq("eventRuleId", triggerId) + .asUpdate().set("zbxId", zbxId[0]).update(); + } + + /** + * 获取设备联动详情 + * + * @param productEvent + * @param eventRuleId + * @return + */ + public MultipleDeviceEventDto detail(ProductEvent productEvent, long eventRuleId) { + MultipleDeviceEventDto multipleDeviceEventDto = new MultipleDeviceEventDto(); + ToolUtil.copyProperties(productEvent, multipleDeviceEventDto); + + multipleDeviceEventDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).findList()); + + if (TRIGGER_TYPE_CONDITION == productEvent.getTriggerType()) { + List expList = new QProductEventExpression().eventRuleId.eq(eventRuleId).findList(); + multipleDeviceEventDto.setExpList(expList); + + List timeExpList = new QProductEventTimeInterval().eventRuleId.eq(eventRuleId).findList(); + multipleDeviceEventDto.setTimeExpList(timeExpList); + + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRuleId).setMaxRows(1).findOne(); + if (null == productEventRelation) { + return multipleDeviceEventDto; + } + multipleDeviceEventDto.setStatus(productEventRelation.getStatus()); + multipleDeviceEventDto.setRemark(productEventRelation.getRemark()); + multipleDeviceEventDto.setInherit(productEventRelation.getInherit()); + + JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), MultipleDeviceEventRule.Tag.class); + + multipleDeviceEventDto.setTags(tagList.stream() + .filter(s -> !s.getTag().equals(SCENE_TAG_NAME)) + .collect(Collectors.toList())); + } else { + Task task = new QTask().id.eq(productEvent.getTaskId()).findOne(); + multipleDeviceEventDto.setScheduleConf(Optional.ofNullable(task).map(Task::getScheduleConf).orElse("")); + multipleDeviceEventDto.setExpList(Collections.emptyList()); + multipleDeviceEventDto.setTimeExpList(Collections.emptyList()); + } + + return multipleDeviceEventDto; + } + + /** + * 创建 设备联动 + * + * @param triggerName 设备联动名称 + * @param expression 表达式 + * @return 触发器ID + */ + public String[] createZbxTrigger(String triggerName, String expression, Byte level) { + String res = zbxTrigger.executeTriggerCreate(triggerName, expression, level); + return JSON.parseObject(res, TriggerIds.class).getTriggerids(); + } + + /** + * 更新 设备联动 + * + * @param triggerId + * @param expression + * @param level + * @return + */ + public String[] updateZbxTrigger(String triggerId, String expression, Byte level) { + String res = zbxTrigger.triggerUpdate(triggerId, expression, level); + return JSON.parseObject(res, TriggerIds.class).getTriggerids(); + } + + /** + * 执行动作服务 + * + * @param eventRuleId 场景ID + * @param type 执行方式 + * @param userId 执行人 + */ + public void execute(Long eventRuleId, String type, Long userId) { + + //先异步 执行记录日志 + deviceLogService.recordSceneLog(eventRuleId, type, userId); + + //根据场景ID 找出需要执行的服务 + List productEventServiceList = new QProductEventService().eventRuleId.eq(eventRuleId) + .deviceId.isNull().findList(); + + Map> deviceServiceMap = productEventServiceList.parallelStream().collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); + + //封装执行的参数 + List> body = new ArrayList<>(); + deviceServiceMap.forEach((key, value) -> { + Map map = new ConcurrentHashMap<>(); + map.put("device", key); + + List> serviceList = new ArrayList<>(); + value.forEach(val -> { + Map serviceMap = new ConcurrentHashMap<>(); + serviceMap.put("name", DefinitionsUtil.getServiceName(val.getServiceId())); + + List paramList = DefinitionsUtil.getServiceParam(val.getServiceId()); + if (ToolUtil.isNotEmpty(paramList)) { + serviceMap.put("param", paramList.parallelStream().filter(o->key.equals(o.getDeviceId())).collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue, (a, b) -> a))); + } + serviceList.add(serviceMap); + }); + map.put("service", serviceList); + body.add(map); + }); + + //提交IOT SERVER执行命令下发 + Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(body)).execute(); + } + + /** + * 场景 参数 检查 + * + * @param eventRule + */ + public void checkParam(MultipleDeviceEventRule eventRule) { + if (eventRule.getTriggerType() == 0) { + if (ToolUtil.isEmpty(eventRule.getExpList())) { + throw new ServiceException(BizExceptionEnum.SCENE_EXPRESSION_NOT_EXISTS); + } + } else { + if (ToolUtil.isEmpty(eventRule.getScheduleConf())) { + throw new ServiceException(BizExceptionEnum.TASK_NOT_SCHEDULE_CONF); + } + + if (!ToolUtil.validCron(eventRule.getScheduleConf())) { + throw new ServiceException(BizExceptionEnum.TASK_SCHEDULE_CONF_NOT_MATCH); + } + } + +// long count = eventRule.getDeviceServices().parallelStream().map(MultipleDeviceEventRule.DeviceService::getServiceId).distinct().count(); + long count = eventRule.getDeviceServices().parallelStream().map(o-> (o.getExecuteDeviceId()+o.getServiceId()).hashCode()).distinct().count(); + if (count < eventRule.getDeviceServices().size()) { + throw new ServiceException(BizExceptionEnum.SERVICE_HAS_DUPLICATE); + } + + } + + @Data + static class TriggerIds { + private String[] triggerids; + } + + @Data + public static class Triggers { + private String triggerid; + private String description; + private List hosts; + } + + @Data + static class Hosts { + private String hostid; + private String host; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java new file mode 100644 index 00000000..5eb13c25 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/SceneScheduleProcessor.java @@ -0,0 +1,45 @@ +package com.zmops.iot.web.device.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.dtflys.forest.Forest; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.SceneEvent; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author yefei + *

+ * 定时 触发场景 处理 + **/ +@Slf4j +@Component +@EnableAsync +public class SceneScheduleProcessor { + + @Autowired + DeviceLogService deviceLogService; + + @EventListener(classes = {SceneEvent.class}) + @Async + public void subscribe(SceneEvent event) { + log.info("子线程接收异步事件 - {},String类型", event.getEventData().getExecuteParam()); + if (ToolUtil.isEmpty(event.getEventData().getExecuteParam())) { + return; + } + Map eventMap = JSONObject.parseObject(event.getEventData().getExecuteParam(), Map.class); + Long eventRuleId = Long.parseLong(eventMap.get("eventRuleId").toString()); + //记录日志 + deviceLogService.recordSceneLog(eventRuleId, "自动", null); + + //提交IOT SERVER 下发命令 + Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(eventMap.get("executeParam"))).execute(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/DeleteDeviceEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/DeleteDeviceEventHandler.java new file mode 100644 index 00000000..89c7d3b9 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/DeleteDeviceEventHandler.java @@ -0,0 +1,59 @@ +package com.zmops.iot.web.device.service.event; + + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.device.query.QDevicesGroups; +import com.zmops.iot.domain.device.query.QTag; +import com.zmops.iot.domain.product.query.*; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.DeviceDeleteEvent; +import com.zmops.zeus.driver.service.ZbxHost; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +import java.util.Collections; + +@Slf4j +@Component +@EnableAsync +public class DeleteDeviceEventHandler { + + @Autowired + private ZbxHost zbxHost; + + @Async + @EventListener(classes = {DeviceDeleteEvent.class}) + public void onApplicationEvent(DeviceDeleteEvent event) { + String deviceId = event.getEventData().getDeviceId(); + String zbxId = event.getEventData().getZbxId(); + + new QTag().sid.eq(deviceId).delete(); + + new QProductAttribute().productId.eq(deviceId).delete(); + + new QDevicesGroups().deviceId.eq(deviceId).delete(); + + if (ToolUtil.isNotEmpty(zbxId)) { + JSONArray jsonArray = JSONObject.parseArray(zbxHost.hostDetail(zbxId)); + if (jsonArray.size() > 0) { + zbxHost.hostDelete(Collections.singletonList(zbxId)); + } + } + + new QProductStatusFunctionRelation().relationId.eq(deviceId).delete(); + new QProductServiceRelation().relationId.eq(deviceId).delete(); + new QProductEventRelation().relationId.eq(deviceId).delete(); + new QProductEventService().deviceId.eq(deviceId).delete(); + new QProductServiceParam().deviceId.eq(deviceId).delete(); +// new QDeviceServiceMethod().deviceId.eq(deviceId).delete(); + + new QDevice().deviceId.eq(deviceId).delete(); + + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveActionMethodEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveActionMethodEventHandler.java new file mode 100644 index 00000000..84f5afd4 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveActionMethodEventHandler.java @@ -0,0 +1,40 @@ +package com.zmops.iot.web.device.service.event; + +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * @author yefei + *

+ * 处理设备服务下发 方法 + */ +@Slf4j +@Component +@Order(1) +public class SaveActionMethodEventHandler implements ApplicationListener { + + @Override + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 2:SaveActionMethodWorker----DEVICEID:{}…………", event.getEventData().getDeviceId()); +// if (null == event.getEventData()) { +// return; +// } +// DeviceDto deviceDto = event.getEventData(); +// if (ToolUtil.isEmpty(deviceDto.getMethod())) { +// return; +// } +// +// //保存设备服务下发 执行方法 +// DeviceServiceMethod deviceServiceMethod = new DeviceServiceMethod(); +// deviceServiceMethod.setDeviceId(deviceDto.getDeviceId()); +// deviceServiceMethod.setMethod(deviceDto.getMethod()); +// +// DB.save(deviceServiceMethod); +// log.debug("step 2:SaveActionMethodWorker----DEVICEID:{} complete…………", deviceDto.getDeviceId()); + return; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveAttributeEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveAttributeEventHandler.java new file mode 100644 index 00000000..9b02bad0 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveAttributeEventHandler.java @@ -0,0 +1,112 @@ +package com.zmops.iot.web.device.service.event; + +import cn.hutool.core.util.IdUtil; +import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.ProductAttributeEvent; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttributeEvent; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author yefei + *

+ * 设备属性处理步骤 + */ +@Slf4j +@Component +@Order(1) +public class SaveAttributeEventHandler implements ApplicationListener { + + + + private static final String ATTR_TYPE_RELY = "18"; + + @Override + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 3:saveAttributeWorker----DEVICEID:{}…………", event.getEventData().getDeviceId()); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); + String deviceId = deviceDto.getDeviceId(); + + if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { + //修改 + //没有修改关联的产品 不做处理 + if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { + return; + } + new QProductAttribute().productId.eq(deviceId).templateId.isNotNull().delete(); + new QProductAttributeEvent().productId.eq(deviceId).templateId.isNotNull().delete(); + } + + //属性 + List productAttributeList = new QProductAttribute().productId.eq( + deviceDto.getProductId() + "").orderBy(" source::int ").findList(); + + List newProductAttributeList = new ArrayList<>(); + + /** + * 处理依赖属性用 + * 遍历属性时 attrKeyMap保存 继承的属性ID 对应的 key + * attrIdMap 保存 key 对应的 新的属性ID + */ + Map attrKeyMap = new ConcurrentHashMap<>(productAttributeList.size()); + Map attrIdMap = new ConcurrentHashMap<>(productAttributeList.size()); + + for (ProductAttribute productAttribute : productAttributeList) { + ProductAttribute newProductAttrbute = new ProductAttribute(); + ToolUtil.copyProperties(productAttribute, newProductAttrbute); + newProductAttrbute.setTemplateId(productAttribute.getAttrId()); + newProductAttrbute.setZbxId(""); + Long attrId = IdUtil.getSnowflake().nextId(); + newProductAttrbute.setAttrId(attrId); + newProductAttrbute.setProductId(deviceId); + //处理依赖属性 + if (ATTR_TYPE_RELY.equals(productAttribute.getSource())) { + String key = attrKeyMap.get(productAttribute.getDepAttrId()); + if (ToolUtil.isNotEmpty(key)) { + Long deptAttrId = attrIdMap.get(key); + newProductAttrbute.setDepAttrId(deptAttrId); + } + } else { + attrKeyMap.put(productAttribute.getAttrId(), productAttribute.getKey()); + attrIdMap.put(productAttribute.getKey(), attrId); + } + newProductAttributeList.add(newProductAttrbute); + } + DB.saveAll(newProductAttributeList); + + //属性事件 + List productAttributeEventList = new QProductAttributeEvent().productId.eq( + deviceDto.getProductId() + "").findList(); + List newProductAttributeEventList = new ArrayList<>(); + + for (ProductAttributeEvent productAttributeEvent : productAttributeEventList) { + ProductAttributeEvent newProductAttrbuteEvent = new ProductAttributeEvent(); + ToolUtil.copyProperties(productAttributeEvent, newProductAttrbuteEvent); + newProductAttrbuteEvent.setTemplateId(productAttributeEvent.getAttrId()); + newProductAttrbuteEvent.setZbxId(""); + newProductAttrbuteEvent.setAttrId(IdUtil.getSnowflake().nextId()); + newProductAttrbuteEvent.setProductId(deviceId); + newProductAttributeEventList.add(newProductAttrbuteEvent); + } + DB.saveAll(newProductAttributeEventList); + + log.debug("step 3:saveAttributeWorker----DEVICEID:{} complete…………", deviceDto.getDeviceId()); + return; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveDeviceGrpEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveDeviceGrpEventHandler.java new file mode 100644 index 00000000..43c7878c --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveDeviceGrpEventHandler.java @@ -0,0 +1,48 @@ +package com.zmops.iot.web.device.service.event; + +import com.zmops.iot.domain.device.DevicesGroups; +import com.zmops.iot.domain.device.query.QDevicesGroups; +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author yefei + *

+ * 处理设备与设备组关系处理步骤 + */ +@Slf4j +@Component +@Order(1) +public class SaveDeviceGrpEventHandler implements ApplicationListener { + + @Override + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 4:SaveDeviceGrpWorker----DEVICEID:{}…………", event.getEventData().getDeviceId()); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); + //修改模式 先清空关联关系 + if (null != deviceDto.getDeviceId()) { + new QDevicesGroups().deviceId.eq(deviceDto.getDeviceId()).delete(); + } + + //保存设备与设备组关系 + List devicesGroupsList = new ArrayList<>(); + for (Long deviceGroupId : deviceDto.getDeviceGroupIds()) { + devicesGroupsList.add( + DevicesGroups.builder().deviceId(deviceDto.getDeviceId()).deviceGroupId(deviceGroupId).build()); + } + DB.saveAll(devicesGroupsList); + log.debug("step 4:SaveDeviceGrpWorker----DEVICEID:{} complate…………", deviceDto.getDeviceId()); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveOtherEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveOtherEventHandler.java new file mode 100644 index 00000000..f97003a1 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveOtherEventHandler.java @@ -0,0 +1,135 @@ +package com.zmops.iot.web.device.service.event; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.ProductStatusFunctionRelation; +import com.zmops.iot.domain.product.query.*; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import com.zmops.iot.web.product.dto.ZbxTriggerInfo; +import com.zmops.iot.web.product.service.ProductEventRuleService; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 其它处理步骤 + */ +@Slf4j +@Component +@Order(2) +public class SaveOtherEventHandler implements ApplicationListener { + + @Autowired + ZbxTrigger zbxTrigger; + + @Override + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 6:SaveOtherWorker----DEVICEID:{}…………", event.getEventData().getDeviceId()); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); + String deviceId = deviceDto.getDeviceId(); + + if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { + //修改 + + //没有修改关联的产品 不做处理 + if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { + return; + } + //删除服务关联 + new QProductServiceRelation().relationId.eq(deviceId).delete(); + //删除服务参数 + new QProductServiceParam().deviceId.eq(deviceId).delete(); + //删除 上下线规则关联 + new QProductStatusFunctionRelation().relationId.eq(deviceId).delete(); + //删除 告警规则关联 + new QProductEventRelation().relationId.eq(deviceId).delete(); + //删除 告警执行动作关联 + new QProductEventService().deviceId.eq(deviceId).delete(); + } + + //服务关联 + DB.sqlUpdate( + "insert into product_service_relation (relation_id,service_id,inherit) SELECT :deviceId,service_id,1 from product_service_relation where relation_id=:relationId") + .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); + //服务参数 + DB.sqlUpdate( + "insert into product_service_param (device_id,service_id,key,name,value,remark) SELECT :deviceId,service_id,key,name,value,remark from product_service_param where device_id=:relationId") + .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "").execute(); + + //上下线规则关联 + ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().relationId.eq( + deviceDto.getProductId() + "").findOne(); + if (null != relation) { + String triggerRes = zbxTrigger.triggerGetByName(relation.getRuleId() + ""); + + List zbxTriggerInfoList = JSONObject.parseArray(triggerRes, ZbxTriggerInfo.class); + Map hostTriggerMap = zbxTriggerInfoList.parallelStream() + .filter(o -> o.getTags().parallelStream().anyMatch(t -> "__offline__".equals(t.getTag()))) + .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid, (a, b) -> a)); + Map hostRecoveryTriggerMap = zbxTriggerInfoList.parallelStream() + .filter(o -> o.getTags().parallelStream().anyMatch(t -> "__online__".equals(t.getTag()))) + .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid, (a, b) -> a)); + + String zbxId = Optional.ofNullable(hostTriggerMap.get(deviceDto.getDeviceId())).orElse(""); + String zbxIdRecovery = Optional.ofNullable(hostRecoveryTriggerMap.get(deviceDto.getDeviceId())).orElse(""); + + DB.sqlUpdate( + "insert into product_status_function_relation (relation_id,rule_id,inherit,zbx_id,zbx_id_recovery) SELECT :deviceId,rule_id,1,:zbxId,:zbxIdRecovery from product_status_function_relation where relation_id=:relationId") + .setParameter("deviceId", deviceId).setParameter("relationId", deviceDto.getProductId() + "") + .setParameter("zbxId", zbxId) + .setParameter("zbxIdRecovery", zbxIdRecovery).execute(); + + } + + //告警规则关联 并 回填zbx triggerId + List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByHost(deviceId), + ProductEventRuleService.Triggers.class); + + Map map = triggers.parallelStream().collect( + Collectors.toMap(ProductEventRuleService.Triggers::getDescription, + ProductEventRuleService.Triggers::getTriggerid, (a, b) -> a)); + + List productEventRelationList = new QProductEventRelation().status.eq( + CommonStatus.ENABLE.getCode()).relationId.eq(deviceDto.getProductId() + "").findList(); + List newRelationList = new ArrayList<>(); + for (ProductEventRelation productEventRelation : productEventRelationList) { + ProductEventRelation newEventRelation = new ProductEventRelation(); + newEventRelation.setRelationId(deviceId); + newEventRelation.setInherit("1"); + newEventRelation.setZbxId(map.get(productEventRelation.getEventRuleId() + "")); + newEventRelation.setRemark(productEventRelation.getRemark()); + newEventRelation.setStatus(productEventRelation.getStatus()); + newEventRelation.setEventRuleId(productEventRelation.getEventRuleId()); + newRelationList.add(newEventRelation); + } + DB.saveAll(newRelationList); + + //告警执行动作关联 + DB.sqlUpdate( + "insert into product_event_service (service_id,device_id,execute_device_id,event_rule_id) SELECT service_id,:deviceId,:executeDeviceId,event_rule_id from product_event_service where device_id=:relationId") + .setParameter("deviceId", deviceId).setParameter("executeDeviceId", deviceId) + .setParameter("relationId", deviceDto.getProductId() + "").execute(); + + log.debug("step 6:SaveOtherWorker----DEVICEID:{} complate…………", deviceDto.getDeviceId()); + return; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveTagEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveTagEventHandler.java new file mode 100644 index 00000000..7fcc7438 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveTagEventHandler.java @@ -0,0 +1,49 @@ +package com.zmops.iot.web.device.service.event; + +import com.zmops.iot.domain.device.query.QTag; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * @author yefei + *

+ * 设备标签处理步骤 + */ +@Slf4j +@Component +@Order(2) +public class SaveTagEventHandler implements ApplicationListener { + + @Override + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 5:SaveTagWorker----DEVICEID:{}…………", event.getEventData().getDeviceId()); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); + String deviceId = deviceDto.getDeviceId(); + + if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { + //修改 + + //没有修改关联的产品 不做处理 + if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { + return; + } + new QTag().sid.eq(deviceId).delete(); + } + + //继承产品中的标签 + DB.sqlUpdate( + "insert into tag (sid,tag,value,template_id) SELECT :deviceId,tag,value,id template_id from tag where sid=:sid") + .setParameter("deviceId", deviceId).setParameter("sid", deviceDto.getProductId() + "").execute(); + log.debug("step 5:SaveTagWorker----DEVICEID:{} complete", deviceDto.getDeviceId()); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveZbxHostEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveZbxHostEventHandler.java new file mode 100644 index 00000000..a4010a61 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/SaveZbxHostEventHandler.java @@ -0,0 +1,73 @@ +package com.zmops.iot.web.device.service.event; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.constant.ConstantsContext; +import com.zmops.iot.domain.device.query.QDeviceGroup; +import com.zmops.iot.domain.product.query.QProduct; +import com.zmops.iot.domain.proxy.query.QProxy; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import com.zmops.zeus.driver.service.ZbxHost; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.List; + +import static com.zmops.iot.web.init.DeviceSatusScriptInit.GLOBAL_HOST_GROUP_CODE; + +/** + * @author yefei + *

+ * 保存至zbx + */ +@Slf4j +@Component +@Order(0) +public class SaveZbxHostEventHandler implements ApplicationListener { + + @Autowired + ZbxHost zbxHost; + + @Override + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("事件step 1:SaveZbxHostWorker----DEVICEID:{}…………", event.getEventData().getDeviceId()); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); + //设备ID 作为zbx HOST name + String host = deviceDto.getDeviceId(); + + //取出 设备对应的 zbx主机组ID,模板ID + List hostGrpIds = new QDeviceGroup().select(QDeviceGroup.alias().zbxId).deviceGroupId.in( + deviceDto.getDeviceGroupIds()).findSingleAttributeList(); + log.debug("step 1-1:SaveZbxHostWorker----hostGrpIds:{}…………", hostGrpIds.toString()); + String templateId = new QProduct().select(QProduct.alias().zbxId).productId.eq(deviceDto.getProductId()) + .findSingleAttribute(); + log.debug("step 1-2:SaveZbxHostWorker----templateId:{}…………", templateId); + hostGrpIds.add(ConstantsContext.getConstntsMap().get(GLOBAL_HOST_GROUP_CODE).toString()); + log.debug("step 1-3:SaveZbxHostWorker----hostGrpIds:{}…………", hostGrpIds.toString()); + //保存 zbx主机 + String result = ""; + Long proxyId = deviceDto.getProxyId(); + String zbxProxyId = null; + if (null != proxyId) { + zbxProxyId = new QProxy().select(QProxy.alias().zbxId).id.eq(proxyId).findSingleAttribute(); + } + log.debug("step 1-4:SaveZbxHostWorker----zbxProxyId:{}…………", zbxProxyId); + if (ToolUtil.isNotEmpty(deviceDto.getZbxId())) { + result = zbxHost.hostUpdate(deviceDto.getZbxId(), hostGrpIds, templateId, zbxProxyId, + deviceDto.getDeviceInterface()); + } else { + result = zbxHost.hostCreate(host, hostGrpIds, templateId, zbxProxyId, deviceDto.getDeviceInterface()); + } + String hostid = JSONObject.parseObject(result).getJSONArray("hostids").getString(0); + deviceDto.setZbxId(hostid); + log.debug("step 1:SaveZbxHostWorker----DEVICEID:{} complete,hostid:{}", deviceDto.getDeviceId(), hostid); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/ScenesLogEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/ScenesLogEventHandler.java new file mode 100644 index 00000000..859f605b --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/ScenesLogEventHandler.java @@ -0,0 +1,47 @@ +package com.zmops.iot.web.device.service.event; + +import com.zmops.iot.domain.device.ScenesTriggerRecord; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.web.event.applicationEvent.DeviceSceneLogEvent; +import com.zmops.iot.web.event.applicationEvent.dto.LogEventData; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +@Slf4j +@Component +@EnableAsync +public class ScenesLogEventHandler { + + @Async + @EventListener(classes = {DeviceSceneLogEvent.class}) + public void onApplicationEvent(DeviceSceneLogEvent event) { + log.debug("insert into ScenesLogWorker…………"); + LogEventData eventData = event.getEventData(); + + long eventRuleId = eventData.getEventRuleId(); + String triggerType = eventData.getTriggerType(); + Long triggerUser = eventData.getTriggerUser(); + + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); + if (productEvent == null) { + return; + } + + ScenesTriggerRecord scenesTriggerRecord = new ScenesTriggerRecord(); + scenesTriggerRecord.setRuleId(eventRuleId); + scenesTriggerRecord.setRuleName(productEvent.getEventRuleName()); + scenesTriggerRecord.setCreateTime(LocalDateTime.now()); + scenesTriggerRecord.setTenantId(productEvent.getTenantId()); + scenesTriggerRecord.setTriggerType(triggerType); + scenesTriggerRecord.setTriggerUser(triggerUser); + + DB.save(scenesTriggerRecord); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/ServiceLogEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/ServiceLogEventHandler.java new file mode 100644 index 00000000..faf0c241 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/ServiceLogEventHandler.java @@ -0,0 +1,76 @@ +package com.zmops.iot.web.device.service.event; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.ServiceExecuteRecord; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductEventService; +import com.zmops.iot.domain.product.ProductService; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.domain.product.query.QProductService; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.DeviceSceneLogEvent; +import com.zmops.iot.web.event.applicationEvent.dto.LogEventData; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +@Slf4j +@Component +@EnableAsync +public class ServiceLogEventHandler { + + @Async + @EventListener(classes = {DeviceSceneLogEvent.class}) + public void onApplicationEvent(DeviceSceneLogEvent event) { + log.debug("insert into service log…………"); + LogEventData eventData = event.getEventData(); + + long eventRuleId = eventData.getEventRuleId(); + String executeType = eventData.getTriggerType(); + Long executeUser = eventData.getTriggerUser(); + + List productEventServiceList = new QProductEventService().eventRuleId.eq(eventRuleId).findList(); + List serviceIds = productEventServiceList.parallelStream().map(ProductEventService::getServiceId).collect(Collectors.toList()); + + List productServiceList = new QProductService().id.in(serviceIds).findList(); + Map productServiceMap = productServiceList.parallelStream().collect(Collectors.toMap(ProductService::getId, o -> o, (a, b) -> a)); + + List deviceIds = productEventServiceList.parallelStream().map(ProductEventService::getExecuteDeviceId).collect(Collectors.toList()); + List deviceList = new QDevice().deviceId.in(deviceIds).tenantId.isNotNull().findList(); + Map deviceIdMap = deviceList.parallelStream().collect(Collectors.toMap(Device::getDeviceId, Device::getTenantId, (a, b) -> a)); + + List serviceExecuteRecordList = new ArrayList<>(); + productEventServiceList.forEach(productEventService -> { + ServiceExecuteRecord serviceExecuteRecord = new ServiceExecuteRecord(); + serviceExecuteRecord.setDeviceId(productEventService.getExecuteDeviceId()); + List paramList = DefinitionsUtil.getServiceParam(productEventService.getServiceId()); + if (ToolUtil.isNotEmpty(paramList)) { + serviceExecuteRecord.setParam(JSONObject.toJSONString(paramList.parallelStream().collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue, (a, b) -> a)))); + } + serviceExecuteRecord.setServiceName(Optional.ofNullable(productServiceMap.get(productEventService.getServiceId())).map(ProductService::getName).orElse("")); + if (deviceIdMap.get(productEventService.getExecuteDeviceId()) != null) { + serviceExecuteRecord.setTenantId(deviceIdMap.get(productEventService.getExecuteDeviceId())); + } + serviceExecuteRecord.setCreateTime(LocalDateTime.now()); + serviceExecuteRecord.setExecuteRuleId(eventRuleId); + serviceExecuteRecord.setExecuteType(executeType); + serviceExecuteRecord.setExecuteUser(executeUser); + + serviceExecuteRecordList.add(serviceExecuteRecord); + }); + DB.saveAll(serviceExecuteRecordList); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateAttrZbxIdEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateAttrZbxIdEventHandler.java new file mode 100644 index 00000000..fa1f647f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateAttrZbxIdEventHandler.java @@ -0,0 +1,85 @@ +package com.zmops.iot.web.device.service.event; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.ProductAttributeEvent; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttributeEvent; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import com.zmops.zeus.driver.entity.ZbxItemInfo; +import com.zmops.zeus.driver.service.ZbxItem; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 更新设备属性中ZBXID + */ +@Slf4j +@Component +@Order(2) +public class UpdateAttrZbxIdEventHandler implements ApplicationListener { + + @Autowired + ZbxItem zbxItem; + + @Override + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 7:resolve Attr zbxID async----deviceid: {} …………", event.getEventData().getDeviceId()); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); + String deviceId = deviceDto.getDeviceId(); + + if (ToolUtil.isNotEmpty(deviceDto.getEdit()) && "true".equals(deviceDto.getEdit())) { + //修改 + + //没有修改关联的产品 不做处理 + if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { + return; + } + } + + //取出 ZBX hostid + + //根据hostid 取出监控项 + List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(null, deviceDto.getZbxId()), + ZbxItemInfo.class); + if (ToolUtil.isEmpty(itemInfos)) { + return; + } + + Map itemMap = itemInfos.parallelStream() + .collect(Collectors.toMap(ZbxItemInfo::getName, o -> o, (a, b) -> a)); + //取出继承的属性 并塞入对应的 itemId + List productAttributeList = new QProductAttribute().productId.eq(deviceId).findList(); + for (ProductAttribute productAttribute : productAttributeList) { + productAttribute.setZbxId(itemMap.get(productAttribute.getTemplateId() + "").getItemid()); + } + + DB.updateAll(productAttributeList); + + //取出继承的属性事件 并塞入对应的 itemId + List productAttributeEventList = new QProductAttributeEvent().productId.eq(deviceId) + .findList(); + for (ProductAttributeEvent productAttributeEvent : productAttributeEventList) { + productAttributeEvent.setZbxId(itemMap.get(productAttributeEvent.getTemplateId() + "").getItemid()); + } + + DB.updateAll(productAttributeEventList); + log.debug("step 7:resolve Attr zbxID async----deviceid: {} complete", deviceDto.getDeviceId()); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateDeviceZbxIdEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateDeviceZbxIdEventHandler.java new file mode 100644 index 00000000..6f797a08 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateDeviceZbxIdEventHandler.java @@ -0,0 +1,39 @@ +package com.zmops.iot.web.device.service.event; + +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * @author yefei + *

+ * 更新设备中zbxID + */ +@Slf4j +@Component +@Order(2) +public class UpdateDeviceZbxIdEventHandler implements ApplicationListener { + + @Override + public void onApplicationEvent(DeviceSaveEvent event) { + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); + + log.debug("step 8:resolve zbxID async----DEVICEID:{}, HOSTID:{}…………", deviceDto.getDeviceId(), + deviceDto.getZbxId()); + + DB.update(Device.class).where().eq("deviceId", deviceDto.getDeviceId()).asUpdate() + .set("zbxId", deviceDto.getZbxId()).update(); + + log.debug("step 8:resolve zbxID async----DEVICEID:{}, HOSTID:{} 完成", deviceDto.getDeviceId(), + deviceDto.getZbxId()); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateZbxTagEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateZbxTagEventHandler.java new file mode 100644 index 00000000..358fd414 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/event/UpdateZbxTagEventHandler.java @@ -0,0 +1,52 @@ +package com.zmops.iot.web.device.service.event; + +import com.zmops.iot.domain.device.Tag; +import com.zmops.iot.domain.device.query.QTag; +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.DeviceSaveEvent; +import com.zmops.zeus.driver.service.ZbxHost; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author yefei + *

+ * 同步设备标签到zbx + */ +@Slf4j +@Component +@Order(2) +public class UpdateZbxTagEventHandler implements ApplicationListener { + + @Autowired + ZbxHost zbxHost; + + @Override + public void onApplicationEvent(DeviceSaveEvent event) { + log.debug("step 9: UpdateZbxTagWorker ……"); + if (null == event.getEventData()) { + return; + } + DeviceDto deviceDto = event.getEventData(); + + //查询出本地tag + List list = new QTag().sid.eq(deviceDto.getDeviceId()).findList(); + Map tagMap = new HashMap<>(list.size()); + for (Tag tag : list) { + tagMap.put(tag.getTag(), tag.getValue()); + } + + //保存 + zbxHost.hostTagUpdate(deviceDto.getZbxId(), tagMap); + log.debug("step 9:resolve zbxID async----DEVICEID:{}, HOSTID:{} 完成", deviceDto.getDeviceId(), + deviceDto.getZbxId()); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java deleted file mode 100644 index 72158ba6..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveAttributeWorker.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.zmops.iot.web.device.service.work; - - -import cn.hutool.core.util.IdUtil; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.domain.product.ProductAttribute; -import com.zmops.iot.domain.product.query.QProductAttribute; -import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.device.dto.DeviceDto; -import io.ebean.DB; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * @author yefei - * - * 设备属性处理步骤 - */ -@Slf4j -@Component -public class SaveAttributeWorker implements IWorker { - - - @Override - public Boolean action(DeviceDto deviceDto, Map> map) { - log.debug("处理Attr工作…………"); - - Long deviceId = deviceDto.getDeviceId(); - //创建 - if (null == deviceId) { - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - deviceId = device.getDeviceId(); - } else { - //修改 - - //没有修改关联的产品 不做处理 - if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { - return true; - } - new QProductAttribute().productId.eq(deviceId).templateId.isNotNull().delete(); - } - - - List productAttributeList = new QProductAttribute().productId.eq(deviceDto.getProductId()).findList(); - List newProductAttributeList = new ArrayList<>(); - - for (ProductAttribute productAttribute : productAttributeList) { - ProductAttribute newProductAttrbute = new ProductAttribute(); - ToolUtil.copyProperties(productAttribute, newProductAttrbute); - newProductAttrbute.setTemplateId(productAttribute.getAttrId()); - newProductAttrbute.setZbxId(""); - newProductAttrbute.setAttrId(IdUtil.getSnowflake().nextId()); - newProductAttrbute.setProductId(deviceId); - newProductAttributeList.add(newProductAttrbute); - } - DB.saveAll(newProductAttributeList); - - return true; - } - - - @Override - public Boolean defaultValue() { - return true; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java deleted file mode 100644 index 33bcaeec..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceGrpWorker.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.zmops.iot.web.device.service.work; - - -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.domain.device.DevicesGroups; -import com.zmops.iot.domain.device.query.QDevicesGroups; -import com.zmops.iot.web.device.dto.DeviceDto; -import io.ebean.DB; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * @author yefei - * - * 处理设备与设备组关系处理步骤 - */ -@Slf4j -@Component -public class SaveDeviceGrpWorker implements IWorker { - - - @Override - public Boolean action(DeviceDto deviceDto, Map> map) { - log.debug("处理设备与设备组关系工作…………"); - - //修改模式 先清空关联关系 - if (null != deviceDto.getDeviceId()) { - new QDevicesGroups().deviceId.eq(deviceDto.getDeviceId()).delete(); - } - - //保存设备与设备组关系 - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - List devicesGroupsList = new ArrayList<>(); - for (Long deviceGroupId : deviceDto.getDeviceGroupIds()) { - devicesGroupsList.add(DevicesGroups.builder().deviceId(device.getDeviceId()).deviceGroupId(deviceGroupId).build()); - } - DB.saveAll(devicesGroupsList); - - return true; - } - - - @Override - public Boolean defaultValue() { - return true; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java deleted file mode 100644 index 40d25add..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveDeviceWorker.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.zmops.iot.web.device.service.work; - - -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.enums.CommonStatus; -import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.device.dto.DeviceDto; -import io.ebean.DB; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.Map; - -/** - * @author yefei - * - * 保存设备 - */ -@Slf4j -@Component -public class SaveDeviceWorker implements IWorker { - - @Override - public Device action(DeviceDto deviceDto, Map> allWrappers) { - log.debug("处理device工作…………"); - - Device device = new Device(); - ToolUtil.copyProperties(deviceDto, device); - - if (null == deviceDto.getDeviceId()) { - device.setStatus(CommonStatus.ENABLE.getCode()); - DB.save(device); - } else { - DB.update(device); - } - - return device; - } - - - @Override - public Device defaultValue() { - return new Device(); - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java deleted file mode 100644 index 48ae81c0..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveTagWorker.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.zmops.iot.web.device.service.work; - - -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.domain.device.query.QTag; -import com.zmops.iot.web.device.dto.DeviceDto; -import io.ebean.DB; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.Map; - -/** - * @author yefei - *

- * 设备标签处理步骤 - */ -@Slf4j -@Component -public class SaveTagWorker implements IWorker { - - @Override - public Boolean action(DeviceDto deviceDto, Map> allWrappers) { - log.debug("处理tag工作…………"); - - Long deviceId = deviceDto.getDeviceId(); - //创建 - if (null == deviceId) { - Device device = (Device) allWrappers.get("saveDvice").getWorkResult().getResult(); - deviceId = device.getDeviceId(); - } else { - //修改 - - //没有修改关联的产品 不做处理 - if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { - return true; - } - new QTag().sid.eq(deviceId).delete(); - } - - DB.sqlUpdate("insert into tag (sid,tag,value,template_id) SELECT :deviceId,tag,value,id template_id from tag where sid=:sid") - .setParameter("deviceId", deviceId).setParameter("sid", deviceDto.getProductId()).execute(); - - return true; - } - - @Override - public Boolean defaultValue() { - return true; - } -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java deleted file mode 100644 index c071ed43..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/SaveZbxHostWorker.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.zmops.iot.web.device.service.work; - - -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.constant.ConstantsContext; -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.domain.device.query.QDeviceGroup; -import com.zmops.iot.domain.product.query.QProduct; -import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.device.dto.DeviceDto; -import com.zmops.zeus.driver.service.ZbxHost; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Map; - -import static com.zmops.iot.web.init.DeviceSatusScriptInit.GLOBAL_HOST_GROUP_CODE; - -/** - * @author yefei - *

- * 保存至zbx - */ -@Slf4j -@Component -public class SaveZbxHostWorker implements IWorker { - - @Autowired - ZbxHost zbxHost; - - @Override - public String action(DeviceDto deviceDto, Map> map) { - log.debug("处理Zbx host工作…………"); - //设备ID 作为zbx HOST name - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - String host = device.getDeviceId() + ""; - - //取出 设备对应的 zbx主机组ID,模板ID - List hostGrpIds = new QDeviceGroup().select(QDeviceGroup.alias().zbxId).deviceGroupId.in(deviceDto.getDeviceGroupIds()).findSingleAttributeList(); - String templateId = new QProduct().select(QProduct.alias().zbxId).productId.eq(deviceDto.getProductId()).findSingleAttribute(); - hostGrpIds.add(ConstantsContext.getConstntsMap().get(GLOBAL_HOST_GROUP_CODE).toString()); - - //保存 zbx主机 - String s = ""; - if (ToolUtil.isNotEmpty(deviceDto.getZbxId())) { - s = zbxHost.hostUpdate(deviceDto.getZbxId(), hostGrpIds, templateId); - } else { - s = zbxHost.hostCreate(host, hostGrpIds, templateId); - } - - return s; - } - - @Override - public String defaultValue() { - return ""; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java deleted file mode 100644 index d5b1d1d8..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateAttrZbxIdWorker.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.zmops.iot.web.device.service.work; - - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.domain.product.ProductAttribute; -import com.zmops.iot.domain.product.query.QProductAttribute; -import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.device.dto.DeviceDto; -import com.zmops.zeus.driver.entity.ZbxItemInfo; -import com.zmops.zeus.driver.service.ZbxItem; -import io.ebean.DB; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * @author yefei - * - * 更新设备属性中ZBXID - */ -@Slf4j -@Component -public class UpdateAttrZbxIdWorker implements IWorker { - - @Autowired - ZbxItem zbxItem; - - @Override - public Boolean action(DeviceDto deviceDto, Map> map) { - log.debug("处理Attr zbx回填工作……"); - Long deviceId = deviceDto.getDeviceId(); - //创建 - if (null == deviceId) { - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - deviceId = device.getDeviceId(); - } else { - //修改 - - //没有修改关联的产品 不做处理 - if (deviceDto.getProductId().equals(deviceDto.getOldProductId())) { - return true; - } - } - - //取出 ZBX hostid - Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); - JSONArray hostid = JSONObject.parseObject(result.toString()).getJSONArray("hostids"); - - //根据hostid 取出监控项 - List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(null, hostid.get(0).toString()), ZbxItemInfo.class); - if (ToolUtil.isEmpty(itemInfos)) { - return true; - } - - Map itemMap = itemInfos.parallelStream().collect(Collectors.toMap(ZbxItemInfo::getName, o -> o)); - //取出继承的属性 并塞入对应的 itemId - List productAttributeList = new QProductAttribute().productId.eq(deviceId).findList(); - for (ProductAttribute productAttribute : productAttributeList) { - productAttribute.setZbxId(itemMap.get(productAttribute.getTemplateId() + "").getItemid()); - } - - DB.updateAll(productAttributeList); - return true; - } - - @Override - public Boolean defaultValue() { - return true; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java deleted file mode 100644 index 1a02e28e..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateDeviceZbxIdWorker.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.zmops.iot.web.device.service.work; - - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; -import io.ebean.DB; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.Map; - -/** - * @author yefei - * - * 更新设备中zbxID - */ -@Slf4j -@Component -public class UpdateDeviceZbxIdWorker implements IWorker { - - - @Override - public Boolean action(String deviceDto, Map> map) { - log.debug("处理 zbxID 回填工作…………"); - - Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); - JSONArray hostid = JSONObject.parseObject(result.toString()).getJSONArray("hostids"); - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - device.setZbxId(hostid.get(0).toString()); - DB.update(device); - - return true; - } - - @Override - public Boolean defaultValue() { - return true; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java deleted file mode 100644 index 68a25fa8..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/device/service/work/UpdateZbxTagWorker.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.zmops.iot.web.device.service.work; - - -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.Device; -import com.zmops.iot.domain.device.Tag; -import com.zmops.iot.domain.device.query.QTag; -import com.zmops.iot.web.device.dto.DeviceDto; -import com.zmops.zeus.driver.service.ZbxHost; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * @author yefei - *

- * 同步设备标签到zbx - */ -@Slf4j -@Component -public class UpdateZbxTagWorker implements IWorker { - - @Autowired - ZbxHost zbxHost; - - @Override - public Boolean action(DeviceDto deviceDto, Map> map) { - log.debug("同步 zbx tag 工作……"); - //取出 ZBX hostid - Object result = map.get("saveZbxHostWork").getWorkResult().getResult(); - JSONArray hostid = JSONObject.parseObject(result.toString()).getJSONArray("hostids"); - - //取 设备ID - Device device = (Device) map.get("saveDvice").getWorkResult().getResult(); - Long deviceId = device.getDeviceId(); - - //查询出本地tag - List list = new QTag().sid.eq(deviceId).findList(); - Map tagMap = new HashMap<>(list.size()); - for (Tag tag : list) { - tagMap.put(tag.getTag(), tag.getValue()); - } - - //保存 - zbxHost.hostTagUpdate(hostid.getString(0), tagMap); - return true; - } - - @Override - public Boolean defaultValue() { - return true; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/BaseEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/BaseEvent.java new file mode 100644 index 00000000..e9fad34e --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/BaseEvent.java @@ -0,0 +1,20 @@ +package com.zmops.iot.web.event.applicationEvent; + +import org.springframework.context.ApplicationEvent; + +/** + * @author yefei + **/ +public abstract class BaseEvent extends ApplicationEvent { + + private T eventData; + + public BaseEvent(Object source, T eventData) { + super(source); + this.eventData = eventData; + } + + public T getEventData() { + return eventData; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceDeleteEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceDeleteEvent.java new file mode 100644 index 00000000..2c25c940 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceDeleteEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.event.applicationEvent.dto.DeviceDeleteEventData; + +/** + * @author yefei + **/ +public class DeviceDeleteEvent extends BaseEvent { + public DeviceDeleteEvent(Object source, DeviceDeleteEventData eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceSaveEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceSaveEvent.java new file mode 100644 index 00000000..e5c286a2 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceSaveEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.device.dto.DeviceDto; + +/** + * @author yefei + **/ +public class DeviceSaveEvent extends BaseEvent { + public DeviceSaveEvent(Object source, DeviceDto eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceSceneLogEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceSceneLogEvent.java new file mode 100644 index 00000000..4b258b84 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceSceneLogEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.event.applicationEvent.dto.LogEventData; + +/** + * @author yefei + **/ +public class DeviceSceneLogEvent extends BaseEvent { + public DeviceSceneLogEvent(Object source, LogEventData eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceServiceLogEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceServiceLogEvent.java new file mode 100644 index 00000000..845afc58 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/DeviceServiceLogEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.event.applicationEvent.dto.LogEventData; + +/** + * @author yefei + **/ +public class DeviceServiceLogEvent extends BaseEvent { + public DeviceServiceLogEvent(Object source, LogEventData eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductAttrCreateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductAttrCreateEvent.java new file mode 100644 index 00000000..58c3b881 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductAttrCreateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductAttr; + +/** + * @author yefei + **/ +public class ProductAttrCreateEvent extends BaseEvent { + public ProductAttrCreateEvent(Object source, ProductAttr eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductAttrUpdateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductAttrUpdateEvent.java new file mode 100644 index 00000000..ed1f32c2 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductAttrUpdateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductAttr; + +/** + * @author yefei + **/ +public class ProductAttrUpdateEvent extends BaseEvent { + public ProductAttrUpdateEvent(Object source, ProductAttr eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductEventTriggerCreateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductEventTriggerCreateEvent.java new file mode 100644 index 00000000..82a62241 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductEventTriggerCreateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductEventRule; + +/** + * @author yefei + **/ +public class ProductEventTriggerCreateEvent extends BaseEvent { + public ProductEventTriggerCreateEvent(Object source, ProductEventRule eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductEventTriggerUpdateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductEventTriggerUpdateEvent.java new file mode 100644 index 00000000..09796102 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductEventTriggerUpdateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductEventRule; + +/** + * @author yefei + **/ +public class ProductEventTriggerUpdateEvent extends BaseEvent { + public ProductEventTriggerUpdateEvent(Object source, ProductEventRule eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductModelCreateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductModelCreateEvent.java new file mode 100644 index 00000000..1dc8f265 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductModelCreateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductAttr; + +/** + * @author yefei + **/ +public class ProductModelCreateEvent extends BaseEvent { + public ProductModelCreateEvent(Object source, ProductAttr eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductModelUpdateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductModelUpdateEvent.java new file mode 100644 index 00000000..68e936df --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductModelUpdateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductAttr; + +/** + * @author yefei + **/ +public class ProductModelUpdateEvent extends BaseEvent { + public ProductModelUpdateEvent(Object source, ProductAttr eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductServiceCreateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductServiceCreateEvent.java new file mode 100644 index 00000000..9a6f0dc6 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductServiceCreateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductServiceDto; + +/** + * @author yefei + **/ +public class ProductServiceCreateEvent extends BaseEvent { + public ProductServiceCreateEvent(Object source, ProductServiceDto eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductServiceUpdateEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductServiceUpdateEvent.java new file mode 100644 index 00000000..83a3caec --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/ProductServiceUpdateEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.product.dto.ProductServiceDto; + +/** + * @author yefei + **/ +public class ProductServiceUpdateEvent extends BaseEvent { + public ProductServiceUpdateEvent(Object source, ProductServiceDto eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/SceneEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/SceneEvent.java new file mode 100644 index 00000000..8037b735 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/SceneEvent.java @@ -0,0 +1,12 @@ +package com.zmops.iot.web.event.applicationEvent; + +import com.zmops.iot.web.event.applicationEvent.dto.SceneEventData; + +/** + * @author yefei + **/ +public class SceneEvent extends BaseEvent { + public SceneEvent(Object source, SceneEventData eventData) { + super(source, eventData); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/DeviceDeleteEventData.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/DeviceDeleteEventData.java new file mode 100644 index 00000000..c936829f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/DeviceDeleteEventData.java @@ -0,0 +1,15 @@ +package com.zmops.iot.web.event.applicationEvent.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class DeviceDeleteEventData { + private String deviceId; + private String zbxId; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/LogEventData.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/LogEventData.java new file mode 100644 index 00000000..b3d80156 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/LogEventData.java @@ -0,0 +1,22 @@ +package com.zmops.iot.web.event.applicationEvent.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author yefei + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class LogEventData { + + private Long eventRuleId; + private String relationId; + private String triggerType; + private Long triggerUser; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/SceneEventData.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/SceneEventData.java new file mode 100644 index 00000000..8be68af4 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/applicationEvent/dto/SceneEventData.java @@ -0,0 +1,17 @@ +package com.zmops.iot.web.event.applicationEvent.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author yefei + **/ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class SceneEventData { + + private String executeParam; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/EventDataProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/EventDataProcess.java new file mode 100644 index 00000000..9c083c72 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/EventDataProcess.java @@ -0,0 +1,41 @@ +package com.zmops.iot.web.event.pgEvent; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; +import lombok.extern.slf4j.Slf4j; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Collection; + +/** + * @author yefei + **/ +@Slf4j +@Component(value = "EventDataProcess") +public class EventDataProcess implements Processor { + + @Autowired + Collection eventProcessList; + + @Override + public void process(Exchange exchange) throws Exception { + String inputContext = exchange.getIn().getBody().toString(); + String[] split = inputContext.split("\\$\\$"); + if (split.length != 2) { + return; + } + + EventDataDto eventData = JSONObject.parseObject(split[1], EventDataDto.class); + + eventProcessList.forEach(eventProcess -> { + if(eventProcess.checkTag(eventData.getTag())){ + eventProcess.process(eventData); + } + }); + + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/EventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/EventProcess.java new file mode 100644 index 00000000..aee831cc --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/EventProcess.java @@ -0,0 +1,13 @@ +package com.zmops.iot.web.event.pgEvent; + +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; + +/** + * @author yefei + **/ +public interface EventProcess { + + void process(EventDataDto eventData); + + boolean checkTag(String tag); +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/SyncZbxEvent.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/SyncZbxEvent.java new file mode 100644 index 00000000..fb31373b --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/SyncZbxEvent.java @@ -0,0 +1,36 @@ +package com.zmops.iot.web.event.pgEvent; + +import com.zmops.iot.util.SpringUtils; +import org.apache.camel.LoggingLevel; +import org.apache.camel.builder.RouteBuilder; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +/** + * @author yefei + **/ +@Component +public class SyncZbxEvent extends RouteBuilder { + + @Value("${spring.datasource.druid.url}") + private String url; + @Value("${spring.datasource.druid.username}") + private String username; + @Value("${spring.datasource.druid.password}") + private String password; + + @Override + public void configure() throws Exception { + url = url.substring(url.indexOf("//") + 2); + String host = url.substring(0, url.indexOf(":")); + int port = Optional.of(url.substring(url.indexOf(":") + 1, url.indexOf("/"))).map(Integer::parseInt).orElse(5432); + + fromF("pgevent:%s:%d/zabbix/zabbix_pg_event?pass=%s&user=%s", host, port, password, username) + .process(SpringUtils.getBean(EventDataProcess.class)) + + .log(LoggingLevel.DEBUG, log, ">>> PgEvent received from Zabbix Events : ${body}"); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/dto/EventDataDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/dto/EventDataDto.java new file mode 100644 index 00000000..7eaa2463 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/dto/EventDataDto.java @@ -0,0 +1,29 @@ +package com.zmops.iot.web.event.pgEvent.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class EventDataDto { + private String eventid; + + private String objectid; + + private String name; + + private String tag; + + private String tagValue; + + private String recoveryValue; + + private Integer acknowledged; + + private Integer clock; + + private Integer rClock; + + private Integer severity; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java new file mode 100644 index 00000000..347345c1 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/AlarmEventProcess.java @@ -0,0 +1,156 @@ +package com.zmops.iot.web.event.pgEvent.service; + +import com.zmops.iot.domain.alarm.Problem; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.messages.MessageBody; +import com.zmops.iot.domain.messages.NoticeRecord; +import com.zmops.iot.domain.messages.NoticeResult; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.sys.SysUser; +import com.zmops.iot.domain.sys.query.QSysUser; +import com.zmops.iot.media.NoticeService; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.alarm.service.AlarmService; +import com.zmops.iot.web.alarm.service.MessageService; +import com.zmops.iot.web.event.pgEvent.EventProcess; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; +import com.zmops.iot.web.sys.dto.UserGroupDto; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Slf4j +@Component +public class AlarmEventProcess implements EventProcess { + + @Autowired + MessageService messageService; + + @Autowired + AlarmService alarmService; + + + @Autowired + NoticeService noticeService; + + @Override + public void process(EventDataDto eventData) { + String triggerId = eventData.getObjectid(); + String triggerName = eventData.getName(); + + log.debug("--------alarm event----------{}", triggerId); + + //step 1:插入problem + boolean isNew = true; + Problem problem = new Problem(); + problem.setEventId(Long.parseLong(eventData.getEventid())); + problem.setObjectId(Long.parseLong(eventData.getObjectid())); + problem.setAcknowledged(eventData.getAcknowledged()); + problem.setSeverity(eventData.getSeverity()); + problem.setName(DefinitionsUtil.getTriggerName(Long.parseLong(eventData.getName()))); + problem.setDeviceId(eventData.getTagValue()); + problem.setClock(LocalDateTimeUtils.getLDTBySeconds(eventData.getClock())); + problem.setRClock(eventData.getRClock() == 0 ? null : LocalDateTimeUtils.getLDTBySeconds(eventData.getRClock())); + if (eventData.getRClock() == 0 && eventData.getAcknowledged() == 0) { + DB.insert(problem); + } else { + DB.update(problem); + isNew = false; + } + + //step 2:找出需要通知的用户ID 推送通知 + List deviceIds = new QProductEventRelation().select(QProductEventRelation.alias().relationId).zbxId.eq(triggerId).findSingleAttributeList(); + if (ToolUtil.isEmpty(deviceIds)) { + return; + } + Map params = new ConcurrentHashMap<>(2); + params.put("hostname", deviceIds); + params.put("triggerName", triggerName); + + List tenantIds = new QDevice().select(QDevice.alias().tenantId).deviceId.in(deviceIds).tenantId.isNotNull().findSingleAttributeList(); + + String sql = "select user_group_id from sys_usrgrp_devicegrp where device_group_id in (select device_group_id from devices_groups where device_id in (:deviceIds))"; + List userGroups = DB.findDto(UserGroupDto.class, sql).setParameter("deviceIds", deviceIds).findList(); + + QSysUser qSysUser = new QSysUser(); + if (ToolUtil.isNotEmpty(userGroups)) { + qSysUser.userGroupId.in(userGroups.parallelStream().map(UserGroupDto::getUserGroupId).collect(Collectors.toList())); + } + if (!CollectionUtils.isEmpty(tenantIds)) { + qSysUser.tenantId.in(tenantIds); + } + List sysUserList = qSysUser.findList(); + List userIds = sysUserList.parallelStream().map(SysUser::getUserId).collect(Collectors.toList()); + + + alarmService.alarm(params); + + //发送Email消息 + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(Long.parseLong(triggerName)).findOne(); + + Map macros = createMacroMap(triggerId, eventData.getRClock() + "", eventData.getAcknowledged() + "", productEvent); + messageService.push(buildMessage(macros, userIds, isNew)); + + List noticeRecords = new ArrayList<>(); + sysUserList.forEach(sysUser -> { + Map notice = noticeService.notice(sysUser, macros, triggerId); + for (Map.Entry en : notice.entrySet()) { + noticeRecords.add(NoticeRecord.builder() + .userId(sysUser.getUserId()) + .problemId(triggerId) + .noticeType(en.getKey()) + .noticeStatus(en.getValue().getStatus().name()) + .noticeMsg(en.getValue().getMsg()) + .creatTime(LocalDateTime.now()) + .alarmInfo(en.getValue().getAlarmInfo()) + .receiveAccount(en.getValue().getReceiveAccount()) + .build()); + } + }); + DB.saveAll(noticeRecords); + } + + private Map createMacroMap(String triggerId, String rclock, String acknowledged, ProductEvent productEvent) { + boolean isnew = "0".equals(rclock); + Map macroMap = new HashMap(); + macroMap.put("${time}", LocalDateTimeUtils.formatTime(LocalDateTime.now())); + + macroMap.put("${level}", DefinitionsUtil.getNameByVal("EVENT_LEVEL", productEvent.getEventLevel())); + macroMap.put("${severity}", productEvent.getEventLevel()); + macroMap.put("${metricName}", productEvent.getEventRuleName()); + macroMap.put("${context}", productEvent.getEventRuleName()); + macroMap.put("${alarmStatus}", isnew ? "告警触发" : "撤销告警"); + macroMap.put("${confirmStatus}", "1".equals(acknowledged) ? "已确认" : "未确认"); + macroMap.put("${problemId}", triggerId); + return macroMap; + } + + private MessageBody buildMessage(Map alarmInfo, List userIds, boolean isNew) { + Map params = new HashMap<>(alarmInfo); + String title = isNew ? "告警触发:" : "告警恢复:"; + return MessageBody.builder().msg(title + alarmInfo.get("${metricName}")).persist(true).to(userIds).body(params).build(); + } + + + @Override + public boolean checkTag(String tag) { + return "__alarm__".equals(tag); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/IncidentEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/IncidentEventProcess.java new file mode 100644 index 00000000..dcc8c705 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/IncidentEventProcess.java @@ -0,0 +1,69 @@ +package com.zmops.iot.web.event.pgEvent.service; + +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.EventTriggerRecord; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductAttributeEvent; +import com.zmops.iot.domain.product.query.QProductAttributeEvent; +import com.zmops.iot.web.analyse.dto.LatestDto; +import com.zmops.iot.web.analyse.service.LatestService; +import com.zmops.iot.web.event.pgEvent.EventProcess; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; + +/** + * @author yefei + * + * 事件处理 + **/ +@Slf4j +@Component +public class IncidentEventProcess implements EventProcess { + + @Autowired + LatestService latestService; + + @Override + public void process(EventDataDto eventData) { + String triggerId = eventData.getObjectid(); + String tagValue = eventData.getTagValue(); + + log.debug("-------- event----------triggerId:{},tagValue:{}", triggerId, tagValue); + + String[] split = tagValue.split("##"); + if (split.length != 2) { + return; + } + String deviceId = split[0]; + String key = split[1]; + + Device device = new QDevice().deviceId.eq(deviceId).findOne(); + ProductAttributeEvent productAttributeEvent = new QProductAttributeEvent().productId.eq(deviceId).key.eq(key).findOne(); + + //取事件属性最新值 + List latestDtos = latestService.queryEventLatest(device.getZbxId(), Collections.singletonList(productAttributeEvent.getZbxId()), + Integer.parseInt(productAttributeEvent.getValueType())); + + EventTriggerRecord eventTriggerRecord = new EventTriggerRecord(); + eventTriggerRecord.setCreateTime(LocalDateTime.now()); + eventTriggerRecord.setDeviceId(deviceId); + eventTriggerRecord.setEventName(productAttributeEvent.getName()); + eventTriggerRecord.setEventValue(latestDtos.get(0).getOriginalValue()); + eventTriggerRecord.setTenantId(device.getTenantId()); + eventTriggerRecord.setKey(productAttributeEvent.getKey()); + + DB.insert(eventTriggerRecord); + } + + @Override + public boolean checkTag(String tag) { + return "__event__".equals(tag); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/OfflineEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/OfflineEventProcess.java new file mode 100644 index 00000000..c59a4357 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/OfflineEventProcess.java @@ -0,0 +1,50 @@ +package com.zmops.iot.web.event.pgEvent.service; + +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductStatusFunctionRelation; +import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.pgEvent.EventProcess; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * @author yefei + *

+ * 设备离线处理 + **/ +@Slf4j +@Component +public class OfflineEventProcess implements EventProcess { + + @Override + public void process(EventDataDto eventData) { + log.debug("update device offline status…………"); + + ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().zbxId.eq(eventData.getObjectid()).findOne(); + if (null == relation) { + return; + } + String deviceId = relation.getRelationId(); + if (ToolUtil.isEmpty(deviceId)) { + return; + } + Device device = new QDevice().deviceId.eq(deviceId).findOne(); + if (null == device) { + return; + } + + DB.update(Device.class).where().eq("deviceId", device.getDeviceId()).asUpdate() + .set("online", 0).set("latestOnline", LocalDateTime.now()).update(); + } + + @Override + public boolean checkTag(String tag) { + return "__offline__".equals(tag); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/OnlineEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/OnlineEventProcess.java new file mode 100644 index 00000000..1971fbff --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/OnlineEventProcess.java @@ -0,0 +1,51 @@ +package com.zmops.iot.web.event.pgEvent.service; + +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductStatusFunctionRelation; +import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.pgEvent.EventProcess; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * @author yefei + *

+ * 设备上线处理 + **/ +@Slf4j +@Component +public class OnlineEventProcess implements EventProcess { + + @Override + public void process(EventDataDto eventData) { + log.debug("update device online status…………"); + + ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().zbxIdRecovery.eq(eventData.getObjectid()).findOne(); + if (null == relation) { + return; + } + String deviceId = relation.getRelationId(); + if (ToolUtil.isEmpty(deviceId)) { + return; + } + Device device = new QDevice().deviceId.eq(deviceId).findOne(); + if (null == device) { + return; + } + + DB.update(Device.class).where().eq("deviceId", device.getDeviceId()).asUpdate() + .set("online", 1).set("latestOnline", LocalDateTime.now()).update(); + } + + @Override + public boolean checkTag(String tag) { + return "__online__".equals(tag); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/SceneEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/SceneEventProcess.java new file mode 100644 index 00000000..297d13c5 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/SceneEventProcess.java @@ -0,0 +1,39 @@ +package com.zmops.iot.web.event.pgEvent.service; + +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.service.MultipleDeviceEventRuleService; +import com.zmops.iot.web.event.pgEvent.EventProcess; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * @author yefei + * + * 场景触发 + **/ +@Slf4j +@Component +public class SceneEventProcess implements EventProcess { + + @Autowired + MultipleDeviceEventRuleService eventRuleService; + + @Override + public void process(EventDataDto eventData) { + log.debug("--------scene event----------ruleId:{}", eventData.getName()); + + if (ToolUtil.isEmpty(eventData.getName())) { + return; + } + + eventRuleService.execute(Long.parseLong(eventData.getName()), "自动", null); + } + + @Override + public boolean checkTag(String tag) { + return "__scene__".equals(tag); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java new file mode 100644 index 00000000..1634430d --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/event/pgEvent/service/ServiceEventProcess.java @@ -0,0 +1,95 @@ +package com.zmops.iot.web.event.pgEvent.service; + +import com.alibaba.fastjson.JSON; +import com.dtflys.forest.Forest; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.ProductEventService; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.DeviceServiceLogEvent; +import com.zmops.iot.web.event.applicationEvent.dto.LogEventData; +import com.zmops.iot.web.event.pgEvent.EventProcess; +import com.zmops.iot.web.event.pgEvent.dto.EventDataDto; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 告警执行服务 + **/ +@Slf4j +@Component +public class ServiceEventProcess implements EventProcess { + + @Autowired + ApplicationEventPublisher publisher; + + @Override + public void process(EventDataDto eventData) { + log.debug("--------service event----------{}", eventData.getObjectid()); + Map alarmInfo = new ConcurrentHashMap<>(3); + + //查询 告警规则 + List productEventRelationList = new QProductEventRelation().zbxId.eq(eventData.getObjectid()).findList(); + if (ToolUtil.isEmpty(productEventRelationList)) { + return; + } + + //记录服务日志 + publisher.publishEvent(new DeviceServiceLogEvent(this, LogEventData.builder().eventRuleId(productEventRelationList.get(0).getEventRuleId()) + .relationId(productEventRelationList.get(0).getRelationId()).triggerType("自动").build())); + + //查询 告警规则 关联的 服务 + List productEventServiceList = new QProductEventService() + .eventRuleId.eq(productEventRelationList.get(0).getEventRuleId()) + .or() + .deviceId.isNull() + .deviceId.eq(productEventRelationList.get(0).getRelationId()) + .endOr() + .findList(); + + List> list = new ArrayList<>(); + Map> collect = productEventServiceList.parallelStream() + .collect(Collectors.groupingBy(ProductEventService::getExecuteDeviceId)); + + collect.forEach((key, value) -> { + Map map = new ConcurrentHashMap<>(); + map.put("device", key); + + List> serviceList = new ArrayList<>(); + value.forEach(val -> { + Map serviceMap = new ConcurrentHashMap<>(); + serviceMap.put("name", DefinitionsUtil.getServiceName(val.getServiceId())); + + List paramList = DefinitionsUtil.getServiceParam(val.getServiceId()); + if (ToolUtil.isNotEmpty(paramList)) { + serviceMap.put("param", paramList.parallelStream().filter(o -> key.equals(o.getDeviceId())) + .collect(Collectors.toMap(ProductServiceParam::getKey, ProductServiceParam::getValue, (a, b) -> a))); + } + serviceList.add(serviceMap); + }); + map.put("service", serviceList); + list.add(map); + }); + + Forest.post("/device/action/exec").host("127.0.0.1").port(12800).contentTypeJson().addBody(JSON.toJSON(list)).execute(); + } + + @Override + public boolean checkTag(String tag) { + return "__execute__".equals(tag); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java index cbcb12b0..fcd73e03 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/aop/GlobalExceptionHandler.java @@ -20,6 +20,7 @@ import com.zmops.iot.core.auth.exception.AuthException; import com.zmops.iot.core.auth.exception.PermissionException; import com.zmops.iot.core.auth.exception.enums.AuthExceptionEnum; +import com.zmops.iot.core.auth.model.LoginUser; import com.zmops.iot.model.exception.InvalidKaptchaException; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.exception.ZbxApiException; @@ -94,9 +95,9 @@ public ErrorResponseData handleError(MethodArgumentTypeMismatchException e) { public ErrorResponseData handleError(MethodArgumentNotValidException e) { log.warn("Method Argument Not Valid", e); BindingResult result = e.getBindingResult(); - FieldError error = result.getFieldError(); -// String message = String.format("%s:%s", error.getField(), error.getDefaultMessage()); - String message = String.format("%s:不能为空", error.getField()); + FieldError error = result.getFieldError(); + + String message = String.format("%s:%s", error.getField(), error.getDefaultMessage()); return new ErrorResponseData(400, message); } @@ -108,8 +109,8 @@ public ErrorResponseData handleError(MethodArgumentNotValidException e) { @ResponseBody public ErrorResponseData handleError(BindException e) { log.warn("Bind Exception", e); - FieldError error = e.getFieldError(); - String message = String.format("%s:%s", error.getField(), error.getDefaultMessage()); + FieldError error = e.getFieldError(); + String message = String.format("%s:不能为空", error.getField(), error.getDefaultMessage()); return new ErrorResponseData(400, message); } @@ -122,9 +123,9 @@ public ErrorResponseData handleError(BindException e) { public ErrorResponseData handleError(ConstraintViolationException e) { log.warn("Constraint Violation", e); Set> violations = e.getConstraintViolations(); - ConstraintViolation violation = violations.iterator().next(); - String path = ((PathImpl) violation.getPropertyPath()).getLeafNode().getName(); - String message = String.format("%s:%s", path, violation.getMessage()); + ConstraintViolation violation = violations.iterator().next(); + String path = ((PathImpl) violation.getPropertyPath()).getLeafNode().getName(); + String message = String.format("%s:%s", path, violation.getMessage()); return new ErrorResponseData(400, message); } @@ -157,7 +158,7 @@ public ErrorResponseData unAuth(AuthException e) { @ResponseStatus(HttpStatus.OK) @ResponseBody public ErrorResponseData permissionExpection(PermissionException e) { - LogManager.me().executeLog(LogTaskFactory.loginLog("username", "验证码错误", getIp())); + LogManager.me().executeLog(LogTaskFactory.loginLog("username", "验证码错误", getIp(), null)); return new ErrorResponseData(e.getCode(), e.getMessage()); } @@ -169,7 +170,7 @@ public ErrorResponseData permissionExpection(PermissionException e) { @ResponseBody public ErrorResponseData credentials(InvalidKaptchaException e) { String username = getRequest().getParameter("username"); - LogManager.me().executeLog(LogTaskFactory.loginLog(username, "验证码错误", getIp())); + LogManager.me().executeLog(LogTaskFactory.loginLog(username, "验证码错误", getIp(), null)); return new ErrorResponseData(AuthExceptionEnum.VALID_CODE_ERROR.getCode(), AuthExceptionEnum.VALID_CODE_ERROR.getMessage()); } @@ -182,7 +183,8 @@ public ErrorResponseData credentials(InvalidKaptchaException e) { public ErrorResponseData bussiness(ServiceException e) { log.error("业务异常:", e); if (LoginContextHolder.getContext().hasLogin()) { - LogManager.me().executeLog(LogTaskFactory.exceptionLog(LoginContextHolder.getContext().getUserId(), e)); + LoginUser user = LoginContextHolder.getContext().getUser(); + LogManager.me().executeLog(LogTaskFactory.exceptionLog(user.getId(), e, user.getTenantId())); } getRequest().setAttribute("tip", e.getMessage()); return new ErrorResponseData(e.getCode(), e.getMessage()); @@ -198,7 +200,8 @@ public ErrorResponseData bussiness(ServiceException e) { public ErrorResponseData bussiness(ZbxApiException e) { log.error("Zabbix接口调用出错:", e); if (LoginContextHolder.getContext().hasLogin()) { - LogManager.me().executeLog(LogTaskFactory.exceptionLog(LoginContextHolder.getContext().getUserId(), e)); + LoginUser user = LoginContextHolder.getContext().getUser(); + LogManager.me().executeLog(LogTaskFactory.exceptionLog(user.getId(), e, user.getTenantId())); } getRequest().setAttribute("tip", e.getMessage()); return new ErrorResponseData(e.getCode(), e.getMessage()); @@ -213,10 +216,28 @@ public ErrorResponseData bussiness(ZbxApiException e) { public ErrorResponseData notFount(Throwable e) { log.error("运行时异常:", e); if (LoginContextHolder.getContext().hasLogin()) { - LogManager.me().executeLog(LogTaskFactory.exceptionLog(LoginContextHolder.getContext().getUserId(), e)); + LoginUser user = LoginContextHolder.getContext().getUser(); + LogManager.me().executeLog(LogTaskFactory.exceptionLog(user.getId(), e, user.getTenantId())); } String message = String.format("服务器未知运行时异常: %s", e.getMessage()); getRequest().setAttribute("tip", message); return new ErrorResponseData(BizExceptionEnum.SERVER_ERROR.getCode(), message); } + + /** + * 拦截运行时异常 + */ + @ExceptionHandler(RuntimeException.class) + @ResponseStatus(HttpStatus.OK) + @ResponseBody + public ErrorResponseData runtime(RuntimeException e) { + log.error("运行时异常:", e); + if (LoginContextHolder.getContext().hasLogin()) { + LoginUser user = LoginContextHolder.getContext().getUser(); + LogManager.me().executeLog(LogTaskFactory.exceptionLog(user.getId(), e, user.getTenantId())); + } + String message = String.format("服务器运行异常请联系管理员"); + getRequest().setAttribute("tip", message); + return new ErrorResponseData(BizExceptionEnum.SERVER_ERROR.getCode(), message); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java index 54a54d2d..be5166c4 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/enums/BizExceptionEnum.java @@ -50,9 +50,12 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { CANT_DELETE_ADMIN(600, "不能删除超级管理员"), CANT_FREEZE_ADMIN(600, "不能冻结超级管理员"), CANT_CHANGE_ADMIN(600, "不能修改超级管理员角色"), + CANT_CHANGE_ADMIN_PWD(600, "不能修改超级管理员密码"), ROLE_HAS_EXIST(601, "角色已存在"), ROLE_HAS_BIND_USER(602, "角色绑定了用户,请先解除绑定!"), MENU_NOT_EXIST_OR_NO_PRERMISSION(603, "菜单不存在或无权授权此菜单"), + ROLE_NOT_EXIST(604, "角色不存在"), + CANNOT_MODIFY_OWNER_MENUS(605, "不能修改自己所在角色的菜单"), /** * 账户问题 @@ -132,21 +135,100 @@ public enum BizExceptionEnum implements AbstractBaseExceptionEnum { PRODUCT_TYPE_HAS_BIND(1304, "产品分类已绑定产品"), PRODUCT_TYPE_PID_NOT_EXIST(1305, "父节点不存在"), PRODUCT_TYPE_PID_ERR(1306, "父节点不可以是自已或子节点"), + PRODUCT_HAS_BIND_DEVICE(1307, "产品已绑定设备"), /** * 属性相关 */ PRODUCT_ATTR_KEY_EXISTS(1401, "该属性Key已存在"), + PRODUCT_ATTR_KEY_NOT_EXISTS(1404, "该属性Key不存在"), + PRODUCT_ATTR_DEPTED_NULL(1402, "依赖的属性不能为空"), + PRODUCT_ATTR_DEPTED_NOT_EXIST(1403, "依赖的属性不能为空"), + PRODUCT_ATTR_DEPTED(1404, "属性被依赖不能删除"), + PRODUCT_EVENT_HASDEPTED(1405, "属性已用于告警规则,不能删除"), /** * 设备相关 */ DEVICE_EXISTS(1501, "设备名称已存在"), + DEVICE_ID_EXISTS(1503, "设备ID已存在"), DEVICE_NOT_EXISTS(1502, "设备不存在"), + DEVICE_NAME_HAS_INCOREECT_CHARACTER(1504, "设备名称不能包含\\或\\/字符"), + + /** + * 服务相关 + */ + SERVICE_EXISTS(1601, "服务已存在"), + SERVICE_NOT_EXISTS(1602, "服务不存在"), + PRODUCT_EVENT_HAS_DEPTED(1605, "服务已用于告警规则或场景联动,不能删除"), + SERVICE_HAS_DUPLICATE(1606, "存在相同的动作服务"), + SERVICE_PARAM_NOT_EXISTS(1607, "服务未配置参数"), + + /** + * 触发规则相关 + */ + RULE_NOT_EXISTS(1701, "上下线规则不存在"), + RULE_EXISTS(1702, "上下线规则已存在"), + + EVENT_HAS_NOT_DEVICE(1703, "告警规则缺少关联产品或设备"), + EVENT_NOT_EXISTS(1704, "告警规则不存在"), + EVENT_EXPRESSION_NOT_EXISTS(1705, "告警表达式关联关系不存在"), + + EVENT_PRODUCT_CANNOT_DELETE(1706, "来自产品的触发器不能删除"), + SCENE_NOT_EXISTS(1707, "场景不存在"), + SCENE_EXPRESSION_NOT_EXISTS(1708, "场景触发条件不能为空"), + SCENE_EXISTED(1709, "场景名称已存在"), + + /** + * 任务相关 + * + * @param code + * @param message + */ + TASK_NOT_SCHEDULE_CONF(2201, "任务调度配置不能为空"), + TASK_SCHEDULE_CONF_NOT_MATCH(2202, "任务调度配置不正确"), /** * 租户相关的异常 */ + TENANT_NAME_EXISTS(1801, "租户名称已存在"), + + TENANT_ACCOUNT_EXISTS(1802, "租户账号已存在"), + TENANT_NOT_EXISTS(1803, "租户不存在"), + TENANT_HAS_RELATION_INFO(1804, "租户已关联用户组、设备组、产品类型"), + + /** + * 设备调试相关 + */ + ZBX_DEVICE_API_HASNOT_KEY(1901, "属性KEY和值不能为空"), + + /** + * 代理服务相关 + */ + PROXY_EXISTS(2001, "代理服务已存在"), + PROXY_NOT_EXISTS(2002, "代理服务不存在"), + + /** + * 协议相关 + */ + PROTOCOL_COMPONENT_EXISTS(2301, "协议组件名称已存在"), + PROTOCOL_COMPONENT_NOT_EXISTS(2302, "协议组件不存在"), + PROTOCOL_COMPONENT_HAS_BIND_GATEWAY(2303, "协议组件已绑定协议网关,不能删除"), + PROTOCOL_SERVICE_EXISTS(2304, "通信服务名称已存在"), + PROTOCOL_SERVICE_NOT_EXISTS(2305, "通信服务不存在"), + PROTOCOL_SERVICE_PORT_EXISTS(2310, "端口已存在"), + PROTOCOL_SERVICE_HAS_BIND_GATEWAY(2306, "通信服务已绑定协议网关,不能删除"), + PROTOCOL_GATEWAY_NOT_EXISTS(2307, "协议网关不存在"), + PROTOCOL_SERVICE_HAS_BIND_COMPONENT(2308, "通信服务已绑定协议协议组件"), + PROTOCOL_GATEWAY_HAS_NOT_COMPONENT(2309, "未选择协议组件"), + + /** + * 数据转换相关 + */ + ZBX_SERBER_NOT_CONFIG(2101, "Zabbix配置信息获取失败"), + ZBX_SERBER_EXPORT_PATH_NOT_CONFIG(2102, "Zabbix日志输出路径未配置"), + + AUTH_REQUEST_ERROR(400, "账号密码错误"); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/exception/page/GlobalController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/page/GlobalController.java new file mode 100644 index 00000000..6fce4466 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/exception/page/GlobalController.java @@ -0,0 +1,31 @@ +package com.zmops.iot.web.exception.page; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * 全局的控制器 + * + * @author fengshuonan + */ +@Controller +@RequestMapping("/global") +public class GlobalController { + + /** + * 跳转到404页面 + */ + @RequestMapping(path = "/error") + public String errorPage() { + return "/404"; + } + + /** + * 跳转到session超时页面 + */ + @RequestMapping(path = "/sessionError") + public String errorPageInfo(Model model) { + return "/index"; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java index 849309ec..4f16a274 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/BasicSettingsInit.java @@ -2,9 +2,8 @@ import com.alibaba.fastjson.JSON; import com.dtflys.forest.config.ForestConfiguration; -import com.zmops.zeus.driver.service.ZbxAction; import com.zmops.zeus.driver.service.ZbxHostGroup; -import com.zmops.zeus.driver.service.ZbxScript; +import com.zmops.zeus.driver.service.ZbxInitService; import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -27,23 +26,28 @@ public class BasicSettingsInit { private ZbxHostGroup zbxHostGroup; @Autowired - private ZbxScript zbxScript; - - @Autowired - private ZbxAction zbxAction; - - private String zeusServerIp; - private String zeusServerPort; - private String zbxApiToken; + private ZbxInitService zbxInitService; + public static String zbxApiToken; @PostConstruct public void init() { - zeusServerIp = configuration.getVariables().get("zeusServerIp").toString(); - zeusServerPort = configuration.getVariables().get("zeusServerPort").toString(); - zbxApiToken = configuration.getVariables().get("zbxApiToken").toString(); + zbxApiToken = configuration.getVariableValue("zbxApiToken").toString(); } + /** + * 查询全局主机组 + * + * @return String + */ + public String getGlobalHostGroup() { + String response = zbxHostGroup.getGlobalHostGroup(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); + if (null != ids && ids.size() > 0) { + return ids.get(0).get("groupid"); + } + return null; + } /** * 创建默认全局主机组 @@ -55,42 +59,80 @@ public String createGlobalHostGroup() { return JSON.parseObject(response, ZbxResponseIds.class).getGroupids()[0]; } - public String getGlobalHostGroup() { - String response = zbxHostGroup.getGlobalHostGroup(zbxApiToken); - List> ids = JSON.parseObject(response, List.class); + /** + * 查询只读权限用户组 + * + * @return String + */ + public String getCookieUserGroup() { + String response = zbxInitService.getCookieUserGroup(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); if (null != ids && ids.size() > 0) { - return ids.get(0).get("groupid"); + return ids.get(0).get("usrgrpid"); } return null; } - - public String createOfflineStatusScript() { - String response = zbxScript.createOfflineStatusScript(zbxApiToken, zeusServerIp, zeusServerPort); - return JSON.parseObject(response, ZbxResponseIds.class).getScriptids()[0]; + /** + * 创建 只读权限用户组 + * + * @param globalHostGroupId 全局主机组ID + * @return String + */ + public String createCookieUserGroup(String globalHostGroupId) { + String response = zbxInitService.createCookieUserGroup(globalHostGroupId, zbxApiToken); + return JSON.parseObject(response, ZbxResponseIds.class).getUsrgrpids()[0]; } - public String getOfflineStatusScript() { - String response = zbxScript.getOfflineStatusScript(zbxApiToken); - List> ids = JSON.parseObject(response, List.class); + /** + * 查询 只读权限用户 + * + * @return String + */ + public String getCookieUser() { + String response = zbxInitService.getCookieUser(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); if (null != ids && ids.size() > 0) { - return ids.get(0).get("scriptid"); + return ids.get(0).get("userid"); } return null; } - - public String createOfflineStatusAction(String scriptId, String groupId) { - String response = zbxAction.createOfflineStatusAction(zbxApiToken, scriptId, groupId); - return JSON.parseObject(response, ZbxResponseIds.class).getActionids()[0]; + /** + * 创建 只读权限用户 + * + * @param groupId 只读用户组ID + * @return String + */ + public String createCookieUser(String groupId, String roleId) { + String response = zbxInitService.createCookieUser(groupId, zbxApiToken, roleId); + return JSON.parseObject(response, ZbxResponseIds.class).getUserids()[0]; } + /** + * 查询 管理员用户角色 + * + * @return String + */ + public String getAdminRoleId() { + String response = zbxInitService.getAdminRole(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); + if (null != ids && ids.size() > 0) { + return ids.get(0).get("roleid"); + } + return null; + } - public String getOfflineStatusAction() { - String response = zbxAction.getOfflineStatusAction(zbxApiToken); - List> ids = JSON.parseObject(response, List.class); + /** + * 查询 访客用户角色 + * + * @return String + */ + public String getGuestRoleId() { + String response = zbxInitService.getGuestRole(zbxApiToken); + List> ids = JSON.parseObject(response, List.class); if (null != ids && ids.size() > 0) { - return ids.get(0).get("actionid"); + return ids.get(0).get("roleid"); } return null; } @@ -99,7 +141,7 @@ public String getOfflineStatusAction() { @Data static class ZbxResponseIds { String[] groupids; - String[] scriptids; - String[] actionids; + String[] userids; + String[] usrgrpids; } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java index db23e880..8423a30e 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/DeviceSatusScriptInit.java @@ -1,20 +1,12 @@ package com.zmops.iot.web.init; -import com.alibaba.fastjson.JSON; -import com.dtflys.forest.config.ForestConfiguration; import com.zmops.iot.domain.sys.SysConfig; -import com.zmops.iot.domain.sys.query.QSysConfig; -import com.zmops.zeus.driver.service.ZbxScript; import io.ebean.DB; -import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; -import javax.annotation.PostConstruct; - /** * @author nantian created at 2021/8/7 20:25 */ @@ -25,7 +17,7 @@ public class DeviceSatusScriptInit implements CommandLineRunner { public static final String GLOBAL_HOST_GROUP_CODE = "ZEUS_HOST_GROUP_ID"; - public static final String GLOBAL_ACTION_CODE = "ZEUS_ACTION_ID"; + public static final String GLOBAL_ADMIN_ROLE_CODE = "ZEUS_ADMIN_ROLE_ID"; @Autowired private BasicSettingsInit basicSettingsInit; @@ -38,22 +30,22 @@ public void run(String... args) throws Exception { if (groupId == null) { groupId = basicSettingsInit.createGlobalHostGroup(); } - DB.update(SysConfig.class).where().eq("code", GLOBAL_HOST_GROUP_CODE).asUpdate().set("value", groupId).update(); - // 第二步:创建全局回调脚本 - String scriptId = basicSettingsInit.getOfflineStatusScript(); - if (scriptId == null) { - scriptId = basicSettingsInit.createOfflineStatusScript(); + //判断系统参数是否存在 zbx管理员ID + String roleId = basicSettingsInit.getAdminRoleId(); + DB.update(SysConfig.class).where().eq("code", GLOBAL_ADMIN_ROLE_CODE).asUpdate().set("value", roleId).update(); + + //判断只读用户是否存在 不存在就创建一个 + String userId = basicSettingsInit.getCookieUser(); + if (userId == null) { + String userGroupId = basicSettingsInit.getCookieUserGroup(); + if (userGroupId == null) { + userGroupId = basicSettingsInit.createCookieUserGroup(groupId); + } + String guestRoleId = basicSettingsInit.getGuestRoleId(); + basicSettingsInit.createCookieUser(userGroupId, guestRoleId); } - String actionId = basicSettingsInit.getOfflineStatusAction(); - if (actionId == null) { - actionId = basicSettingsInit.createOfflineStatusAction(scriptId, groupId); - } - - DB.update(SysConfig.class).where().eq("code", GLOBAL_ACTION_CODE).asUpdate().set("value", actionId).update(); - - log.info("全局主机组ID:{},在线触发动作ID:{}", groupId, actionId); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/init/SysConfigInit.java b/zeus-webapp/src/main/java/com/zmops/iot/web/init/SysConfigInit.java index e62037af..e45c468a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/init/SysConfigInit.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/init/SysConfigInit.java @@ -20,6 +20,11 @@ public class SysConfigInit implements CommandLineRunner { @Override public void run(String... args) { + initConfigConst(); + + } + + public void initConfigConst(){ //初始化所有的常量 List list = DB.find(SysConfig.class).findList(); @@ -30,6 +35,5 @@ public void run(String... args) { log.info("初始化常量" + list.size() + "条!"); } - } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/log/aop/LogAop.java b/zeus-webapp/src/main/java/com/zmops/iot/web/log/aop/LogAop.java index 52d6a862..b72db969 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/log/aop/LogAop.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/log/aop/LogAop.java @@ -65,15 +65,15 @@ public Object recordSysLog(ProceedingJoinPoint point) throws Throwable { private void handle(ProceedingJoinPoint point) throws Exception { //获取拦截的方法名 - Signature sig = point.getSignature(); + Signature sig = point.getSignature(); MethodSignature msig = null; if (!(sig instanceof MethodSignature)) { throw new IllegalArgumentException("该注解只能用于方法"); } msig = (MethodSignature) sig; - Object target = point.getTarget(); + Object target = point.getTarget(); Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes()); - String methodName = currentMethod.getName(); + String methodName = currentMethod.getName(); //如果当前用户未登录,不做日志 LoginUser user = LoginContextHolder.getContext().getUser(); @@ -82,14 +82,14 @@ private void handle(ProceedingJoinPoint point) throws Exception { } //获取拦截方法的参数 - String className = point.getTarget().getClass().getName(); - Object[] params = point.getArgs(); + String className = point.getTarget().getClass().getName(); + Object[] params = point.getArgs(); //获取操作名称 - BussinessLog annotation = currentMethod.getAnnotation(BussinessLog.class); - String bussinessName = annotation.value(); - String key = annotation.key(); - Class dictClass = annotation.dict(); + BussinessLog annotation = currentMethod.getAnnotation(BussinessLog.class); + String bussinessName = annotation.value(); + String key = annotation.key(); + Class dictClass = annotation.dict(); StringBuilder sb = new StringBuilder(); for (Object param : params) { @@ -109,6 +109,6 @@ private void handle(ProceedingJoinPoint point) throws Exception { // msg = Contrast.parseMutiKey(dictMap, key, parameters); // } - LogManager.me().executeLog(LogTaskFactory.bussinessLog(user.getId(), bussinessName, className, methodName, msg)); + LogManager.me().executeLog(LogTaskFactory.bussinessLog(user.getId(), bussinessName, className, methodName, msg,user.getTenantId())); } } \ No newline at end of file diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/log/factory/LogFactory.java b/zeus-webapp/src/main/java/com/zmops/iot/web/log/factory/LogFactory.java index ed93b793..add62cef 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/log/factory/LogFactory.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/log/factory/LogFactory.java @@ -34,7 +34,7 @@ public class LogFactory { * 创建操作日志 */ public static SysOperationLog createOperationLog(LogType logType, Long userId, String bussinessName, - String clazzName, String methodName, String msg, LogSucceed succeed) { + String clazzName, String methodName, String msg, LogSucceed succeed,Long tenantId) { SysOperationLog operationLog = new SysOperationLog(); operationLog.setLogType(logType.getMessage()); operationLog.setLogName(bussinessName); @@ -44,13 +44,14 @@ public static SysOperationLog createOperationLog(LogType logType, Long userId, S operationLog.setCreateTime(LocalDateTime.now()); operationLog.setSucceed(succeed.getMessage()); operationLog.setMessage(msg); + operationLog.setTenantId(tenantId); return operationLog; } /** * 创建登录日志 */ - public static SysLoginLog createLoginLog(LogType logType, Long userId, String msg, String ip) { + public static SysLoginLog createLoginLog(LogType logType, Long userId, String msg, String ip,Long tenantId) { SysLoginLog loginLog = new SysLoginLog(); loginLog.setLogName(logType.getMessage()); loginLog.setUserId(userId); @@ -58,6 +59,7 @@ public static SysLoginLog createLoginLog(LogType logType, Long userId, String ms loginLog.setSucceed(LogSucceed.SUCCESS.getMessage()); loginLog.setIpAddress(ip); loginLog.setMessage(msg); + loginLog.setTenantId(tenantId); return loginLog; } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/log/factory/LogTaskFactory.java b/zeus-webapp/src/main/java/com/zmops/iot/web/log/factory/LogTaskFactory.java index 898ba8ff..9062f489 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/log/factory/LogTaskFactory.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/log/factory/LogTaskFactory.java @@ -16,7 +16,6 @@ package com.zmops.iot.web.log.factory; -import cn.hutool.core.util.IdUtil; import com.zmops.iot.domain.sys.SysLoginLog; import com.zmops.iot.domain.sys.SysOperationLog; import com.zmops.iot.util.ToolUtil; @@ -35,12 +34,12 @@ @Slf4j public class LogTaskFactory { - public static TimerTask loginLog(final Long userId, final String ip) { + public static TimerTask loginLog(final Long userId, final String ip,Long tenantId) { return new TimerTask() { @Override public void run() { try { - SysLoginLog loginLog = LogFactory.createLoginLog(LogType.LOGIN, userId, null, ip); + SysLoginLog loginLog = LogFactory.createLoginLog(LogType.LOGIN, userId, null, ip,tenantId); DB.insert(loginLog); } catch (Exception e) { log.error("创建登录日志异常!", e); @@ -49,12 +48,12 @@ public void run() { }; } - public static TimerTask loginLog(final String username, final String msg, final String ip) { + public static TimerTask loginLog(final String username, final String msg, final String ip,Long tenantId) { return new TimerTask() { @Override public void run() { SysLoginLog loginLog = LogFactory.createLoginLog( - LogType.LOGIN_FAIL, null, "账号:" + username + "," + msg, ip); + LogType.LOGIN_FAIL, null, "账号:" + username + "," + msg, ip,tenantId); try { DB.insert(loginLog); } catch (Exception e) { @@ -64,11 +63,11 @@ public void run() { }; } - public static TimerTask exitLog(final Long userId, final String ip) { + public static TimerTask exitLog(final Long userId, final String ip,Long tenantId) { return new TimerTask() { @Override public void run() { - SysLoginLog loginLog = LogFactory.createLoginLog(LogType.EXIT, userId, null, ip); + SysLoginLog loginLog = LogFactory.createLoginLog(LogType.EXIT, userId, null, ip,tenantId); try { DB.insert(loginLog); } catch (Exception e) { @@ -78,12 +77,12 @@ public void run() { }; } - public static TimerTask bussinessLog(final Long userId, final String bussinessName, final String clazzName, final String methodName, final String msg) { + public static TimerTask bussinessLog(final Long userId, final String bussinessName, final String clazzName, final String methodName, final String msg,Long tenantId) { return new TimerTask() { @Override public void run() { SysOperationLog operationLog = LogFactory.createOperationLog( - LogType.BUSSINESS, userId, bussinessName, clazzName, methodName, msg, LogSucceed.SUCCESS); + LogType.BUSSINESS, userId, bussinessName, clazzName, methodName, msg, LogSucceed.SUCCESS,tenantId); try { DB.insert(operationLog); } catch (Exception e) { @@ -93,13 +92,13 @@ public void run() { }; } - public static TimerTask exceptionLog(final Long userId, final Throwable exception) { + public static TimerTask exceptionLog(final Long userId, final Throwable exception,Long tenantId) { return new TimerTask() { @Override public void run() { String msg = ToolUtil.getExceptionMsg(exception); SysOperationLog operationLog = LogFactory.createOperationLog( - LogType.EXCEPTION, userId, "", null, null, msg, LogSucceed.FAIL); + LogType.EXCEPTION, userId, "", null, null, msg, LogSucceed.FAIL,tenantId); try { DB.insert(operationLog); } catch (Exception e) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java new file mode 100644 index 00000000..acb30692 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/controller/MacroController.java @@ -0,0 +1,169 @@ +package com.zmops.iot.web.macro.controller; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.query.QProduct; +import com.zmops.iot.enums.InheritStatus; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.macro.dto.UserMacro; +import com.zmops.iot.web.macro.service.MacroService; +import com.zmops.zeus.driver.service.ZbxHost; +import com.zmops.zeus.driver.service.ZbxMacro; +import lombok.Getter; +import lombok.Setter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author nantian created at 2021/9/18 10:53 + */ + +@RequestMapping("/macro") +@RestController +public class MacroController { + + @Autowired + private ZbxMacro zbxMacro; + + @Autowired + private ZbxHost zbxHost; + + @Autowired + private MacroService macroService; + + /** + * 创建 变量 + * + * @return ResponseData + */ + @RequestMapping("/create") + public ResponseData createUserMacro(@Validated(BaseEntity.Create.class) @RequestBody UserMacro userMacro) { + // 获取 host id + String zbxId = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(userMacro.getDeviceId()).findSingleAttribute(); + if (ToolUtil.isEmpty(zbxId)) { + zbxId = new QProduct().select(QProduct.alias().zbxId).productId.eq(Long.parseLong(userMacro.getDeviceId())).findSingleAttribute(); + } + + if (ToolUtil.isEmpty(zbxId)) { + throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + } + + return ResponseData.success(macroService.createMacro(userMacro, zbxId)); + } + + /** + * 变量更新 + * + * @param userMacro + * @return ResponseData + */ + @RequestMapping("/update") + public ResponseData updateUserMacro(@Validated(BaseEntity.Update.class) @RequestBody UserMacro userMacro) { + if (InheritStatus.YES.getCode().equals(userMacro.getInherit())) { + String zbxId = new QDevice().select(QDevice.alias().zbxId).deviceId.eq(userMacro.getDeviceId()).findSingleAttribute(); + if (ToolUtil.isEmpty(zbxId)) { + throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + } + macroService.createMacro(userMacro, zbxId); + } else { + zbxMacro.macroUpdate(userMacro.getHostmacroid(), userMacro.getMacro(), userMacro.getValue(), userMacro.getDescription()); + } + return ResponseData.success(); + } + + /** + * 变量列表 + * + * @param userMacro + * @return ResponseData + */ + @RequestMapping("/list") + public ResponseData getUserMacro(@Validated(BaseEntity.Get.class) @RequestBody UserMacro userMacro) { + + // 获取 模板ID 或者 设备ID + String zbxId = ""; + Device device = new QDevice().deviceId.eq(userMacro.getDeviceId()).findOne(); + if (device != null) { + zbxId = device.getZbxId(); + } else { + zbxId = new QProduct().select(QProduct.alias().zbxId).productId.eq(Long.parseLong(userMacro.getDeviceId())).findSingleAttribute(); + } + + if (ToolUtil.isEmpty(zbxId)) { + throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + } + + // 模板ID + if (device == null) { + List tempMacroList = JSONObject.parseArray(zbxMacro.macroGet(zbxId + ""), UserMacro.class); + return ResponseData.success(tempMacroList); + } + + // 模板IDs + List tempListObject = JSON.parseArray(zbxHost.hostTempidGet(userMacro.getDeviceId()), HostQueryTempObject.class); + + TemplateIdObject tempId = tempListObject.get(0).getParentTemplates().get(0); + if (ToolUtil.isNotEmpty(tempId)) { + // 模板宏 + List tempMacroList = JSONObject.parseArray(zbxMacro.macroGet(tempId.getTemplateid()), UserMacro.class); + tempMacroList.forEach(macro -> { + macro.setInherit("1"); + macro.setInheritName("否"); + }); + // 主机宏 + List hostMacroList = JSONObject.parseArray(zbxMacro.macroGet(zbxId + ""), UserMacro.class); + Map hostMacroMap = hostMacroList.parallelStream().collect(Collectors.toMap(UserMacro::getMacro, o -> o, (a, b) -> a)); + //过滤模板宏中相同的KEY + tempMacroList.removeIf(macro -> null != hostMacroMap.get(macro.getMacro())); + + tempMacroList.addAll(hostMacroList); + + return ResponseData.success(tempMacroList); + } + + return ResponseData.error(ResponseData.DEFAULT_ERROR_CODE, ""); + } + + + /** + * 变量删除 + * + * @param userMacro + * @return ResponseData + */ + @RequestMapping("/delete") + public ResponseData deleteUserMacro(@Validated(BaseEntity.Delete.class) @RequestBody UserMacro userMacro) { + zbxMacro.macroDelete(Collections.singletonList(userMacro.getHostmacroid())); + return ResponseData.success(); + } + + + @Getter + @Setter + static class HostQueryTempObject { + private String hostid; + private List parentTemplates; + } + + @Getter + @Setter + static class TemplateIdObject { + private String templateid; + private String name; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java new file mode 100644 index 00000000..836d1c29 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/dto/UserMacro.java @@ -0,0 +1,32 @@ +package com.zmops.iot.web.macro.dto; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotBlank; + +/** + * @author nantian created at 2021/9/18 11:47 + */ + +@Getter +@Setter +public class UserMacro { + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class, BaseEntity.Get.class}) + private String deviceId; // 产品ID 或者 设备ID + + private String macro; + + private String value; + + private String description; + + @NotBlank(groups = BaseEntity.Update.class) + private String inherit = "0"; + private String inheritName = "否"; + + @NotBlank(groups = {BaseEntity.Delete.class, BaseEntity.Update.class}) + private String hostmacroid; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/macro/service/MacroService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/service/MacroService.java new file mode 100644 index 00000000..d4cc8d0d --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/macro/service/MacroService.java @@ -0,0 +1,36 @@ +package com.zmops.iot.web.macro.service; + +import com.alibaba.fastjson.JSON; +import com.zmops.iot.web.macro.dto.UserMacro; +import com.zmops.zeus.driver.service.ZbxMacro; +import lombok.Getter; +import lombok.Setter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Locale; + +/** + * @author yefei + **/ +@Service +public class MacroService { + + @Autowired + ZbxMacro zbxMacro; + + public Long createMacro(UserMacro userMacro, String zbxId) { + + // 创建宏 + String res = zbxMacro.macroCreate(zbxId, userMacro.getMacro().toUpperCase(Locale.ROOT), userMacro.getValue(), userMacro.getDescription()); + + Macroids macroids = JSON.parseObject(res, Macroids.class); + return macroids.getHostmacroids()[0]; + } + + @Getter + @Setter + static class Macroids { + private Long[] hostmacroids; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java new file mode 100644 index 00000000..3f65d972 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductAttributeEventController.java @@ -0,0 +1,149 @@ +package com.zmops.iot.web.product.controller; + +import cn.hutool.core.util.IdUtil; +import com.alibaba.fastjson.JSON; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.ProductAttributeEvent; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttributeEvent; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.iot.web.product.dto.ProductAttrDto; +import com.zmops.iot.web.product.dto.param.ProductAttrParam; +import com.zmops.iot.web.product.service.ProductAttributeEventService; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author nantian created at 2021/8/3 19:44 + *

+ * 产品 属性事件 + */ + +@RestController +@RequestMapping("/product/attribute/event") +public class ProductAttributeEventController { + + @Autowired + private ProductAttributeEventService productAttributeEventService; + + //依赖属性类型 + private static final String ATTR_SOURCE_DEPEND = "18"; + + /** + * 产品属性事件 分页列表 + * + * @return ResponseData + */ + @RequestMapping("/getAttrEventByPage") + public Pager prodAttributeEventList(@RequestBody ProductAttrParam productAttr) { + return productAttributeEventService.prodAttributeEventList(productAttr); + } + + /** + * 属性事件 列表 + * + * @return ResponseData + */ + @RequestMapping("/list") + public ResponseData list(@RequestBody ProductAttrParam productAttr) { + return ResponseData.success(productAttributeEventService.list(productAttr)); + } + + /** + * 属性事件 详情 + * + * @return ResponseData + */ + @RequestMapping("/detail") + public ResponseData detail(@RequestParam(value = "attrId") Long attrId) { + return ResponseData.success(productAttributeEventService.detail(attrId)); + } + + /** + * 创建 产品属性事件 + * + * @return ResponseData + */ + @RequestMapping("/create") + public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity.Create.class) ProductAttr productAttr) { + int i = new QProductAttribute().productId.eq(productAttr.getProductId()).key.eq(productAttr.getKey()).findCount(); + if (i > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); + } + + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + if (productAttr.getDepAttrId() == null) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); + } + ProductAttributeEvent productAttributeEvent = new QProductAttributeEvent().attrId.eq(productAttr.getDepAttrId()).findOne(); + if (null == productAttributeEvent) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); + } + productAttr.setMasterItemId(productAttributeEvent.getZbxId()); + } + + Long attrId = IdUtil.getSnowflake().nextId(); + productAttr.setAttrId(attrId); + + String response = productAttributeEventService.createTrapperItem(productAttr); + String zbxId = JSON.parseObject(response, TemplateIds.class).getItemids()[0]; + + productAttributeEventService.createProductAttr(productAttr, zbxId); + + return ResponseData.success(productAttr); + } + + /** + * 修改 产品属性事件 + * + * @return ResponseData + */ + @RequestMapping("/update") + public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity.Update.class) ProductAttr productAttr) { + int i = new QProductAttribute().productId.eq(productAttr.getProductId()).key.eq(productAttr.getKey()) + .attrId.ne(productAttr.getAttrId()).findCount(); + if (i > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); + } + + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + if (productAttr.getDepAttrId() == null) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); + } + ProductAttributeEvent productAttributeEvent = new QProductAttributeEvent().attrId.eq(productAttr.getDepAttrId()).findOne(); + if (null == productAttributeEvent) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); + } + productAttr.setMasterItemId(productAttributeEvent.getZbxId()); + } + + return ResponseData.success(productAttributeEventService.updateTrapperItem(productAttr)); + } + + /** + * 删除 产品属性事件 + * + * @return ResponseData + */ + @RequestMapping("/delete") + public ResponseData prodModelAttributeDelete(@RequestBody @Validated(BaseEntity.Delete.class) ProductAttr productAttr) { + + productAttributeEventService.deleteTrapperItem(productAttr); + return ResponseData.success(); + } + + @Data + static class TemplateIds { + private String[] itemids; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java index 9f08519c..8dc72d97 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductController.java @@ -4,13 +4,15 @@ import com.alibaba.fastjson.JSON; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.device.Tag; +import com.zmops.iot.domain.device.query.QDevice; import com.zmops.iot.domain.device.query.QTag; import com.zmops.iot.domain.product.Product; -import com.zmops.iot.domain.product.query.QProduct; +import com.zmops.iot.domain.product.query.*; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductBasicInfo; import com.zmops.iot.web.product.dto.ProductDto; @@ -44,6 +46,7 @@ public class ProductController { /** * 产品分页列表 */ + @Permission(code = "product_list") @PostMapping("/getProductByPage") public Pager getProductByPage(@RequestBody ProductBasicInfo prodBasicInfo) { return productService.getProductByPage(prodBasicInfo); @@ -52,6 +55,7 @@ public Pager getProductByPage(@RequestBody ProductBasicInfo prodBasi /** * 产品列表 */ + @Permission(code = "product_list") @PostMapping("/list") public ResponseData prodList(@RequestBody ProductBasicInfo prodBasicInfo) { return ResponseData.success(productService.prodList(prodBasicInfo)); @@ -60,24 +64,27 @@ public ResponseData prodList(@RequestBody ProductBasicInfo prodBasicInfo) { /** * 产品详情 */ + @Permission(code = "product_detail") @GetMapping("/detail") - public ResponseData prodDetail(@RequestParam("prodId") Long prodId) { + public ResponseData prodDetail(@RequestParam("productId") Long prodId) { return ResponseData.success(productService.prodDetail(prodId)); } /** * 产品标签列表 */ - @GetMapping("/prodTag/list") - public ResponseData prodTagList(@RequestParam("prodId") Long prodId) { + @Permission(code = "product") + @GetMapping("/tag/list") + public ResponseData prodTagList(@RequestParam("productId") String prodId) { return ResponseData.success(productService.prodTagList(prodId)); } /** * 值映射列表 */ + @Permission(code = "product") @GetMapping("/valueMap/list") - public ResponseData valueMapList(@RequestParam("prodId") Long prodId) { + public ResponseData valueMapList(@RequestParam("productId") Long prodId) { return ResponseData.success(productService.valueMapList(prodId)); } @@ -87,6 +94,7 @@ public ResponseData valueMapList(@RequestParam("prodId") Long prodId) { * @param prodBasicInfo 产品基本信息 * @return */ + @Permission(code = "product_add") @PostMapping("/create") public ResponseData prodCreate(@RequestBody @Validated(value = BaseEntity.Create.class) ProductBasicInfo prodBasicInfo) { @@ -96,13 +104,14 @@ public ResponseData prodCreate(@RequestBody @Validated(value = BaseEntity.Create } // 第一步:创建模板 - Long prodId = IdUtil.getSnowflake().nextId(); + Long prodId = IdUtil.getSnowflake().nextId(); String result = productService.zbxTemplateCreate(prodId + ""); // 第二步:创建产品 - String zbxId = JSON.parseObject(result, TemplateIds.class).getTemplateids()[0]; - Product prod = productService.createProduct(zbxId, prodId, prodBasicInfo); - return ResponseData.success(prod); + String zbxId = JSON.parseObject(result, TemplateIds.class).getTemplateids()[0]; + productService.createProduct(zbxId, prodId, prodBasicInfo); + prodBasicInfo.setProductId(prodId); + return ResponseData.success(prodBasicInfo); } @@ -111,6 +120,7 @@ public ResponseData prodCreate(@RequestBody @Validated(value = BaseEntity.Create * * @return */ + @Permission(code = "product_update") @PostMapping("/update") public ResponseData prodUpdate(@RequestBody @Validated(value = BaseEntity.Update.class) ProductBasicInfo prodBasicInfo) { @@ -123,7 +133,7 @@ public ResponseData prodUpdate(@RequestBody @Validated(value = BaseEntity.Update Product product = productService.updateProduct(prodBasicInfo); - return ResponseData.success(product); + return ResponseData.success(prodBasicInfo); } @@ -133,25 +143,48 @@ public ResponseData prodUpdate(@RequestBody @Validated(value = BaseEntity.Update * @param prodBasicInfo 产品基础信息 * @return */ + @Permission(code = "product_delete") @PostMapping("/delete") public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete.class) ProductBasicInfo prodBasicInfo) { - //第一步:验证产品下 是否有设备存在 Product product = new QProduct().productId.eq(prodBasicInfo.getProductId()).findOne(); if (null == product) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } - // TODO 判断该产品下 是否有设备 + int deviceNum = new QDevice().productId.eq(prodBasicInfo.getProductId()).findCount(); + if (deviceNum > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_HAS_BIND_DEVICE); + } //第二步:删除Zabbix对应的模板 - String response = productService.zbxTemplateDelete(product.getZbxId() + ""); - String templateId = JSON.parseObject(response, TemplateIds.class).getTemplateids()[0]; - if (templateId.equals(product.getZbxId())) { - log.info("产品模板删除成功,ID:{}", templateId); + productService.zbxTemplateDelete(product.getZbxId() + ""); + + //删除关联信息 + List statusFunctionRuleIds = new QProductStatusFunctionRelation().select(QProductStatusFunctionRelation.alias().ruleId).relationId.eq(product.getProductId() + "").findSingleAttributeList(); + if (ToolUtil.isNotEmpty(statusFunctionRuleIds)) { + new QProductStatusFunction().ruleId.in(statusFunctionRuleIds).delete(); + new QProductStatusFunctionRelation().relationId.eq(product.getProductId() + "").delete(); + } + + List serviceIds = new QProductServiceRelation().select(QProductServiceRelation.alias().serviceId).relationId.eq(product.getProductId() + "").findSingleAttributeList(); + if (ToolUtil.isNotEmpty(serviceIds)) { + new QProductService().id.in(serviceIds).delete(); + new QProductServiceParam().serviceId.in(serviceIds).delete(); + new QProductServiceRelation().relationId.eq(product.getProductId() + "").delete(); + } + + List eventIds = new QProductEventRelation().select(QProductEventRelation.alias().eventRuleId).relationId.eq(product.getProductId() + "").findSingleAttributeList(); + if (ToolUtil.isNotEmpty(eventIds)) { + new QProductEvent().eventRuleId.in(eventIds).delete(); + new QProductEventExpression().eventRuleId.in(eventIds).delete(); + new QProductEventService().eventRuleId.in(eventIds).delete(); + new QProductEventRelation().relationId.eq(product.getProductId() + "").delete(); } + new QProductAttribute().productId.eq(product.getProductId() + "").delete(); + new QProductAttributeEvent().productId.eq(product.getProductId() + "").delete(); //第三步:删除产品 boolean del = product.delete(); @@ -164,26 +197,31 @@ public ResponseData prodDelete(@RequestBody @Validated(value = BaseEntity.Delete * * @return */ + @Permission(code = "product") @PostMapping("/tag/update") public ResponseData prodTagCreate(@RequestBody @Valid ProductTag productTag) { - Long productId = productTag.getProductId(); - Product product = new QProduct().productId.eq(productId).findOne(); + String productId = productTag.getProductId(); + Product product = new QProduct().productId.eq(Long.parseLong(productId)).findOne(); if (null == product) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } + new QTag().sid.eq(productTag.getProductId()).delete(); + List tags = new ArrayList<>(); for (ProductTag.Tag tag : productTag.getProductTag()) { - tags.add( - Tag.builder().sid(productTag.getProductId()) - .tag(tag.getTag()).value(tag.getValue()) - .build()); + tags.add(Tag.builder() + .sid(productTag.getProductId()) + .tag(tag.getTag()).value(tag.getValue()) + .build() + ); } + DB.saveAll(tags); - String response = productService.updateTemplateTags(product.getZbxId(), productTag); + String response = productService.updateTemplateTags(product.getZbxId(), productTag); String templateId = JSON.parseObject(response, TemplateIds.class).getTemplateids()[0]; if (templateId.equals(product.getZbxId())) { log.info("产品标签修改成功,ID:{}", templateId); @@ -199,10 +237,11 @@ public ResponseData prodTagCreate(@RequestBody @Valid ProductTag productTag) { * @param valueMap * @return */ - @PostMapping("/valuemap/update") + @Permission(code = "product") + @PostMapping("/valueMap/update") public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create.class) ValueMap valueMap) { - Product product = new QProduct().productId.eq(valueMap.getProductId()).findOne(); + Product product = new QProduct().productId.eq(Long.parseLong(valueMap.getProductId())).findOne(); if (null == product) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } @@ -224,9 +263,10 @@ public ResponseData prodValueMapCreate(@RequestBody @Validated(BaseEntity.Create * @param valueMap * @return */ - @PostMapping("/valuemap/delete") + @Permission(code = "product") + @PostMapping("/valueMap/delete") public ResponseData prodValueMapDelete(@RequestBody @Validated(BaseEntity.Delete.class) ValueMap valueMap) { - String response = productService.valueMapDelete(valueMap.getValuemapid()); + String response = productService.valueMapDelete(valueMap.getValuemapid()); String valuemapid = JSON.parseObject(response, TemplateIds.class).getValuemapids()[0]; return ResponseData.success(valuemapid); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java index 96e1974b..eccfe510 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductEventTriggerController.java @@ -1,16 +1,253 @@ package com.zmops.iot.web.product.controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import cn.hutool.core.util.IdUtil; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.domain.product.query.QProductEventExpression; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.enums.InheritStatus; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductEventTriggerCreateEvent; +import com.zmops.iot.web.event.applicationEvent.ProductEventTriggerUpdateEvent; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductEventDto; +import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.iot.web.product.dto.param.EventParm; +import com.zmops.iot.web.product.service.ProductEventRuleService; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import io.ebean.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; /** - * @author nantian created at 2021/8/7 11:58 + * @author nantian created at 2021/8/26 23:04 *

- * 配置告警规则 + * 产品 物模型功能 【告警规则】 */ + @RestController -@RequestMapping("/product/trigger/event") +@RequestMapping("/product/event/trigger") public class ProductEventTriggerController { - + + @Autowired + private ProductEventRuleService productEventRuleService; + + @Autowired + private ZbxTrigger zbxTrigger; + + private static final String ALARM_TAG_NAME = "__alarm__"; + private static final String EXECUTE_TAG_NAME = "__execute__"; + + @Autowired + ApplicationEventPublisher publisher; + + /** + * 触发器 分页列表 + * + * @param eventParm + * @return + */ + @PostMapping("/getEventByPage") + public Pager getEventByPage(@Validated @RequestBody EventParm eventParm) { + return productEventRuleService.getEventByPage(eventParm); + } + + /** + * 触发器 详情 + * + * @param eventRuleId + * @return + */ + @GetMapping("/detail") + public ResponseData detail(@RequestParam("eventRuleId") long eventRuleId, @RequestParam("prodId") String prodId) { + ProductEvent productEvent = new QProductEvent().eventRuleId.eq(eventRuleId).findOne(); + if (null == productEvent) { + throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); + } + return ResponseData.success(productEventRuleService.detail(productEvent, eventRuleId, prodId)); + } + + /** + * 创建 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/create") + public ResponseData createProductEventRule(@RequestBody @Validated(value = BaseEntity.Create.class) + ProductEventRule eventRule) { + + Long eventRuleId = IdUtil.getSnowflake().nextId(); // ruleId, trigger name + eventRule.setEventRuleId(eventRuleId); + productEventRuleService.createProductEventRule(eventRule); + + //step 1: 先创建 zbx 触发器 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + + //step 2: zbx 保存触发器 + String[] triggerIds = productEventRuleService.createZbxTrigger(eventRuleId + "", expression, eventRule.getEventLevel()); + + //step 4: zbx 触发器创建 Tag + Map tags = new ConcurrentHashMap<>(3); + if (ToolUtil.isNotEmpty(eventRule.getTags())) { + tags = eventRule.getTags().stream() + .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); + } + if (!tags.containsKey(ALARM_TAG_NAME)) { + tags.put(ALARM_TAG_NAME, "{HOST.HOST}"); + } + if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { + tags.put(EXECUTE_TAG_NAME, eventRuleId + ""); + } +// Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); +// if (any.isPresent()) { +// tags.put(EVENT_TAG_NAME, eventRuleId + ""); +// } + for (String triggerId : triggerIds) { + zbxTrigger.triggerTagCreate(triggerId, tags); + } + + //step 5: 更新 zbxId + productEventRuleService.updateProductEventRuleZbxId(eventRuleId, triggerIds); + + //step 6: 同步到产品下的设备 + publisher.publishEvent(new ProductEventTriggerCreateEvent(this,eventRule)); + + + // 返回触发器ID + return ResponseData.success(eventRuleId); + } + + /** + * 修改 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/update") + public ResponseData updateProductEventRule(@RequestBody @Validated(value = BaseEntity.Update.class) ProductEventRule eventRule) { + + //step 1: 更新所有服务 + productEventRuleService.updateProductEventRule(eventRule.getEventRuleId(), eventRule); + + //step 2: 更新zbx表达式 + String expression = eventRule.getExpList() + .stream().map(Object::toString).collect(Collectors.joining(" " + eventRule.getExpLogic() + " ")); + + ProductEvent event = new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).findOne(); + if (event == null) { + throw new ServiceException(BizExceptionEnum.EVENT_NOT_EXISTS); + } + + List list = new QProductEventRelation().eventRuleId.eq(event.getEventRuleId()).inherit.eq(InheritStatus.NO.getCode()).findList(); + if (list.isEmpty()) { + throw new ServiceException(BizExceptionEnum.EVENT_EXPRESSION_NOT_EXISTS); + } + + zbxTrigger.triggerUpdate(list.get(0).getZbxId(), expression, eventRule.getEventLevel()); + + + //step 3: zbx 触发器创建 Tag + Map tags = eventRule.getTags().stream() + .collect(Collectors.toMap(ProductEventRule.Tag::getTag, ProductEventRule.Tag::getValue, (k1, k2) -> k2)); + + if (ToolUtil.isEmpty(tags)) { + tags = new HashMap<>(2); + } + if (!tags.containsKey(ALARM_TAG_NAME)) { + tags.put(ALARM_TAG_NAME, "{HOST.HOST}"); + } +// if (ToolUtil.isNotEmpty(eventRule.getDeviceServices()) && !tags.containsKey(EXECUTE_TAG_NAME)) { +// tags.put(EXECUTE_TAG_NAME, eventRule.getEventRuleId() + ""); +// } +// Optional any = eventRule.getExpList().parallelStream().filter(o -> EVENT_TYPE_NAME.equals(o.getProductAttrType())).findAny(); +// if (any.isPresent()) { +// tags.put(EVENT_TAG_NAME, eventRule.getEventRuleId() + ""); +// } + + zbxTrigger.triggerTagCreate(list.get(0).getZbxId(), tags); + + //step 4: 同步到产品下的设备 + publisher.publishEvent(new ProductEventTriggerUpdateEvent(this,eventRule)); + + + return ResponseData.success(eventRule.getEventRuleId()); + } + + /** + * 修改 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @PostMapping("/status") + public ResponseData updateProductEventStatus(@RequestBody @Validated(value = BaseEntity.Status.class) ProductEventRule eventRule) { + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).asUpdate().set("status", eventRule.getStatus()).update(); + + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).inherit.eq("0").findOne(); + + if (null != productEventRelation && null != productEventRelation.getZbxId()) { + zbxTrigger.triggerStatusUpdate(productEventRelation.getZbxId(), eventRule.getStatus().equals(CommonStatus.ENABLE.getCode()) ? "0" : "1"); + } + + return ResponseData.success(); + } + + /** + * 删除 触发器 + * + * @param eventRule 触发器规则 + * @return 触发器ID + */ + @Transactional + @PostMapping("/delete") + public ResponseData deleteProductEventRule(@RequestBody @Validated(value = BaseEntity.Delete.class) + ProductEventRule eventRule) { + ProductEventRelation productEventRelation = new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).inherit.eq("0").findOne(); + if (null == productEventRelation) { + return ResponseData.success(); + } + //step 01:删除 zbx触发器 + String s = zbxTrigger.triggerGet(productEventRelation.getZbxId()); + List triggers = JSONObject.parseArray(s, ProductEventRuleService.Triggers.class); + if (ToolUtil.isNotEmpty(triggers)) { + zbxTrigger.triggerDelete(productEventRelation.getZbxId()); + } + + //step 1:删除 与产品 设备的关联 + new QProductEventRelation().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 2:删除 关联的执行服务 + new QProductEventService().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 3:删除 关联的表达式 + new QProductEventExpression().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + //step 4:删除 触发器 + new QProductEvent().eventRuleId.eq(eventRule.getEventRuleId()).delete(); + + + return ResponseData.success(); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java index fdd6d166..8742e991 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductModelController.java @@ -3,6 +3,7 @@ import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSON; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductAttribute; import com.zmops.iot.domain.product.query.QProductAttribute; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; @@ -23,7 +24,7 @@ /** * @author nantian created at 2021/8/3 19:44 *

- * 产品物模型: 属性 服务 事件 + * 产品物模型: 属性 */ @RestController @@ -34,6 +35,8 @@ public class ProductModelController { @Autowired private ProductModelService productModelService; + //依赖属性类型 + private static final String ATTR_SOURCE_DEPEND = "18"; /** * 产品物模型 属性 分页列表 @@ -77,13 +80,24 @@ public ResponseData prodModelAttributeCreate(@RequestBody @Validated(BaseEntity. throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); } + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + if (productAttr.getDepAttrId() == null) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); + } + ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getDepAttrId()).findOne(); + if (null == productAttribute) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); + } + productAttr.setMasterItemId(productAttribute.getZbxId()); + } + Long attrId = IdUtil.getSnowflake().nextId(); productAttr.setAttrId(attrId); - String response = productModelService.createTrapperItem(productAttr); - String zbxId = JSON.parseObject(response, TemplateIds.class).getItemids()[0]; + String response = productModelService.createTrapperItem(productAttr); + String zbxId = JSON.parseObject(response, TemplateIds.class).getItemids()[0]; - productModelService.createProductAttr(productAttr,zbxId); + productModelService.createProductAttr(productAttr, zbxId); return ResponseData.success(productAttr); } @@ -101,6 +115,17 @@ public ResponseData prodModelAttributeUpdate(@RequestBody @Validated(BaseEntity. throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_EXISTS); } + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + if (productAttr.getDepAttrId() == null) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NULL); + } + ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getDepAttrId()).findOne(); + if (null == productAttribute) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED_NOT_EXIST); + } + productAttr.setMasterItemId(productAttribute.getZbxId()); + } + return ResponseData.success(productModelService.updateTrapperItem(productAttr)); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java index e5c244c1..922e9bf9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductServiceController.java @@ -1,17 +1,78 @@ package com.zmops.iot.web.product.controller; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.product.dto.ProductServiceDto; +import com.zmops.iot.web.product.dto.param.ProductSvcParam; +import com.zmops.iot.web.product.service.ProductSvcService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * @author nantian created at 2021/8/4 16:33 *

- * 产品 物模型 服务 【功能】 + * 产品物模型: 服务 */ @RestController @RequestMapping("/product/service") public class ProductServiceController { + @Autowired + ProductSvcService productSvcService; + /** + * 服务分页列表 + */ + @RequestMapping("/getServiceByPage") + public Pager getServiceByPage(@Validated @RequestBody ProductSvcParam productSvcParam) { + return productSvcService.getServiceByPage(productSvcParam); + } + + /** + * 服务列表 + */ + @RequestMapping("/list") + public ResponseData list(@Validated @RequestBody ProductSvcParam productSvcParam) { + return ResponseData.success(productSvcService.list(productSvcParam)); + } + + /** + * 根据服务 获取参数列表 + */ + @RequestMapping("/param/list") + public ResponseData paramList(@RequestParam("serviceId") long serviceId) { + return ResponseData.success(productSvcService.paramList(serviceId)); + } + + /** + * 服务创建 + */ + @RequestMapping("/create") + public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody ProductServiceDto productServiceDto) { + productServiceDto.setId(null); + return ResponseData.success(productSvcService.create(productServiceDto)); + } + + /** + * 服务修改 + */ + @RequestMapping("/update") + public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody ProductServiceDto productServiceDto) { + return ResponseData.success(productSvcService.update(productServiceDto)); + } + + /** + * 服务删除 + */ + @RequestMapping("/delete") + public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody ProductServiceDto productServiceDto) { + productSvcService.delete(productServiceDto.getIds()); + return ResponseData.success(productServiceDto.getIds()); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java index e60b965c..8a965eef 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductStatusTriggerController.java @@ -1,32 +1,29 @@ package com.zmops.iot.web.product.controller; -import com.alibaba.fastjson.JSON; +import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.ProductStatusFunction; import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.domain.product.query.QProductStatusFunction; +import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.response.ResponseData; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductStatusJudgeRule; import com.zmops.iot.web.product.service.ProductTriggerService; -import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.service.ZbxItem; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import javax.validation.Valid; -import java.util.List; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; /** * @author nantian created at 2021/8/3 19:45 *

- * 设备在线状态 触发器 + * 设备在线 离线状态 触发器 */ @RestController -@RequestMapping("/product/trigger/status") +@RequestMapping("/product/status/trigger") public class ProductStatusTriggerController { @@ -36,6 +33,17 @@ public class ProductStatusTriggerController { @Autowired private ProductTriggerService productTriggerService; + /** + * 离线 或者 在线触发器 信息 + * + * @param relationId 关联产品或设备ID + * @return ResponseData + */ + @GetMapping("/detail") + public ResponseData getRule(@RequestParam("relationId") String relationId) { + return ResponseData.success(productTriggerService.getRule(relationId)); + } + /** * 创建 离线 或者 在线触发器 @@ -44,23 +52,58 @@ public class ProductStatusTriggerController { * @return ResponseData */ @PostMapping("/create") - public ResponseData createOfflineTrigger(@RequestBody @Valid ProductStatusJudgeRule rule) { + public ResponseData createDeviceStatusTrigger(@RequestBody @Validated(BaseEntity.Create.class) ProductStatusJudgeRule rule) { - // nodata(/sanshi-host/sender.a,1m)=1 - // 查询 itemid itemkey 和 template name - ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getProductAttrId()).findOne(); - if (null == prodAttr) { - throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getAttrId()).findOne(); + ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getAttrIdRecovery()).findOne(); + + if (null == prodAttr || null == prodAttrSecond) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_NOT_EXISTS); + } + + int count = new QProductStatusFunctionRelation().relationId.eq(rule.getRelationId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.RULE_EXISTS); } + return ResponseData.success(productTriggerService.createDeviceStatusJudgeTrigger(rule)); + } + - List itemInfo = JSON.parseObject(zbxItem.getItemInfo(prodAttr.getZbxId(), null), List.class); + /** + * 修改 离线 或者 在线触发器 + * + * @param rule 在线规则 + * @return ResponseData + */ + @PostMapping("/update") + public ResponseData updateDeviceStatusTrigger(@RequestBody @Validated(BaseEntity.Update.class) ProductStatusJudgeRule rule) { - String key = itemInfo.get(0).getKey_(); // item key + ProductAttribute prodAttr = new QProductAttribute().attrId.eq(rule.getAttrId()).findOne(); + ProductAttribute prodAttrSecond = new QProductAttribute().attrId.eq(rule.getAttrIdRecovery()).findOne(); + if (null == prodAttr || null == prodAttrSecond) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_KEY_NOT_EXISTS); + } - productTriggerService.createDeviceStatusJudgeTrigger(rule); + // 数据库查询 triggerId 并且赋值 + ProductStatusFunction productStatusFunction = new QProductStatusFunction().ruleId.eq(rule.getRuleId()).findOne(); + if (null == productStatusFunction) { + throw new ServiceException(BizExceptionEnum.RULE_NOT_EXISTS); + } + return ResponseData.success(productTriggerService.updateDeviceStatusJudgeTrigger(rule)); + } + /** + * 删除 离线 或者 在线触发器 + * + * @param rule 在线规则 + * @return ResponseData + */ + @PostMapping("/delete") + public ResponseData deleteDeviceStatusTrigger(@RequestBody @Validated(BaseEntity.Delete.class) ProductStatusJudgeRule rule) { + productTriggerService.deleteDeviceStatusTrigger(rule.getRuleId()); return ResponseData.success(); } + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductTypeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductTypeController.java index 8a9ff2e1..77acb8cc 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductTypeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/controller/ProductTypeController.java @@ -3,6 +3,7 @@ import com.zmops.iot.core.log.BussinessLog; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.product.dto.param.ProductTypeParam; import com.zmops.iot.web.product.service.ProductTypeService; import lombok.extern.slf4j.Slf4j; @@ -28,6 +29,7 @@ public class ProductTypeController { /** * 产品分类树 */ + @Permission(code = "product_type") @RequestMapping("/tree") public ResponseData tree() { return ResponseData.success(productTypeService.tree()); @@ -36,6 +38,7 @@ public ResponseData tree() { /** * 新增产品分类 */ + @Permission(code = "product_type") @RequestMapping("/create") @BussinessLog("新增产品分类") public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody ProductTypeParam productType) { @@ -45,6 +48,7 @@ public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody Prod /** * 修改产品分类 */ + @Permission(code = "product_type") @RequestMapping("/update") @BussinessLog("修改产品分类") public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody ProductTypeParam productType) { @@ -54,6 +58,7 @@ public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody Prod /** * 删除产品分类 */ + @Permission(code = "product_type") @RequestMapping("/delete") @BussinessLog("删除产品分类") public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody ProductTypeParam productType) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java index c172b160..d8d59298 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttr.java @@ -6,6 +6,7 @@ import lombok.Getter; import lombok.Setter; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.time.LocalDateTime; import java.util.List; @@ -30,26 +31,28 @@ public class ProductAttr { private String key; private String units; - private String unitName; //来源:设备 trapper ,属性依赖 dependent @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String source; - private String sourceName; + + private Byte eventLevel = 1; private String remark; private Long depAttrId; + @JsonIgnore + private String masterItemId; + @JsonIgnore private String zbxId; @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) - private Long productId; + private String productId; @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) private String valueType; - private String valueTypeName; private String valuemapid; @@ -58,13 +61,17 @@ public class ProductAttr { //预处理 private List processStepList; - @NotNull(groups = BaseEntity.Delete.class) + @NotEmpty(groups = BaseEntity.Delete.class) private List attrIds; + private Integer delay; + //取数间隔单位 + private String unit; + LocalDateTime createTime; LocalDateTime updateTime; - Long createUser; - Long updateUser; + Long createUser; + Long updateUser; /** * 预处理步骤 @@ -93,13 +100,8 @@ public String getParams() { paramStr.append(param).append("\\\\n"); } return paramStr.substring(0, paramStr.length() - 3); - } else { - return ""; } + return ""; } - -// public void setParams(String params){ -// this.params = params.split("\\n"); -// } } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java index 05c18ddb..ad96650c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductAttrDto.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.domain.BaseDto; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; import com.zmops.iot.model.cache.filter.DicType; @@ -20,7 +19,7 @@ @Data @JsonSerialize(using = CachedValueFilter.class) -public class ProductAttrDto implements BaseDto { +public class ProductAttrDto { private Long attrId; @@ -29,22 +28,25 @@ public class ProductAttrDto implements BaseDto { private String key; - @CachedValue(value = "UNITS") + @CachedValue(value = "UNITS", fieldName = "unitsName") private String units; - @CachedValue(value = "DEVICE_TYPE") + @CachedValue(value = "ATTR_TYPE", fieldName = "sourceName") private String source; private String remark; private Long depAttrId; + @CachedValue(value = "EVENT_LEVEL", fieldName = "eventLevelName") + private String eventLevel; + @JsonIgnore private String zbxId; - private Long productId; + private String productId; - @CachedValue(value = "DATA_TYPE") + @CachedValue(value = "DATA_TYPE", fieldName = "valueTypeName") private String valueType; private String valuemapid; @@ -52,16 +54,28 @@ public class ProductAttrDto implements BaseDto { private List tags; //预处理 + @JsonIgnore private List processStepList; private Long templateId; - LocalDateTime createTime; - LocalDateTime updateTime; + private LocalDateTime createTime; + private LocalDateTime updateTime; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") private Long createUser; - @CachedValue(type = DicType.SysUserName) + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") private Long updateUser; + private String clock; + + private String value; + private String originalValue; + + private Integer delay; + private String delayName; + //取数间隔单位 + private String unit; + + private String error; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductBasicInfo.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductBasicInfo.java index e029100f..fe7a5e5c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductBasicInfo.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductBasicInfo.java @@ -39,4 +39,9 @@ public class ProductBasicInfo extends BaseQueryParam { private String tag; private String tagVal; + + private Long tenantId; + + private String icon; + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java index 9aad1777..5195cb5c 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductDto.java @@ -2,30 +2,31 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import com.zmops.iot.domain.BaseDto; import com.zmops.iot.model.cache.filter.CachedValue; import com.zmops.iot.model.cache.filter.CachedValueFilter; import com.zmops.iot.model.cache.filter.DicType; import lombok.Data; +import java.time.LocalDateTime; + /** * @author yefei **/ @Data @JsonSerialize(using = CachedValueFilter.class) -public class ProductDto implements BaseDto { +public class ProductDto { private Long productId; - @CachedValue(type = DicType.ProdType) + @CachedValue(type = DicType.ProdType, fieldName = "groupName") private Long groupId; @JsonProperty("prodName") private String name; @JsonProperty("prodType") - @CachedValue(value = "DEVICE_TYPE") + @CachedValue(value = "DEVICE_TYPE", fieldName = "typeName") private String type; private String manufacturer; @@ -39,16 +40,19 @@ public class ProductDto implements BaseDto { private String zbxId; - @CachedValue(type = DicType.SysUserName) - private String createUser; - private String createTime; - @CachedValue(type = DicType.SysUserName) - private String updateUser; - private String updateTime; + + private LocalDateTime createTime; + private LocalDateTime updateTime; + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + private Long createUser; + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + private Long updateUser; private Long deviceNum; -// private List productTag; -// private JSONArray valueMaps; + @CachedValue(type = DicType.Tenant, fieldName = "tenantName") + private Long tenantId; + + private String icon; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java new file mode 100644 index 00000000..8740ab41 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventDto.java @@ -0,0 +1,50 @@ +package com.zmops.iot.web.product.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class ProductEventDto { + + private Long eventRuleId; + + private Byte eventNotify; + + private String eventRuleName; + + @CachedValue(value = "EVENT_LEVEL", fieldName = "eventLevelName") + private String eventLevel; + + @CachedValue(value = "STATUS", fieldName = "statusName") + private String status; + + @CachedValue(value = "WHETHER", fieldName = "inheritName") + private String inherit; + + private String remark; + private String classify; + private String expLogic; + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + private Long createUser; + private String createTime; + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + private Long updateUser; + private String updateTime; + + @CachedValue(type= DicType.Tenant, fieldName = "tenantName") + private Long tenantId; + + private Integer taskId; + + @CachedValue(value = "triggerType", fieldName = "triggerTypeName") + + private String triggerType; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java new file mode 100644 index 00000000..2065aa7f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRule.java @@ -0,0 +1,143 @@ +package com.zmops.iot.web.product.dto; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.util.ToolUtil; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang.StringUtils; + +import javax.validation.Valid; +import javax.validation.constraints.Max; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author nantian created at 2021/9/14 14:47 + *

+ * 告警规则 + */ + +@Getter +@Setter +public class ProductEventRule { + + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class, BaseEntity.Status.class}) + private Long eventRuleId; + + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private Byte eventNotify; // 0 否 1 是,默认 1 + + // 告警规则名称 + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String eventRuleName; + + // 告警规则级别 + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private Byte eventLevel; + + // 表达式列表 + @Valid + @NotEmpty(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private List expList; + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String expLogic; // and or + + private String remark; + + private List deviceServices; + + private List tags; + + @NotNull(groups = BaseEntity.Update.class) + private String zbxId; + + @NotBlank(groups = BaseEntity.Create.class) + private String productId; // 产品ID + + @NotBlank(groups = BaseEntity.Status.class) + private String status; + + private String classify = "0"; + + @Data + public static class Tag { + + @Max(20) + private String tag; + + @Max(50) + private String value; + } + + @Getter + @Setter + // 告警表达式 构成 + public static class Expression { + + private Long eventExpId; + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String function; // last avg max min sum change nodata + + private String scope; // s m h T + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String condition; // > < = <> >= <= + + @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String value; + + @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + private String productAttrKey; // 产品属性 Key + + private String productId; // 产品 ID + + private String unit; + + private Long productAttrId; + + private String productAttrType; + + private String attrValueType; + + private String period; + + @Override + public String toString() { + StringBuilder expression = new StringBuilder(); + expression.append(function); + expression.append("(/"); + expression.append(productId); + expression.append("/"); + expression.append(productAttrKey); + + if (StringUtils.isNotBlank(scope)) { + expression.append(", "); + expression.append(scope); + } + expression.append(") ").append(condition).append(" ").append(ToolUtil.addQuotes(value)); + return expression.toString(); + } + } + + + @Setter + @Getter + public static class DeviceService { + + private String deviceId; + + private String executeDeviceId; + + private Long serviceId; + } + +} + + + + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java new file mode 100644 index 00000000..7eaa5414 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductEventRuleDto.java @@ -0,0 +1,73 @@ +package com.zmops.iot.web.product.dto; + +import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.iot.domain.product.ProductEventService; +import com.zmops.iot.model.cache.filter.CachedValue; +import lombok.Data; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.Max; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author nantian created at 2021/9/14 14:47 + *

+ * 告警规则 + */ + +@Getter +@Setter +public class ProductEventRuleDto { + + private Long eventRuleId; + + private Byte eventNotify; + private String eventRuleName; + + private Byte eventLevel; + + private List expList; + + private String expLogic; + + private String remark; + + private List deviceServices; + + private List tags; + + private String zbxId; + + private String productId; + + private String status; + + private String inherit; + + private String inheritProductId; + + private String scheduleConf; + + @CachedValue(value = "triggerType", fieldName = "triggerTypeName") + private Integer triggerType; + + private Integer taskId; + + @Data + public static class Tag { + + @Max(20) + private String tag; + + @Max(50) + private String value; + } + + +} + + + + diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java new file mode 100644 index 00000000..84ebf5bf --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductServiceDto.java @@ -0,0 +1,44 @@ +package com.zmops.iot.web.product.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class ProductServiceDto { + + @NotNull(groups = BaseEntity.Update.class) + private Long id; + + @NotBlank(groups = BaseEntity.Create.class) + private String name; + + private String mark; + + private String remark; + + @NotNull(groups = BaseEntity.Create.class) + private String relationId; + + @CachedValue(value = "EXECUTE_TYPE", fieldName = "asyncName") + private String async; + + @CachedValue(value = "WHETHER", fieldName = "inheritName") + private String inherit; + + private List productServiceParamList; + + @NotNull(groups = BaseEntity.Delete.class) + private List ids; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java new file mode 100644 index 00000000..acdce4ea --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusFunctionDto.java @@ -0,0 +1,65 @@ +package com.zmops.iot.web.product.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +/** + * @author nantian created at 2021/8/5 16:06 + *

+ * 设备 离线/上线 规则 last(/Zabbix server/system.cpu.util[,user])>10 + */ + +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class ProductStatusFunctionDto { + + + private String relationId; + + private Long ruleId; + + private Long attrId; + + private Integer ruleStatus; + + private String ruleFunction; + + private String ruleCondition; + + @CachedValue(value = "UNITS", fieldName = "unitName") + private String unit; + + @CachedValue(value = "UNITS", fieldName = "unitsName") + private String units; + + @CachedValue(value = "UNITS", fieldName = "unitsRecoveryName") + private String unitsRecovery; + + private String productAttrKey; + + private Long attrIdRecovery; + + private String ruleFunctionRecovery; + + private String ruleConditionRecovery; + + private String productAttrKeyRecovery; + + @CachedValue(value = "UNITS", fieldName = "unitRecoveryName") + private String unitRecovery; + + private String attrName; + + private String attrNameRecovery; + + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + private Long createUser; + private String createTime; + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + private Long updateUser; + private String updateTime; + private String zbxIdRecovery; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java index 332767dd..82c84943 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductStatusJudgeRule.java @@ -1,39 +1,60 @@ package com.zmops.iot.web.product.dto; +import com.zmops.iot.domain.BaseEntity; import lombok.Data; +import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * @author nantian created at 2021/8/5 16:06 *

- * 设备 离线/上线 规则 + * 设备 离线/上线 规则 last(/Zabbix server/system.cpu.util[,user])>10 */ @Data public class ProductStatusJudgeRule { - @NotNull - private Long productAttrId; // 设备属性ID - @NotNull - private String ruleType; // 触发离线 还是 触发在线 + @NotBlank(groups = {BaseEntity.Create.class}) + private String relationId; // deviceid - @NotNull - private String ruleFunction; // nodata 或者 last 函数 + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class}) + private Long ruleId; // 自动生成,trigger name - @NotNull - private String ruleValue; // 时间 或者 值 + private String ruleName; + //##################### 下线规则 - private String triggerName; // ID - private String itemKey; - private String hostName; + @NotNull(groups = {BaseEntity.Create.class}) + private Long attrId; // 设备属性ID + @NotBlank(groups = {BaseEntity.Create.class}) + private String ruleFunction; // nodata 或者 > < = 函数 - public static final String ON_LINE = "online"; // 上线触发器 - public static final String OFF_LINE = "offline"; // 离线触发器 - public static final String NODATA = "nodata"; - public static final String LASTDATA = "lastdata"; + @NotBlank(groups = {BaseEntity.Create.class}) + private String ruleCondition; // 时间 或者 特定值 + @NotNull(groups = {BaseEntity.Create.class}) + private String unit; //单位 s m h 或空 + + @NotBlank(groups = {BaseEntity.Create.class}) + private String productAttrKey; // 属性 Key + + + //##################### 上线规则 + + @NotNull(groups = {BaseEntity.Create.class}) + private Long attrIdRecovery; // 设备属性ID + + @NotBlank(groups = {BaseEntity.Create.class}) + private String ruleFunctionRecovery; // nodata 或者 > < = 函数 + + @NotBlank(groups = {BaseEntity.Create.class}) + private String ruleConditionRecovery; // 时间 或者 特定值 + + @NotBlank(groups = {BaseEntity.Create.class}) + private String productAttrKeyRecovery; // 属性 Key + + private String unitRecovery; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java index 45db0104..67a3dd06 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ProductTag.java @@ -2,8 +2,10 @@ import lombok.Data; -import javax.validation.constraints.Max; +import javax.validation.Valid; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; import java.util.List; /** @@ -16,17 +18,20 @@ public class ProductTag { @NotNull - private Long productId; + private String productId; + @Valid private List productTag; @Data public static class Tag { - @Max(20) + @Size(max = 20) + @Pattern(regexp = "^[A-Za-z0-9]+$", + message = "标签名称不能包含中文、特殊字符") private String tag; - @Max(50) + @Size(max = 50) private String value; } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ValueMap.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ValueMap.java index ca89bd7c..e1af8f96 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ValueMap.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ValueMap.java @@ -14,7 +14,7 @@ public class ValueMap { @NotNull(groups = BaseEntity.Create.class) - private Long productId; + private String productId; @NotNull(groups = BaseEntity.Create.class) private String valueMapName; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ZbxTriggerInfo.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ZbxTriggerInfo.java new file mode 100644 index 00000000..5508384b --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/ZbxTriggerInfo.java @@ -0,0 +1,29 @@ +package com.zmops.iot.web.product.dto; + +import lombok.Data; + +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class ZbxTriggerInfo { + private List hosts; + private List tags; + private String triggerid; + private String description; + + + @Data + public static class Host{ + private String hostid; + private String host; + } + + @Data + public static class Tag{ + private String tag; + private String value; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java new file mode 100644 index 00000000..f5a13ec3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/EventParm.java @@ -0,0 +1,19 @@ +package com.zmops.iot.web.product.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @author yefei + **/ +@Data +public class EventParm extends BaseQueryParam { + + private String eventRuleName; + + @NotBlank + private String prodId; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java index 41617f57..4705ecd6 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductAttrParam.java @@ -4,7 +4,7 @@ import com.zmops.iot.web.sys.dto.param.BaseQueryParam; import lombok.Data; -import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.util.List; @@ -14,13 +14,15 @@ @Data public class ProductAttrParam extends BaseQueryParam { - private Long prodId; + @NotNull(groups = BaseEntity.Get.class, message = "请选择一个设备再查询") + private String prodId; private String attrName; private String key; + private String source; - @NotNull(groups = BaseEntity.Delete.class) + @NotEmpty(groups = BaseEntity.Delete.class) private List ids; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java new file mode 100644 index 00000000..05788077 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductSvcParam.java @@ -0,0 +1,20 @@ +package com.zmops.iot.web.product.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @author yefei + **/ +@Data +public class ProductSvcParam extends BaseQueryParam { + + private String name; + + private String mark; + + @NotBlank + private String prodId; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductTypeParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductTypeParam.java index 55be4b4e..e11edfba 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductTypeParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/dto/param/ProductTypeParam.java @@ -25,6 +25,8 @@ public class ProductTypeParam { private String remark; + private Long tenantId; + @NotNull(groups = BaseEntity.Delete.class) private List ids; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java new file mode 100644 index 00000000..8c24338e --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductAttributeEventService.java @@ -0,0 +1,315 @@ +package com.zmops.iot.web.product.service; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.device.Device; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.Product; +import com.zmops.iot.domain.product.ProductAttributeEvent; +import com.zmops.iot.domain.product.query.QProduct; +import com.zmops.iot.domain.product.query.QProductAttributeEvent; +import com.zmops.iot.domain.product.query.QProductEventExpression; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductAttrCreateEvent; +import com.zmops.iot.web.event.applicationEvent.ProductAttrUpdateEvent; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.iot.web.product.dto.ProductAttrDto; +import com.zmops.iot.web.product.dto.ProductTag; +import com.zmops.iot.web.product.dto.param.ProductAttrParam; +import com.zmops.zeus.driver.entity.ZbxItemInfo; +import com.zmops.zeus.driver.entity.ZbxProcessingStep; +import com.zmops.zeus.driver.service.ZbxItem; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Service +@Slf4j +public class ProductAttributeEventService { + + @Autowired + private ZbxItem zbxItem; + + @Autowired + ApplicationEventPublisher publisher; + + /** + * 产品属性分页列表 + * + * @param productAttr + * @return + */ + public Pager prodAttributeEventList(ProductAttrParam productAttr) { + QProductAttributeEvent qProductAttribute = new QProductAttributeEvent(); + + if (ToolUtil.isNotEmpty(productAttr.getProdId())) { + qProductAttribute.productId.eq(productAttr.getProdId()); + } + if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { + qProductAttribute.name.contains(productAttr.getAttrName()); + } + if (ToolUtil.isNotEmpty(productAttr.getKey())) { + qProductAttribute.key.contains(productAttr.getKey()); + } + + List pagedList = qProductAttribute.setFirstRow((productAttr.getPage() - 1) * productAttr.getMaxRow()).setMaxRows(productAttr.getMaxRow()).asDto(ProductAttrDto.class).findList(); + int count = qProductAttribute.findCount(); + return new Pager<>(pagedList, count); + } + + /** + * 产品属性列表 + * + * @param productAttr + * @return + */ + public List list(ProductAttrParam productAttr) { + QProductAttributeEvent qProductAttribute = new QProductAttributeEvent(); + if (null != productAttr.getProdId()) { + qProductAttribute.productId.eq(productAttr.getProdId()); + } + if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { + qProductAttribute.name.contains(productAttr.getAttrName()); + } + if (ToolUtil.isNotEmpty(productAttr.getKey())) { + qProductAttribute.key.contains(productAttr.getKey()); + } + List list = qProductAttribute.orderBy(" create_time desc").findList(); + return ToolUtil.convertBean(list, ProductAttrDto.class); +// StringBuilder sql = new StringBuilder("select * from product_attribute_event where 1=1"); +// if (null != productAttr.getProdId()) { +// sql.append(" and product_id = :productId"); +// } +// if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { +// sql.append(" and name like :attrName"); +// } +// if (ToolUtil.isNotEmpty(productAttr.getKey())) { +// sql.append(" and key like :key"); +// } +// sql.append(" order by create_time desc"); +// DtoQuery dto = DB.findDto(ProductAttrDto.class, sql.toString()); +// +// if (null != productAttr.getProdId()) { +// dto.setParameter("productId", productAttr.getProdId()); +// } +// if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { +// dto.setParameter("attrName", "%" + productAttr.getAttrName() + "%"); +// } +// if (ToolUtil.isNotEmpty(productAttr.getKey())) { +// dto.setParameter("key", "%" + productAttr.getKey() + "%"); +// } + +// return dto.findList(); + } + + /** + * 产品属性详情 + * + * @param attrId + * @return + */ + public ProductAttrDto detail(Long attrId) { +// ProductAttrDto attr = new QProductAttributeEvent().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); + ProductAttrDto attr = DB.findDto(ProductAttrDto.class, "select * from product_attribute_event where attr_id=:attrId").setParameter("attrId", attrId).findOne(); + + if (attr == null || ToolUtil.isEmpty(attr.getZbxId())) { + return attr; + } + JSONArray itemInfo = JSONObject.parseArray(zbxItem.getItemInfo(attr.getZbxId(), null)); + attr.setTags(JSONObject.parseArray(itemInfo.getJSONObject(0).getString("tags"), ProductTag.Tag.class)); + attr.setProcessStepList(formatProcessStep(itemInfo.getJSONObject(0).getString("preprocessing"))); + String valuemap = itemInfo.getJSONObject(0).getString("valuemap"); + if (ToolUtil.isNotEmpty(valuemap) && !"[]".equals(valuemap)) { + attr.setValuemapid(JSONObject.parseObject(valuemap).getString("valuemapid")); + } + return attr; + } + + private List formatProcessStep(String preprocessing) { + if (ToolUtil.isEmpty(preprocessing)) { + return Collections.emptyList(); + } + List processingSteps = new ArrayList<>(); + JSONArray jsonArray = JSONObject.parseArray(preprocessing); + for (Object object : jsonArray) { + ProductAttr.ProcessingStep processingStep = new ProductAttr.ProcessingStep(); + processingStep.setType(((JSONObject) object).getString("type")); + processingStep.setParams(((JSONObject) object).getString("params").split("\\n")); + processingSteps.add(processingStep); + } + + return processingSteps; + } + + /** + * 创建 产品属性 + * + * @param productAttr 产品属性DTO + */ + public void createProductAttr(ProductAttr productAttr, String zbxId) { + ProductAttributeEvent productAttributeEvent = new ProductAttributeEvent(); + buildProdAttribute(productAttributeEvent, productAttr); + productAttributeEvent.setZbxId(zbxId); + productAttributeEvent.save(); + + publisher.publishEvent(new ProductAttrCreateEvent(this, productAttr)); + + log.debug("------------------"); + + } + + private ProductAttributeEvent buildProdAttribute(ProductAttributeEvent prodAttribute, ProductAttr productAttr) { + prodAttribute.setProductId(productAttr.getProductId()); + prodAttribute.setName(productAttr.getAttrName()); + prodAttribute.setKey(productAttr.getKey()); + prodAttribute.setUnits(productAttr.getUnits()); + prodAttribute.setRemark(productAttr.getRemark()); + prodAttribute.setValueType(productAttr.getValueType()); + prodAttribute.setAttrId(productAttr.getAttrId()); + prodAttribute.setEventLevel(productAttr.getEventLevel()); + prodAttribute.setSource(productAttr.getSource()); + prodAttribute.setDepAttrId(productAttr.getDepAttrId()); + prodAttribute.setValuemapid(productAttr.getValuemapid()); + prodAttribute.setUnit(productAttr.getUnit()); + + return prodAttribute; + } + + /** + * 创建 Trapper 类型 ITEM + * + * @param productAttr 属性 + * @return String + */ + public String createTrapperItem(ProductAttr productAttr) { + + String itemName = productAttr.getAttrId() + ""; + String hostId = ""; + Device device = new QDevice().deviceId.eq(productAttr.getProductId()).findOne(); + if (null == device) { + Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); + if (null == prod) { + throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + } + hostId = prod.getZbxId(); + } else { + hostId = device.getZbxId(); + } + + List processingSteps = new ArrayList<>(); + if (ToolUtil.isNotEmpty(productAttr.getProcessStepList())) { + productAttr.getProcessStepList().forEach(i -> { + ZbxProcessingStep step = new ZbxProcessingStep(); + step.setType(i.getType()); + step.setParams(i.getParams()); + processingSteps.add(step); + }); + } + Map tagMap = new HashMap<>(); + if (ToolUtil.isNotEmpty(productAttr.getTags())) { + tagMap = productAttr.getTags().stream() + .collect(Collectors.toMap(ProductTag.Tag::getTag, ProductTag.Tag::getValue, (k1, k2) -> k2)); + } + + return zbxItem.createTrapperItem(itemName, productAttr.getKey(), + hostId, productAttr.getSource(), productAttr.getDelay() + "", productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap, null); + } + + /** + * 修改 Trapper 类型 ITEM + * + * @param productAttr 属性 + * @return String + */ + public ProductAttr updateTrapperItem(ProductAttr productAttr) { + ProductAttributeEvent productAttributeEvent = new QProductAttributeEvent().attrId.eq(productAttr.getAttrId()).findOne(); + buildProdAttribute(productAttributeEvent, productAttr); + String hostId = ""; + Device device = new QDevice().deviceId.eq(productAttr.getProductId()).findOne(); + if (null == device) { + Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); + if (null == prod) { + throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); + } + hostId = prod.getZbxId(); + } else { + hostId = device.getZbxId(); + } + List processingSteps = new ArrayList<>(); + if (ToolUtil.isNotEmpty(productAttr.getProcessStepList())) { + productAttr.getProcessStepList().forEach(i -> { + ZbxProcessingStep step = new ZbxProcessingStep(); + + step.setType(i.getType()); + step.setParams(i.getParams()); + + processingSteps.add(step); + }); + } + + Map tagMap = new HashMap<>(); + if (ToolUtil.isNotEmpty(productAttr.getTags())) { + tagMap = productAttr.getTags().stream() + .collect(Collectors.toMap(ProductTag.Tag::getTag, ProductTag.Tag::getValue, (k1, k2) -> k2)); + } + + + zbxItem.updateTrapperItem(productAttributeEvent.getZbxId(), productAttr.getAttrId() + "", productAttr.getKey(), + hostId, productAttr.getSource(), productAttr.getDelay() + "", productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap, null); + + DB.update(productAttributeEvent); + + publisher.publishEvent(new ProductAttrUpdateEvent(this, productAttr)); + + log.debug("----------------------"); + return productAttr; + } + + /** + * 删称 Trapper 类型 ITEM + * + * @param productAttr 属性 + * @return String + */ + public void deleteTrapperItem(ProductAttr productAttr) { + + //检查是否有属性依赖 + int count = new QProductAttributeEvent().depAttrId.in(productAttr.getAttrIds()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED); + } + + //检查属性是否被告警规则引入 + List attrIds = new QProductAttributeEvent().select(QProductAttributeEvent.alias().attrId).templateId.in(productAttr.getAttrIds()).findSingleAttributeList(); + count = new QProductEventExpression().productAttrId.in(productAttr.getAttrIds()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_EVENT_HASDEPTED); + } + + List zbxIds = new QProductAttributeEvent().select(QProductAttributeEvent.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); + //删除zbx item + if (ToolUtil.isNotEmpty(zbxIds)) { + List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(zbxIds.toString(), null), ZbxItemInfo.class); + if (ToolUtil.isNotEmpty(itemInfos)) { + zbxItem.deleteTrapperItem(itemInfos.parallelStream().map(ZbxItemInfo::getItemid).collect(Collectors.toList())); + } + } + + //删除 属性 + new QProductAttributeEvent().attrId.in(productAttr.getAttrIds()).delete(); + + //删除 设备 继承的属性 + new QProductAttributeEvent().templateId.in(productAttr.getAttrIds()).delete(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java new file mode 100644 index 00000000..8aa3ae6b --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductEventRuleService.java @@ -0,0 +1,327 @@ +package com.zmops.iot.web.product.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.product.ProductEvent; +import com.zmops.iot.domain.product.ProductEventExpression; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEvent; +import com.zmops.iot.domain.product.query.QProductEventExpression; +import com.zmops.iot.domain.product.query.QProductEventRelation; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.enums.InheritStatus; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.product.dto.ProductEventDto; +import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.iot.web.product.dto.ProductEventRuleDto; +import com.zmops.iot.web.product.dto.param.EventParm; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author nantian created at 2021/9/15 13:59 + *

+ * 告警规则 创建,产品 和 设备 + */ + +@Slf4j +@Service +public class ProductEventRuleService implements CommandLineRunner { + + @Autowired + private ZbxTrigger zbxTrigger; + + private static final String TRIGGER_CLASSIFY = "0"; + + /** + * 保存触发器 + * + * @param eventRule 告警规则 + */ + public void createProductEventRule(ProductEventRule eventRule) { + // step 1: 保存产品告警规则 + ProductEvent event = initEventRule(eventRule); + event.setEventRuleId(eventRule.getEventRuleId()); + DB.save(event); + + //step 2: 保存 表达式,方便回显 + List expList = new ArrayList<>(); + + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = initEventExpression(i); + exp.setEventRuleId(eventRule.getEventRuleId()); + expList.add(exp); + }); + + DB.saveAll(expList); + + //step 3: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id,execute_device_id, service_id) values (:eventRuleId, :deviceId,:executeDeviceId, :serviceId)") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .setParameter("deviceId", eventRule.getProductId()) + .execute(); + }); + } + + //step 4: 保存关联关系 + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setEventRuleId(eventRule.getEventRuleId()); + productEventRelation.setRelationId(eventRule.getProductId()); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setInherit(InheritStatus.NO.getCode()); + productEventRelation.setRemark(eventRule.getRemark()); + DB.save(productEventRelation); + + //更新緩存 + updateProductEvent(); + } + + /** + * 更新触发器 + * + * @param eventRuleId 触发器ID + * @param eventRule 告警规则 + */ + public void updateProductEventRule(Long eventRuleId, ProductEventRule eventRule) { + + //step 1: 函数表达式 + DB.sqlUpdate("delete from product_event_expression where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + + //step 2: 删除服务方法调用 + DB.sqlUpdate("delete from product_event_service where event_rule_id = :eventRuleId") + .setParameter("eventRuleId", eventRule.getEventRuleId()) + .execute(); + + // step 3: 保存产品告警规则 + ProductEvent event = initEventRule(eventRule); + event.setEventRuleId(eventRuleId); + DB.update(event); + + //step 4: 保存 表达式,方便回显 + List expList = new ArrayList<>(); + + eventRule.getExpList().forEach(i -> { + ProductEventExpression exp = initEventExpression(i); + exp.setEventRuleId(eventRuleId); + expList.add(exp); + }); + + DB.saveAll(expList); + + //step 5: 保存触发器 调用 本产品方法 + if (null != eventRule.getDeviceServices() && !eventRule.getDeviceServices().isEmpty()) { + eventRule.getDeviceServices().forEach(i -> { + DB.sqlUpdate("insert into product_event_service(event_rule_id, device_id, service_id) values (:eventRuleId, :deviceId, :serviceId)") + .setParameter("eventRuleId", eventRuleId) + .setParameter("deviceId", eventRule.getProductId()) + .setParameter("executeDeviceId", i.getExecuteDeviceId()) + .setParameter("serviceId", i.getServiceId()) + .execute(); + }); + } + + //step 6:保存备注 + if (null != eventRule.getRemark()) { + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRule.getEventRuleId()).eq("relationId", eventRule.getProductId()) + .asUpdate().set("remark", eventRule.getRemark()).update(); + } + + //更新緩存 + updateProductEvent(); + } + + + private ProductEvent initEventRule(ProductEventRule eventRule) { + ProductEvent event = new ProductEvent(); + event.setEventLevel(eventRule.getEventLevel().toString()); + event.setExpLogic(eventRule.getExpLogic()); + event.setEventNotify(eventRule.getEventNotify().toString()); + event.setClassify(eventRule.getClassify()); + event.setEventRuleName(eventRule.getEventRuleName()); + + return event; + } + + private ProductEventExpression initEventExpression(ProductEventRule.Expression exp) { + ProductEventExpression eventExpression = new ProductEventExpression(); + eventExpression.setCondition(exp.getCondition()); + eventExpression.setFunction(exp.getFunction()); + eventExpression.setScope(exp.getScope()); + eventExpression.setValue(exp.getValue()); +// eventExpression.setDeviceId(exp.getProductId()); + eventExpression.setProductAttrKey(exp.getProductAttrKey()); + eventExpression.setProductAttrId(exp.getProductAttrId()); + eventExpression.setProductAttrType(exp.getProductAttrType()); + eventExpression.setPeriod(exp.getPeriod()); + eventExpression.setUnit(exp.getUnit()); + eventExpression.setAttrValueType(exp.getAttrValueType()); + return eventExpression; + } + + + /** + * 更新 触发器规则 zbxId + * + * @param eventRuleId 规则ID + * @param zbxId triggerId + */ + public void updateProductEventRuleZbxId(Long eventRuleId, String[] zbxId) { + String s = zbxTrigger.triggerGet(Arrays.toString(zbxId)); + + List triggers = JSONObject.parseArray(s, Triggers.class); + + Map map = triggers.parallelStream().collect(Collectors.toMap(o -> o.hosts.get(0).host, Triggers::getTriggerid, (a, b) -> a)); + + List productEventRelationList = new QProductEventRelation().eventRuleId.eq(eventRuleId).findList(); + + productEventRelationList.forEach(productEventRelation -> { + if (null != map.get(productEventRelation.getRelationId())) { + DB.update(ProductEventRelation.class).where().eq("eventRuleId", eventRuleId).eq("relationId", productEventRelation.getRelationId()) + .asUpdate().set("zbxId", map.get(productEventRelation.getRelationId())).update(); + } + }); + + } + + + /** + * 创建 触发器 + * + * @param triggerName 触发器名称 + * @param expression 表达式 + * @param level 告警等级 + * @return 触发器ID + */ + public String[] createZbxTrigger(String triggerName, String expression, Byte level) { + String res = zbxTrigger.triggerCreate(triggerName, expression, level,0); + return JSON.parseObject(res, TriggerIds.class).getTriggerids(); + } + + + /** + * 触发器 分页列表 + * + * @param eventParm + * @return + */ + public Pager getEventByPage(EventParm eventParm) { + QProductEvent query = new QProductEvent(); + + if (ToolUtil.isNotEmpty(eventParm.getEventRuleName())) { + query.eventRuleName.contains(eventParm.getEventRuleName()); + } + + query.classify.eq(TRIGGER_CLASSIFY); + + List productEventRelationList = new QProductEventRelation().relationId.eq(eventParm.getProdId()).findList(); + if (ToolUtil.isEmpty(productEventRelationList)) { + return new Pager<>(); + } + List eventRuleIdList = productEventRelationList.parallelStream().map(ProductEventRelation::getEventRuleId).collect(Collectors.toList()); + if (ToolUtil.isNotEmpty(eventRuleIdList)) { + query.eventRuleId.in(eventRuleIdList); + } + Map productEventRelationMap = productEventRelationList.parallelStream().collect(Collectors.toMap(ProductEventRelation::getEventRuleId, o -> o, (a, b) -> a)); + + + List list = query.setFirstRow((eventParm.getPage() - 1) * eventParm.getMaxRow()) + .setMaxRows(eventParm.getMaxRow()).orderBy(" create_time desc").asDto(ProductEventDto.class).findList(); + + list.forEach(productEventDto -> { + if (null != productEventRelationMap.get(productEventDto.getEventRuleId())) { + productEventDto.setStatus(productEventRelationMap.get(productEventDto.getEventRuleId()).getStatus()); + productEventDto.setRemark(productEventRelationMap.get(productEventDto.getEventRuleId()).getRemark()); + productEventDto.setInherit(productEventRelationMap.get(productEventDto.getEventRuleId()).getInherit()); + } + }); + + return new Pager<>(list, query.findCount()); + } + + /** + * 获取 告警规则 详情 + * + * @param productEvent + * @param eventRuleId + * @param prodId + * @return + */ + public ProductEventRuleDto detail(ProductEvent productEvent, long eventRuleId, String prodId) { + ProductEventRuleDto productEventRuleDto = new ProductEventRuleDto(); + ToolUtil.copyProperties(productEvent, productEventRuleDto); + + List expList = new QProductEventExpression().eventRuleId.eq(eventRuleId).findList(); + expList.forEach(productEventExpression -> { + if (ToolUtil.isEmpty(productEventExpression.getDeviceId())) { + productEventExpression.setDeviceId(prodId); + } + }); + productEventRuleDto.setExpList(expList); + productEventRuleDto.setDeviceServices(new QProductEventService().eventRuleId.eq(eventRuleId).deviceId.eq(prodId).findList()); + + ProductEventRelation productEventRelation = new QProductEventRelation().relationId.eq(prodId).eventRuleId.eq(eventRuleId).findOne(); + productEventRuleDto.setStatus(productEventRelation.getStatus()); + productEventRuleDto.setRemark(productEventRelation.getRemark()); + JSONArray triggerInfo = JSONObject.parseArray(zbxTrigger.triggerAndTagsGet(productEventRelation.getZbxId())); + + List tagList = JSONObject.parseArray(triggerInfo.getJSONObject(0).getString("tags"), ProductEventRuleDto.Tag.class); + + productEventRuleDto.setZbxId(productEventRelation.getZbxId()); + productEventRuleDto.setTags(tagList.stream() + .filter(s -> !s.getTag().equals("__execute__") && !s.getTag().equals("__alarm__") && !s.getTag().equals("__event__")) + .collect(Collectors.toList())); + + return productEventRuleDto; + } + + public void updateProductEvent() { + List deviceList = new QProductEvent().findList(); + Map map = deviceList.parallelStream().collect(Collectors.toMap(ProductEvent::getEventRuleId, ProductEvent::getEventRuleName, (a, b) -> a)); + DefinitionsUtil.updateProductEventCache(map); + } + + @Override + public void run(String... args) throws Exception { + updateProductEvent(); + } + + + @Data + static class TriggerIds { + private String[] triggerids; + } + + @Data + public static class Triggers { + private String triggerid; + private String description; + private List hosts; + } + + @Data + public static class Hosts { + private String hostid; + private String host; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelEventPublisher.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelEventPublisher.java new file mode 100644 index 00000000..9f3effae --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelEventPublisher.java @@ -0,0 +1,28 @@ +package com.zmops.iot.web.product.service; + +import com.zmops.iot.web.event.applicationEvent.ProductModelCreateEvent; +import com.zmops.iot.web.event.applicationEvent.ProductModelUpdateEvent; +import com.zmops.iot.web.product.dto.ProductAttr; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +@Component +@EnableAsync +public class ProductModelEventPublisher { + + @Autowired + ApplicationEventPublisher publisher; + + @Async + public void productModelCreateEventPublish(ProductAttr productAttr) { + publisher.publishEvent(new ProductModelCreateEvent(this, productAttr)); + } + + @Async + public void productModelUpdateEventPublish(ProductAttr productAttr) { + publisher.publishEvent(new ProductModelUpdateEvent(this, productAttr)); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java index e054f9ea..55a7ddb8 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductModelService.java @@ -2,30 +2,25 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; -import com.zmops.iot.async.executor.Async; -import com.zmops.iot.async.wrapper.WorkerWrapper; import com.zmops.iot.domain.product.Product; import com.zmops.iot.domain.product.ProductAttribute; -import com.zmops.iot.domain.product.ProductType; import com.zmops.iot.domain.product.query.QProduct; import com.zmops.iot.domain.product.query.QProductAttribute; -import com.zmops.iot.domain.product.query.QProductType; +import com.zmops.iot.domain.product.query.QProductEventExpression; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; -import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.product.dto.ProductAttr; import com.zmops.iot.web.product.dto.ProductAttrDto; import com.zmops.iot.web.product.dto.ProductTag; import com.zmops.iot.web.product.dto.param.ProductAttrParam; -import com.zmops.iot.web.product.service.work.SaveProdAttrWorker; -import com.zmops.iot.web.product.service.work.UpdateAttributeWorker; +import com.zmops.zeus.driver.entity.ZbxItemInfo; import com.zmops.zeus.driver.entity.ZbxProcessingStep; import com.zmops.zeus.driver.service.ZbxItem; import io.ebean.DB; +import io.ebean.DtoQuery; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Service; import java.util.*; @@ -41,10 +36,7 @@ public class ProductModelService { private ZbxItem zbxItem; @Autowired - SaveProdAttrWorker saveProdAttrWorker; - - @Autowired - UpdateAttributeWorker updateProdAttrWorker; + ProductModelEventPublisher productModelEventPublisher; /** * 产品属性分页列表 @@ -55,7 +47,7 @@ public class ProductModelService { public Pager prodModelAttributeList(ProductAttrParam productAttr) { QProductAttribute qProductAttribute = new QProductAttribute(); - if (null != productAttr.getProdId()) { + if (ToolUtil.isNotEmpty(productAttr.getProdId())) { qProductAttribute.productId.eq(productAttr.getProdId()); } if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { @@ -65,8 +57,12 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr qProductAttribute.key.contains(productAttr.getKey()); } - List pagedList = qProductAttribute.setFirstRow((productAttr.getPage() - 1) * productAttr.getMaxRow()).setMaxRows(productAttr.getMaxRow()).asDto(ProductAttrDto.class).findList(); - int count = qProductAttribute.findCount(); + List pagedList = qProductAttribute + .setFirstRow((productAttr.getPage() - 1) * productAttr.getMaxRow()) + .setMaxRows(productAttr.getMaxRow()).orderBy(" create_time desc ") + .asDto(ProductAttrDto.class).findList(); + + int count = qProductAttribute.findCount(); return new Pager<>(pagedList, count); } @@ -76,18 +72,47 @@ public Pager prodModelAttributeList(ProductAttrParam productAttr * @param productAttr * @return */ - public List list(ProductAttrParam productAttr) { - QProductAttribute qProductAttribute = new QProductAttribute(); + public List list(ProductAttrParam productAttr) { +// QProductAttribute qProductAttribute = new QProductAttribute(); +// if (null != productAttr.getProdId()) { +// qProductAttribute.productId.eq(productAttr.getProdId()); +// } +// if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { +// qProductAttribute.name.contains(productAttr.getAttrName()); +// } +// if (ToolUtil.isNotEmpty(productAttr.getKey())) { +// qProductAttribute.key.contains(productAttr.getKey()); +// } + StringBuilder sql = new StringBuilder("select * from product_attribute where 1=1"); if (null != productAttr.getProdId()) { - qProductAttribute.productId.eq(productAttr.getProdId()); + sql.append(" and product_id = :productId"); } if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { - qProductAttribute.name.contains(productAttr.getAttrName()); + sql.append(" and name like :attrName"); } if (ToolUtil.isNotEmpty(productAttr.getKey())) { - qProductAttribute.key.contains(productAttr.getKey()); + sql.append(" and key like :key"); + } + if (ToolUtil.isNotEmpty(productAttr.getSource())) { + sql.append(" and source = :source"); + } + sql.append(" order by create_time desc"); + + DtoQuery dto = DB.findDto(ProductAttrDto.class, sql.toString()); + + if (null != productAttr.getProdId()) { + dto.setParameter("productId", productAttr.getProdId()); + } + if (ToolUtil.isNotEmpty(productAttr.getAttrName())) { + dto.setParameter("attrName", "%" + productAttr.getAttrName() + "%"); + } + if (ToolUtil.isNotEmpty(productAttr.getKey())) { + dto.setParameter("key", "%" + productAttr.getKey() + "%"); + } + if (ToolUtil.isNotEmpty(productAttr.getSource())) { + dto.setParameter("source", productAttr.getSource()); } - return qProductAttribute.orderBy(" create_time desc").findList(); + return dto.findList(); } /** @@ -97,18 +122,23 @@ public List list(ProductAttrParam productAttr) { * @return */ public ProductAttrDto detail(Long attrId) { - ProductAttrDto attr = new QProductAttribute().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); + //ProductAttrDto attr = new QProductAttribute().attrId.eq(attrId).asDto(ProductAttrDto.class).findOne(); + ProductAttrDto attr = DB.findDto(ProductAttrDto.class, "select * from product_attribute where attr_id=:attrId").setParameter("attrId", attrId).findOne(); - if (null == attr.getZbxId()) { + if (attr == null || ToolUtil.isEmpty(attr.getZbxId())) { return attr; } JSONArray itemInfo = JSONObject.parseArray(zbxItem.getItemInfo(attr.getZbxId(), null)); attr.setTags(JSONObject.parseArray(itemInfo.getJSONObject(0).getString("tags"), ProductTag.Tag.class)); attr.setProcessStepList(formatProcessStep(itemInfo.getJSONObject(0).getString("preprocessing"))); - String valuemap = itemInfo.getJSONObject(0).getString("valuemap"); - if (ToolUtil.isNotEmpty(valuemap) && !"[]".equals(valuemap)) { - attr.setValuemapid(JSONObject.parseObject(valuemap).getString("valuemapid")); - } + + +// String valuemap = itemInfo.getJSONObject(0).getString("valuemap"); +// +// if (ToolUtil.isNotEmpty(valuemap) && !"[]".equals(valuemap)) { +// attr.setValuemapid(JSONObject.parseObject(valuemap).getString("valuemapid")); +// } + return attr; } @@ -117,7 +147,7 @@ private List formatProcessStep(String preprocessing) return Collections.emptyList(); } List processingSteps = new ArrayList<>(); - JSONArray jsonArray = JSONObject.parseArray(preprocessing); + JSONArray jsonArray = JSONObject.parseArray(preprocessing); for (Object object : jsonArray) { ProductAttr.ProcessingStep processingStep = new ProductAttr.ProcessingStep(); processingStep.setType(((JSONObject) object).getString("type")); @@ -139,17 +169,23 @@ public void createProductAttr(ProductAttr productAttr, String zbxId) { productAttribute.setZbxId(zbxId); productAttribute.save(); - WorkerWrapper saveProdAttrWork = WorkerWrapper.builder().worker(saveProdAttrWorker).build(); + productModelEventPublisher.productModelCreateEventPublish(productAttr); - try { - Async.work(100, saveProdAttrWork).awaitFinish(); - } catch (InterruptedException e) { - e.printStackTrace(); - } + +// WorkerWrapper asyncAttrZbxIdWork = new WorkerWrapper.Builder() +// .worker(asyncAttrZbxIdWorker).param(productAttr).build(); +// WorkerWrapper saveProdAttrWork = new WorkerWrapper.Builder() +// .worker(saveProdAttrWorker).param(productAttr).next(asyncAttrZbxIdWork).build(); +// +// try { +// Async.beginWork(10000, saveProdAttrWork); +// } catch (ExecutionException | InterruptedException e) { +// e.printStackTrace(); +// } } - private ProductAttribute buildProdAttribute(ProductAttribute prodAttribute, ProductAttr productAttr) { + private void buildProdAttribute(ProductAttribute prodAttribute, ProductAttr productAttr) { prodAttribute.setProductId(productAttr.getProductId()); prodAttribute.setName(productAttr.getAttrName()); prodAttribute.setKey(productAttr.getKey()); @@ -159,7 +195,8 @@ private ProductAttribute buildProdAttribute(ProductAttribute prodAttribute, Prod prodAttribute.setValueType(productAttr.getValueType()); prodAttribute.setAttrId(productAttr.getAttrId()); prodAttribute.setDepAttrId(productAttr.getDepAttrId()); - return prodAttribute; + prodAttribute.setValuemapid(productAttr.getValuemapid()); + prodAttribute.setUnit(productAttr.getUnit()); } /** @@ -172,7 +209,7 @@ public String createTrapperItem(ProductAttr productAttr) { String itemName = productAttr.getAttrId() + ""; - Product prod = new QProduct().productId.eq(productAttr.getProductId()).findOne(); + Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); if (null == prod) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } @@ -184,7 +221,7 @@ public String createTrapperItem(ProductAttr productAttr) { ZbxProcessingStep step = new ZbxProcessingStep(); step.setType(i.getType()); - step.setParams(i.getParams()); + step.setParams(i.getParams().replaceAll("\n", "").replaceAll("\"", "\\\\\\\\\"")); processingSteps.add(step); }); @@ -194,9 +231,12 @@ public String createTrapperItem(ProductAttr productAttr) { tagMap = productAttr.getTags().stream() .collect(Collectors.toMap(ProductTag.Tag::getTag, ProductTag.Tag::getValue, (k1, k2) -> k2)); } - + String delay = ""; + if (null != productAttr.getDelay()) { + delay = productAttr.getDelay() + productAttr.getUnit(); + } return zbxItem.createTrapperItem(itemName, productAttr.getKey(), - hostId, productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(), delay, productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap, null); } /** @@ -207,19 +247,22 @@ public String createTrapperItem(ProductAttr productAttr) { */ public ProductAttr updateTrapperItem(ProductAttr productAttr) { ProductAttribute productAttribute = new QProductAttribute().attrId.eq(productAttr.getAttrId()).findOne(); + if (null == productAttribute) { + productAttribute = new ProductAttribute(); + } buildProdAttribute(productAttribute, productAttr); - Product prod = new QProduct().productId.eq(productAttr.getProductId()).findOne(); + Product prod = new QProduct().productId.eq(Long.parseLong(productAttr.getProductId())).findOne(); if (null == prod) { throw new ServiceException(BizExceptionEnum.PRODUCT_NOT_EXISTS); } - String hostId = prod.getZbxId(); + String hostId = prod.getZbxId(); List processingSteps = new ArrayList<>(); if (ToolUtil.isNotEmpty(productAttr.getProcessStepList())) { productAttr.getProcessStepList().forEach(i -> { ZbxProcessingStep step = new ZbxProcessingStep(); step.setType(i.getType()); - step.setParams(i.getParams()); + step.setParams(i.getParams().replaceAll("\n", "").replaceAll("\"", "\\\\\\\\\"")); processingSteps.add(step); }); @@ -231,19 +274,24 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { .collect(Collectors.toMap(ProductTag.Tag::getTag, ProductTag.Tag::getValue, (k1, k2) -> k2)); } - + String delay = ""; + if (null != productAttr.getDelay()) { + delay = productAttr.getDelay() + productAttr.getUnit(); + } zbxItem.updateTrapperItem(productAttribute.getZbxId(), productAttr.getAttrId() + "", productAttr.getKey(), - hostId, productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap); + hostId, productAttr.getSource(), delay, productAttr.getMasterItemId(), productAttr.getValueType(), productAttr.getUnits(), processingSteps, productAttr.getValuemapid(), tagMap, null); DB.update(productAttribute); - WorkerWrapper updateProdAttrWork = WorkerWrapper.builder().worker(updateProdAttrWorker).build(); + productModelEventPublisher.productModelUpdateEventPublish(productAttr); - try { - Async.work(100, updateProdAttrWork).awaitFinish(); - } catch (InterruptedException e) { - e.printStackTrace(); - } +// WorkerWrapper updateProdAttrWork = new WorkerWrapper.Builder().worker(updateProdAttrWorker).param(productAttr).build(); +// +// try { +// Async.beginWork(100, updateProdAttrWork); +// } catch (ExecutionException | InterruptedException e) { +// e.printStackTrace(); +// } return productAttr; } @@ -256,9 +304,28 @@ public ProductAttr updateTrapperItem(ProductAttr productAttr) { */ public void deleteTrapperItem(ProductAttr productAttr) { + //检查是否有属性依赖 + int count = new QProductAttribute().depAttrId.in(productAttr.getAttrIds()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_ATTR_DEPTED); + } + + //检查属性是否被告警规则引入 +// List attrIds = new QProductAttribute().select(QProductAttribute.alias().attrId).templateId.in(productAttr.getAttrIds()).findSingleAttributeList(); +// attrIds.addAll(productAttr.getAttrIds()); + count = new QProductEventExpression().productAttrId.in(productAttr.getAttrIds()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_EVENT_HASDEPTED); + } + List zbxIds = new QProductAttribute().select(QProductAttribute.alias().zbxId).attrId.in(productAttr.getAttrIds()).findSingleAttributeList(); //删除zbx item - zbxItem.deleteTrapperItem(zbxIds); + if (ToolUtil.isNotEmpty(zbxIds)) { + List itemInfos = JSONObject.parseArray(zbxItem.getItemInfo(zbxIds.toString(), null), ZbxItemInfo.class); + if (ToolUtil.isNotEmpty(itemInfos)) { + zbxItem.deleteTrapperItem(itemInfos.parallelStream().map(ZbxItemInfo::getItemid).collect(Collectors.toList())); + } + } //删除 属性 new QProductAttribute().attrId.in(productAttr.getAttrIds()).delete(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java index 49a65167..6fa25915 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductService.java @@ -3,6 +3,7 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.zmops.iot.constant.ConstantsContext; +import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.domain.device.Device; import com.zmops.iot.domain.device.Tag; import com.zmops.iot.domain.device.query.QDevice; @@ -65,6 +66,10 @@ public List prodList(ProductBasicInfo prodBasicInfo) { if (ToolUtil.isNotEmpty(prodBasicInfo.getProdName())) { qProduct.name.contains(prodBasicInfo.getProdName()); } + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + qProduct.tenantId.eq(tenantId); + } return qProduct.orderBy(" create_time desc").findList(); } @@ -83,14 +88,17 @@ public Pager getProductByPage(ProductBasicInfo prodBasicInfo) { if (ToolUtil.isNotEmpty(prodBasicInfo.getProdName())) { qProduct.name.contains(prodBasicInfo.getProdName()); } - + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + qProduct.tenantId.eq(tenantId); + } List list = qProduct.setFirstRow((prodBasicInfo.getPage() - 1) * prodBasicInfo.getMaxRow()) .setMaxRows(prodBasicInfo.getMaxRow()).orderBy(" create_time desc").asDto(ProductDto.class).findList(); if (ToolUtil.isNotEmpty(list)) { - List productIds = list.parallelStream().map(ProductDto::getProductId).collect(Collectors.toList()); - List deviceList = new QDevice().select(QDevice.alias().productId, QDevice.alias().totalCount).productId.in(productIds).findList(); - Map map = deviceList.parallelStream().collect(Collectors.toMap(Device::getProductId, Device::getTotalCount)); + List productIds = list.parallelStream().map(ProductDto::getProductId).collect(Collectors.toList()); + List deviceList = new QDevice().select(QDevice.alias().productId, QDevice.alias().totalCount).productId.in(productIds).findList(); + Map map = deviceList.parallelStream().collect(Collectors.toMap(Device::getProductId, Device::getTotalCount, (a, b) -> a)); for (ProductDto productDto : list) { productDto.setDeviceNum(Optional.ofNullable(map.get(productDto.getProductId())).orElse(0L)); } @@ -119,8 +127,12 @@ public String zbxTemplateCreate(String templateName) { * @param templdateId 模板ID * @return */ - public String zbxTemplateDelete(String templdateId) { - return zbxTemplate.templateDelete(templdateId); + public void zbxTemplateDelete(String templdateId) { + + JSONArray jsonArray = JSONObject.parseArray(zbxTemplate.templateGet(templdateId)); + if (jsonArray.size() > 0) { + zbxTemplate.templateDelete(templdateId); + } } /** @@ -219,7 +231,8 @@ private static Product buildPord(ProductBasicInfo prodBasicInfo) { product.setRemark(prodBasicInfo.getRemark()); product.setType(prodBasicInfo.getProdType()); product.setGroupId(prodBasicInfo.getGroupId()); - + product.setTenantId(prodBasicInfo.getTenantId()); + product.setIcon(prodBasicInfo.getIcon()); return product; } @@ -241,7 +254,7 @@ public ProductDto prodDetail(Long prodId) { * @param prodId * @return */ - public List prodTagList(Long prodId) { + public List prodTagList(String prodId) { QTag tag = QTag.alias(); return new QTag().select(tag.id, tag.sid, tag.tag, tag.value).sid.eq(prodId).orderBy(" create_time desc").findList(); } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java new file mode 100644 index 00000000..bcb1627d --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductSvcService.java @@ -0,0 +1,260 @@ +package com.zmops.iot.web.product.service; + +import com.zmops.iot.domain.product.ProductService; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.domain.product.ProductServiceRelation; +import com.zmops.iot.domain.product.query.QProductEventService; +import com.zmops.iot.domain.product.query.QProductService; +import com.zmops.iot.domain.product.query.QProductServiceParam; +import com.zmops.iot.domain.product.query.QProductServiceRelation; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductServiceCreateEvent; +import com.zmops.iot.web.event.applicationEvent.ProductServiceUpdateEvent; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductServiceDto; +import com.zmops.iot.web.product.dto.param.ProductSvcParam; +import io.ebean.DB; +import io.ebean.DtoQuery; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 产品 物模型 服务 + **/ +@Service +public class ProductSvcService implements CommandLineRunner { + + @Autowired + ApplicationEventPublisher publisher; + + /** + * 服务分页列表 + * + * @param productSvcParam + * @return + */ + public Pager getServiceByPage(ProductSvcParam productSvcParam) { + StringBuilder sql = new StringBuilder("SELECT s.*,r.inherit from product_service s LEFT JOIN product_service_relation r on r.service_id=s.id where 1=1 "); + QProductService qProductService = new QProductService(); + if (ToolUtil.isNotEmpty(productSvcParam.getName())) { + sql.append(" and s.name like :name"); + qProductService.name.contains(productSvcParam.getName()); + } + if (ToolUtil.isNotEmpty(productSvcParam.getMark())) { + sql.append(" and s.mark like :mark"); + qProductService.mark.contains(productSvcParam.getMark()); + } + if (ToolUtil.isNotEmpty(productSvcParam.getProdId())) { + sql.append(" and r.relation_id = :relationId"); + List serviceIds = getServiceIdList(productSvcParam.getProdId()); + if (ToolUtil.isNotEmpty(serviceIds)) { + qProductService.id.in(serviceIds); + } + } + sql.append(" order by id desc"); + DtoQuery query = DB.findDto(ProductServiceDto.class, sql.toString()); + if (ToolUtil.isNotEmpty(productSvcParam.getName())) { + query.setParameter("name", "%" + productSvcParam.getName() + "%"); + } + if (ToolUtil.isNotEmpty(productSvcParam.getMark())) { + query.setParameter("mark", "%" + productSvcParam.getMark() + "%"); + } + if (ToolUtil.isNotEmpty(productSvcParam.getProdId())) { + query.setParameter("relationId", productSvcParam.getProdId()); + } + + List productServiceDtoList = query.setFirstRow((productSvcParam.getPage() - 1) * productSvcParam.getMaxRow()) + .setMaxRows(productSvcParam.getMaxRow()).findList(); + + if (ToolUtil.isEmpty(productServiceDtoList)) { + return new Pager<>(productServiceDtoList, 0); + } + //查询关联的参数 + List sids = productServiceDtoList.parallelStream().map(ProductServiceDto::getId).collect(Collectors.toList()); + List serviceParamList = new QProductServiceParam().serviceId.in(sids).deviceId.eq(productSvcParam.getProdId()).findList(); + Map> map = serviceParamList.parallelStream().collect(Collectors.groupingBy(ProductServiceParam::getServiceId)); + productServiceDtoList.forEach(productServiceDto -> { + if (null != map.get(productServiceDto.getId())) { + productServiceDto.setProductServiceParamList(map.get(productServiceDto.getId())); + } + }); + return new Pager<>(productServiceDtoList, qProductService.findCount()); + } + + /** + * 服务列表 + * + * @param productSvcParam + * @return + */ + public List list(ProductSvcParam productSvcParam) { + QProductService qProdService = new QProductService(); + if (ToolUtil.isNotEmpty(productSvcParam.getName())) { + qProdService.name.contains(productSvcParam.getName()); + } + if (ToolUtil.isNotEmpty(productSvcParam.getProdId())) { + List serviceIds = getServiceIdList(productSvcParam.getProdId()); + if (ToolUtil.isEmpty(serviceIds)) { + return Collections.emptyList(); + } + qProdService.id.in(serviceIds); + } + if (ToolUtil.isNotEmpty(productSvcParam.getMark())) { + qProdService.mark.contains(productSvcParam.getMark()); + } + qProdService.orderBy(" id desc"); + return qProdService.findList(); + } + + /** + * 服务创建 + * + * @param productServiceDto + * @return + */ + @Transactional(rollbackFor = Exception.class) + public ProductServiceDto create(ProductServiceDto productServiceDto) { + //查询 是否已存在同名服务 + List serviceIds = getServiceIdList(productServiceDto.getRelationId()); + if (ToolUtil.isNotEmpty(serviceIds)) { + int count = new QProductService().name.eq(productServiceDto.getName()).id.in(serviceIds).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.SERVICE_EXISTS); + } + } + //保存服务 + ProductService productService = new ProductService(); + ToolUtil.copyProperties(productServiceDto, productService); + DB.save(productService); + Long serviceId = productService.getId(); + productServiceDto.setId(serviceId); + + //保存服务与产品 关联关系 + ProductServiceRelation productServiceRelation = new ProductServiceRelation(); + productServiceRelation.setServiceId(productService.getId()); + productServiceRelation.setRelationId(productServiceDto.getRelationId()); + DB.save(productServiceRelation); + + //保存服务参数 + if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { + for (ProductServiceParam productServiceParam : productServiceDto.getProductServiceParamList()) { + productServiceParam.setServiceId(null); + productServiceParam.setServiceId(serviceId); + productServiceParam.setDeviceId(productServiceDto.getRelationId()); + } + DB.saveAll(productServiceDto.getProductServiceParamList()); + } + + //同步到设备 + + if (ToolUtil.isNum(productServiceDto.getRelationId())) { + publisher.publishEvent(new ProductServiceCreateEvent(this, productServiceDto)); + } + updateService(); + return productServiceDto; + } + + /** + * 服务修改 + * + * @param productServiceDto + * @return + */ + public ProductServiceDto update(ProductServiceDto productServiceDto) { + //查询 是否已存在同名服务 + List serviceIds = getServiceIdList(productServiceDto.getRelationId()); + if (ToolUtil.isNotEmpty(serviceIds)) { + int count = new QProductService().name.eq(productServiceDto.getName()).id.in(serviceIds) + .id.ne(productServiceDto.getId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.SERVICE_EXISTS); + } + } + + //保存服务 + ProductService productService = new ProductService(); + ToolUtil.copyProperties(productServiceDto, productService); + DB.update(productService); + + //重新保存服务参数 + new QProductServiceParam().serviceId.eq(productServiceDto.getId()).deviceId.eq(productServiceDto.getRelationId()).delete(); + if (ToolUtil.isNotEmpty(productServiceDto.getProductServiceParamList())) { + for (ProductServiceParam productServiceParam : productServiceDto.getProductServiceParamList()) { + productServiceParam.setServiceId(productServiceDto.getId()); + productServiceParam.setDeviceId(productServiceDto.getRelationId()); + } + DB.saveAll(productServiceDto.getProductServiceParamList()); + } + + //同步到设备 + + + if (ToolUtil.isNum(productServiceDto.getRelationId())) { + publisher.publishEvent(new ProductServiceUpdateEvent(this, productServiceDto)); + } + updateService(); + return productServiceDto; + } + + private List getServiceIdList(String relationId) { + return new QProductServiceRelation().select(QProductServiceRelation.Alias.serviceId).relationId.eq(relationId) + .findSingleAttributeList(); + } + + /** + * 服务删除 + * + * @param ids + * @return + */ + public void delete(List ids) { + + //检查服务是否被 告警 联动规则引用 + int count = new QProductEventService().serviceId.in(ids).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PRODUCT_EVENT_HAS_DEPTED); + } + + new QProductServiceParam().serviceId.in(ids).delete(); + new QProductServiceRelation().serviceId.in(ids).delete(); + new QProductService().id.in(ids).delete(); + } + + /** + * 根据服务 获取参数列表 + */ + public List paramList(long serviceId) { + return new QProductServiceParam().serviceId.eq(serviceId).findList(); + } + + /** + * 更新服务名称 服务参数 缓存 + */ + private void updateService() { + List serviceList = new QProductService().findList(); + Map map = serviceList.parallelStream().collect(Collectors.toMap(ProductService::getId, ProductService::getName, (a, b) -> a)); + DefinitionsUtil.updateServiceCache(map); + + List serviceParamList = new QProductServiceParam().findList(); + Map> paramMap = serviceParamList.parallelStream().collect(Collectors.groupingBy(ProductServiceParam::getServiceId)); + DefinitionsUtil.updateServiceParamCache(paramMap); + } + + @Override + public void run(String... args) throws Exception { + updateService(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java index cfedf564..f719a095 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTriggerService.java @@ -1,16 +1,32 @@ package com.zmops.iot.web.product.service; +import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.product.ProductStatusFunction; +import com.zmops.iot.domain.product.ProductStatusFunctionRelation; +import com.zmops.iot.domain.product.query.QProductStatusFunction; +import com.zmops.iot.domain.product.query.QProductStatusFunctionRelation; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.ProductStatusFunctionDto; import com.zmops.iot.web.product.dto.ProductStatusJudgeRule; +import com.zmops.iot.web.product.dto.ZbxTriggerInfo; import com.zmops.zeus.driver.service.ZbxDeviceStatusTrigger; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; import lombok.Data; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; -import static com.zmops.iot.web.product.dto.ProductStatusJudgeRule.OFF_LINE; -import static com.zmops.iot.web.product.dto.ProductStatusJudgeRule.ON_LINE; -import static com.zmops.iot.web.product.dto.ProductStatusJudgeRule.NODATA; -import static com.zmops.iot.web.product.dto.ProductStatusJudgeRule.LASTDATA; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; /** * @author nantian created at 2021/8/10 17:55 @@ -26,6 +42,24 @@ public class ProductTriggerService { @Autowired private ZbxDeviceStatusTrigger deviceStatusTrigger; + @Autowired + private ZbxTrigger zbxTrigger; + + /** + * 离线 或者 在线触发器 信息 + * + * @param relationId 在线规则 + * @return ResponseData + */ + public ProductStatusFunctionDto getRule(String relationId) { + String sql = "select s.*,p.name attrName,p2.name attrNameRecovery,p.units,p2.units unitsRecovery " + + " from product_status_function s" + + " LEFT JOIN product_attribute p on p.attr_id = s.attr_id" + + " LEFT JOIN product_attribute p2 on p2.attr_id = s.attr_id_recovery" + + " where s.rule_id in (select rule_id from product_status_function_relation where relation_id = :relationId)"; + return DB.findDto(ProductStatusFunctionDto.class, sql).setParameter("relationId", relationId).findOne(); + } + /** * 创建 设备状态 触发器 @@ -33,42 +67,145 @@ public class ProductTriggerService { * @param judgeRule 判断规则 * @return Integer */ - public Integer createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { - - String triggerName = judgeRule.getTriggerName(); - String hostName = judgeRule.getHostName(); - String itemKey = judgeRule.getItemKey(); - String ruleValue = judgeRule.getRuleValue(); - - if (NODATA.equals(judgeRule.getRuleFunction())) { - // 上线触发器 - if (ON_LINE.equals(judgeRule.getRuleType())) { - return getTriggerId(deviceStatusTrigger.nodataOnline(hostName, itemKey, ruleValue, triggerName)); + @Transactional(rollbackFor = Exception.class) + public Long createDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { + + long ruleId = IdUtil.getSnowflake().nextId(); + judgeRule.setRuleId(ruleId); + //step 1:保存到zbx 建立上线及下线规则 + String ruleCondition = judgeRule.getRuleCondition(); + if(!ToolUtil.isNum(ruleCondition)){ + ruleCondition = "\""+ruleCondition+"\""; + } + String res = deviceStatusTrigger.createDeviceStatusTrigger(judgeRule.getRuleId() + "", judgeRule.getRelationId(), + judgeRule.getProductAttrKey(), ruleCondition + judgeRule.getUnit(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), + judgeRule.getRuleConditionRecovery() + judgeRule.getUnitRecovery(), judgeRule.getRuleFunctionRecovery()); + + String[] triggerIds = getTriggerId(res); + + //step 2:保存规则 + ProductStatusFunction productStatusFunction = new ProductStatusFunction(); + BeanUtils.copyProperties(judgeRule, productStatusFunction); + productStatusFunction.setRuleId(ruleId); + DB.save(productStatusFunction); + + //step 3:保存规则与产品的关联关系 + ProductStatusFunctionRelation productStatusFunctionRelation = new ProductStatusFunctionRelation(); + productStatusFunctionRelation.setRelationId(judgeRule.getRelationId()); + productStatusFunctionRelation.setRuleId(ruleId); + //对应zbx下线规则ID + productStatusFunctionRelation.setZbxId(triggerIds[0]); + //对应zbx上线规则ID + productStatusFunctionRelation.setZbxIdRecovery(triggerIds[1]); + DB.save(productStatusFunctionRelation); + + //step 4:同步到设备 + String relationId = judgeRule.getRelationId(); + if (ToolUtil.isNum(relationId)) { + //查询出继承了此产品的设备 + String sql = "select device_id from device where product_id = :productId and device_id not in (select relation_id from product_status_function_relation where inherit='0')"; + List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", Long.parseLong(relationId)).findList(); + if (ToolUtil.isEmpty(deviceDtoList)) { + return productStatusFunction.getRuleId(); } - if (OFF_LINE.equals(judgeRule.getRuleType())) { - return getTriggerId(deviceStatusTrigger.nodataOffline(hostName, itemKey, ruleValue, triggerName)); + //从Zbx 查询出所有设备的 名称是 judgeRule.getRuleId() 的触发器 + String triggerRes = zbxTrigger.triggerGetByName(judgeRule.getRuleId() + ""); + if (ToolUtil.isEmpty(triggerRes)) { + return productStatusFunction.getRuleId(); } + List zbxTriggerInfoList = JSONObject.parseArray(triggerRes, ZbxTriggerInfo.class); + Map hostTriggerMap = zbxTriggerInfoList.parallelStream().filter(o -> o.getTags().parallelStream().anyMatch(t -> "__offline__".equals(t.getTag()))) + .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid, (a, b) -> a)); + Map hostRecoveryTriggerMap = zbxTriggerInfoList.parallelStream().filter(o -> o.getTags().parallelStream().anyMatch(t -> "__online__".equals(t.getTag()))) + .collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ZbxTriggerInfo::getTriggerid, (a, b) -> a)); + + //保存 设备与规则的关系 + deviceDtoList.forEach(deviceDto -> { + String zbxId = Optional.ofNullable(hostTriggerMap.get(deviceDto.getDeviceId())).orElse(""); + String zbxIdRecovery = Optional.ofNullable(hostRecoveryTriggerMap.get(deviceDto.getDeviceId())).orElse(""); + + DB.sqlUpdate("insert into product_status_function_relation (relation_id,rule_id,inherit,zbx_id,zbx_id_recovery) SELECT :deviceId,rule_id,1,:zbxId,:zbxIdRecovery from product_status_function_relation where relation_id=:relationId") + .setParameter("deviceId", deviceDto.getDeviceId()).setParameter("relationId", judgeRule.getRelationId() + "") + .setParameter("zbxId", zbxId) + .setParameter("zbxIdRecovery", zbxIdRecovery) + .execute(); + }); } - if (LASTDATA.equals(judgeRule.getRuleFunction())) { - return getTriggerId(deviceStatusTrigger.lastValueJudge(hostName, itemKey, ruleValue, triggerName)); + return productStatusFunction.getRuleId(); + } + + /** + * 修改 触发器 + * + * @param judgeRule 判断规则 + * @return Integer + */ + public Long updateDeviceStatusJudgeTrigger(ProductStatusJudgeRule judgeRule) { + + ProductStatusFunctionRelation relation = new QProductStatusFunctionRelation().ruleId.eq(judgeRule.getRuleId()).relationId.eq(judgeRule.getRelationId()).findOne(); + if (null == relation) { + return judgeRule.getRuleId(); } + String ruleCondition = judgeRule.getRuleCondition(); + if(!ToolUtil.isNum(ruleCondition)){ + ruleCondition = "\""+ruleCondition+"\""; + } + deviceStatusTrigger.updateDeviceStatusTrigger(relation.getZbxId(), judgeRule.getRuleId() + "", judgeRule.getRelationId(), + judgeRule.getProductAttrKey(), ruleCondition + judgeRule.getUnit(), judgeRule.getRuleFunction(), judgeRule.getProductAttrKeyRecovery(), + judgeRule.getRuleConditionRecovery() + judgeRule.getUnitRecovery(), judgeRule.getRuleFunctionRecovery(), relation.getZbxIdRecovery()); + + ProductStatusFunction productStatusFunction = new ProductStatusFunction(); + BeanUtils.copyProperties(judgeRule, productStatusFunction); + DB.update(productStatusFunction); + + return judgeRule.getRuleId(); + } + + /** + * 值拷贝 + * + * @param rule 新规则 + * @param judgeRule 规则 + */ + private void buildTriggerCreateMap(Map rule, ProductStatusJudgeRule judgeRule) { + rule.put("ruleId", judgeRule.getRuleId() + ""); + rule.put("deviceId", judgeRule.getRelationId()); + + rule.put("ruleFunction", judgeRule.getRuleFunction()); + rule.put("ruleCondition", judgeRule.getRuleCondition()); + rule.put("itemKey", judgeRule.getProductAttrKey()); - return null; + rule.put("itemKeyRecovery", judgeRule.getProductAttrKeyRecovery()); + rule.put("ruleConditionRecovery", judgeRule.getRuleConditionRecovery()); + rule.put("ruleFunctionRecovery", judgeRule.getRuleFunctionRecovery()); } - private Integer getTriggerId(String responseStr) { + + private String[] getTriggerId(String responseStr) { TriggerIds ids = JSON.parseObject(responseStr, TriggerIds.class); - if (null != ids && ids.getTriggerids().length > 0) { - return ids.getTriggerids()[0]; + if (null == ids || ids.getTriggerids().length != 2) { + throw new ServiceException(BizExceptionEnum.ZBX_CALL_ERR); } - return null; + return ids.getTriggerids(); + } + + /** + * 删除 离线 或者 在线触发器 + */ + @Transactional(rollbackFor = Exception.class) + public void deleteDeviceStatusTrigger(Long ruleId) { + new QProductStatusFunctionRelation().ruleId.eq(ruleId).delete(); + + new QProductStatusFunction().ruleId.eq(ruleId).delete(); } @Data static class TriggerIds { - Integer[] triggerids; + String[] triggerids; } + + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java index ef09c156..10ab73cd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/ProductTypeService.java @@ -1,5 +1,6 @@ package com.zmops.iot.web.product.service; +import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.core.tree.DefaultTreeBuildFactory; import com.zmops.iot.domain.product.ProductType; import com.zmops.iot.domain.product.query.QProduct; @@ -29,8 +30,16 @@ public class ProductTypeService implements CommandLineRunner { * 产品分类树 */ public List tree() { - String sql = "select id,pid pId,name,pids from product_type"; - List list = DB.findDto(TreeNode.class, sql).findList(); + + String sql = "select p.id,p.pid pId,p.name,p.pids,t.name tenantName,p.create_time,u.name createUserName from product_type p " + + " LEFT JOIN tenant_info t on t.tenant_id = p.tenant_id " + + " LEFT JOIN sys_user u on u.user_id = p.create_user"; + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + sql += " where p.tenant_id = " + tenantId; + } + + List list = DB.findDto(TreeNode.class, sql).findList(); DefaultTreeBuildFactory treeBuildFactory = new DefaultTreeBuildFactory<>(); treeBuildFactory.setRootParentId("0"); return treeBuildFactory.doTreeBuild(list); @@ -44,7 +53,7 @@ public List tree() { */ public ProductType create(ProductTypeParam productTypeParam) { - int count = new QProductType().name.eq(productTypeParam.getName()) + int count = new QProductType().name.eq(productTypeParam.getName()).tenantId.eq(productTypeParam.getTenantId()) .pid.eq(productTypeParam.getPid()) .findCount(); if (count > 0) { @@ -69,7 +78,7 @@ public Object update(ProductTypeParam productTypeParam) { if (oldProTypeCount <= 0) { throw new ServiceException(BizExceptionEnum.PRODUCT_TYPE_NOT_EXIST); } - int count = new QProductType().name.eq(productTypeParam.getName()) + int count = new QProductType().name.eq(productTypeParam.getName()).tenantId.eq(productTypeParam.getTenantId()) .pid.eq(productTypeParam.getPid()) .id.ne(productTypeParam.getId()) .findCount(); @@ -109,7 +118,7 @@ private void setPids(ProductType productType) { if (productType.getPid().equals(0L)) { productType.setPids("[0],"); } else { - Long pid = productType.getPid(); + Long pid = productType.getPid(); ProductType temp = new QProductType().id.eq(pid).findOne(); if (null == temp) { throw new ServiceException(BizExceptionEnum.PRODUCT_TYPE_PID_NOT_EXIST); @@ -130,7 +139,7 @@ private void updateProductType() { if (ToolUtil.isEmpty(list)) { return; } - DefinitionsUtil.updateProductType(list.parallelStream().collect(Collectors.toMap(ProductType::getId, ProductType::getName))); + DefinitionsUtil.updateProductType(list.parallelStream().collect(Collectors.toMap(ProductType::getId, ProductType::getName, (a, b) -> a))); } @Override diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/AsyncAttrEventZbxIdEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/AsyncAttrEventZbxIdEventHandler.java new file mode 100644 index 00000000..be47bad0 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/AsyncAttrEventZbxIdEventHandler.java @@ -0,0 +1,63 @@ +package com.zmops.iot.web.product.service.event; + + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.product.ProductAttributeEvent; +import com.zmops.iot.domain.product.query.QProductAttributeEvent; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductAttrCreateEvent; +import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.zeus.driver.entity.ZbxItemInfo; +import com.zmops.zeus.driver.service.ZbxItem; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 更新设备属性事件中ZBXID + */ +@Slf4j +@Component +@EnableAsync +public class AsyncAttrEventZbxIdEventHandler implements ApplicationListener { + + @Autowired + ZbxItem zbxItem; + + @Override + @Async + public void onApplicationEvent(ProductAttrCreateEvent event) { + log.debug("AsyncAttrEventZbxIdWorker……"); + ProductAttr productAttr = event.getEventData(); + Long attrId = productAttr.getAttrId(); + + //根据name 取出监控项 + List itemInfos = JSONObject.parseArray(zbxItem.getItemListByName(attrId + ""), ZbxItemInfo.class); + if (ToolUtil.isEmpty(itemInfos)) { + return; + } + + Map itemMap = itemInfos.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), o -> o)); + //取出继承的属性 并塞入对应的 itemId + List productAttributeEventList = new QProductAttributeEvent().templateId.eq(attrId).findList(); + for (ProductAttributeEvent productAttributeEvent : productAttributeEventList) { + if (itemMap.get(productAttributeEvent.getProductId() + "") == null) { + continue; + } + productAttributeEvent.setZbxId(itemMap.get(productAttributeEvent.getProductId() + "").getItemid()); + } + + DB.updateAll(productAttributeEventList); + + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/AsyncAttrZbxIdEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/AsyncAttrZbxIdEventHandler.java new file mode 100644 index 00000000..37bf9770 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/AsyncAttrZbxIdEventHandler.java @@ -0,0 +1,58 @@ +package com.zmops.iot.web.product.service.event; + + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductModelCreateEvent; +import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.zeus.driver.entity.ZbxItemInfo; +import com.zmops.zeus.driver.service.ZbxItem; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 更新设备属性中ZBXID + */ +@Slf4j +@Component +@Order(1) +public class AsyncAttrZbxIdEventHandler implements ApplicationListener { + + @Autowired + ZbxItem zbxItem; + + @Override + public void onApplicationEvent(ProductModelCreateEvent event) { + log.debug("AsyncAttrZbxIdWorker……"); + ProductAttr productAttr = event.getEventData(); + Long attrId = productAttr.getAttrId(); + + //根据name 取出监控项 + List itemInfos = JSONObject.parseArray(zbxItem.getItemListByName(attrId + ""), ZbxItemInfo.class); + if (ToolUtil.isEmpty(itemInfos)) { + return; + } + + Map itemMap = itemInfos.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), o -> o)); + //取出继承的属性 并塞入对应的 itemId + List productAttributeList = new QProductAttribute().templateId.eq(attrId).findList(); + for (ProductAttribute productAttribute : productAttributeList) { + productAttribute.setZbxId(itemMap.get(productAttribute.getProductId() + "").getItemid()); + } + + DB.updateAll(productAttributeList); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventEventHandler.java new file mode 100644 index 00000000..924734f4 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventEventHandler.java @@ -0,0 +1,58 @@ +package com.zmops.iot.web.product.service.event; + + +import cn.hutool.core.util.IdUtil; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductAttributeEvent; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductAttrCreateEvent; +import com.zmops.iot.web.product.dto.ProductAttr; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author yefei + *

+ * 产品属性事件创建 同步到设备 步骤 + */ +@Slf4j +@Component +public class SaveProdAttrEventEventHandler implements ApplicationListener { + + + @Override + @Async + public void onApplicationEvent(ProductAttrCreateEvent event) { + log.debug("SaveProdAttrEventTriggerWorker…………"); + ProductAttr productAttr = event.getEventData(); + String prodId = productAttr.getProductId(); + + int count = new QDevice().deviceId.eq(prodId).findCount(); + if (count > 0) { + return; + } + + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + + List productAttributeEventList = new ArrayList<>(); + + for (String deviceId : deviceIds) { + ProductAttributeEvent productAttributeEvent = new ProductAttributeEvent(); + ToolUtil.copyProperties(productAttr, productAttributeEvent); + productAttributeEvent.setAttrId(IdUtil.getSnowflake().nextId()); + productAttributeEvent.setName(productAttr.getAttrName()); + productAttributeEvent.setProductId(deviceId); + productAttributeEvent.setTemplateId(productAttr.getAttrId()); + productAttributeEventList.add(productAttributeEvent); + } + DB.saveAll(productAttributeEventList); + + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventHandler.java new file mode 100644 index 00000000..02c91704 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventHandler.java @@ -0,0 +1,76 @@ +package com.zmops.iot.web.product.service.event; + + +import cn.hutool.core.util.IdUtil; +import com.zmops.iot.domain.product.ProductAttribute; +import com.zmops.iot.domain.product.query.QProductAttribute; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.DeviceDto; +import com.zmops.iot.web.event.applicationEvent.ProductModelCreateEvent; +import com.zmops.iot.web.product.dto.ProductAttr; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 产品属性创建 同步到设备 步骤 + */ +@Slf4j +@Component +@Order(0) +public class SaveProdAttrEventHandler implements ApplicationListener { + + private static final String ATTR_SOURCE_DEPEND = "18"; + + @Override + public void onApplicationEvent(ProductModelCreateEvent event) { + log.debug("SaveProdAttrWorker…………"); + ProductAttr productAttr = event.getEventData(); + + String sql = "select device_id from device " + + " where product_id = :productId and device_id not in (" + + " select product_id from product_attribute " + + " where template_id is null and key = :key)"; + + List deviceDtoList = DB.findDto(DeviceDto.class, sql).setParameter("productId", Long.parseLong(productAttr.getProductId())) + .setParameter("key", productAttr.getKey()).findList(); + List productAttributeList = new ArrayList<>(); + + if (ToolUtil.isEmpty(deviceDtoList)) { + return; + } + + //处理依赖属性 + Map attrIdMap = new ConcurrentHashMap<>(deviceDtoList.size()); + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource())) { + List list = new QProductAttribute().templateId.eq(productAttr.getDepAttrId()).findList(); + attrIdMap = list.parallelStream().collect(Collectors.toMap(ProductAttribute::getProductId, ProductAttribute::getAttrId, (a, b) -> a)); + } + + for (DeviceDto deviceDto : deviceDtoList) { + ProductAttribute productAttrbute = new ProductAttribute(); + ToolUtil.copyProperties(productAttr, productAttrbute); + productAttrbute.setAttrId(IdUtil.getSnowflake().nextId()); + productAttrbute.setName(productAttr.getAttrName()); + productAttrbute.setProductId(deviceDto.getDeviceId()); + productAttrbute.setTemplateId(productAttr.getAttrId()); + if (ATTR_SOURCE_DEPEND.equals(productAttr.getSource()) && null != attrIdMap.get(deviceDto.getDeviceId())) { + productAttrbute.setDepAttrId(attrIdMap.get(deviceDto.getDeviceId())); + } + productAttributeList.add(productAttrbute); + } + DB.saveAll(productAttributeList); + + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventTriggerEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventTriggerEventHandler.java new file mode 100644 index 00000000..17a71967 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdAttrEventTriggerEventHandler.java @@ -0,0 +1,57 @@ +package com.zmops.iot.web.product.service.event; + + +import com.alibaba.fastjson.JSON; +import com.zmops.iot.web.event.applicationEvent.ProductAttrCreateEvent; +import com.zmops.iot.web.product.dto.ProductAttr; +import com.zmops.zeus.driver.service.ZbxTrigger; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author yefei + *

+ * 产品属性事件创建 告警 步骤 + */ +@Slf4j +@Component +public class SaveProdAttrEventTriggerEventHandler implements ApplicationListener { + + @Autowired + private ZbxTrigger zbxTrigger; + private static final String EVENT_TAG_NAME = "__event__"; + + @Override + @Async + public void onApplicationEvent(ProductAttrCreateEvent event) { + log.debug("SaveProdAttrEventTriggerWorker…………"); + ProductAttr productAttr = event.getEventData(); + String prodId = productAttr.getProductId(); + StringBuilder expression = new StringBuilder(); + expression.append("count(/"); + expression.append(prodId); + expression.append("/"); + expression.append(productAttr.getKey()); + expression.append(",#1"); + expression.append(") >0 "); + String res = zbxTrigger.triggerCreate(productAttr.getAttrName(), expression.toString(), productAttr.getEventLevel(),1); + + String[] triggerids = JSON.parseObject(res, TriggerIds.class).getTriggerids(); + Map tags = new ConcurrentHashMap<>(1); + tags.put(EVENT_TAG_NAME, "{HOST.HOST}##" + productAttr.getKey()); + zbxTrigger.triggerTagCreate(triggerids[0], tags); + + } + + @Data + static class TriggerIds { + private String[] triggerids; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdStatusTriggerEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdStatusTriggerEventHandler.java new file mode 100644 index 00000000..f36d1e89 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdStatusTriggerEventHandler.java @@ -0,0 +1,42 @@ +package com.zmops.iot.web.product.service.event; + + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * @author yefei + *

+ * 产品服务创建 同步到设备 步骤 + */ +@Slf4j +@Component +public class SaveProdStatusTriggerEventHandler {//implements IWorker + + +// @Override +// public Boolean action(ProductServiceDto productServiceDto, Map map) { +// +// String prodId = productServiceDto.getRelationId(); +// +// List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); +// List productStatusFunctionRelationList = new ArrayList<>(); +// for (String deviceId : deviceIds) { +// ProductStatusFunctionRelation productStatusFunctionRelation = new ProductStatusFunctionRelation(); +// productStatusFunctionRelation.setRelationId(deviceId); +// productStatusFunctionRelation.setRuleId(productServiceDto.getId()); +// productStatusFunctionRelation.setInherit("1"); +// productStatusFunctionRelationList.add(productStatusFunctionRelation); +// } +// DB.saveAll(productStatusFunctionRelationList); +// +// return true; +// } +// +// +// @Override +// public Boolean defaultValue() { +// return true; +// } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdSvcEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdSvcEventHandler.java new file mode 100644 index 00000000..fd9d539e --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProdSvcEventHandler.java @@ -0,0 +1,68 @@ +package com.zmops.iot.web.product.service.event; + + +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.domain.product.ProductServiceRelation; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductServiceCreateEvent; +import com.zmops.iot.web.product.dto.ProductServiceDto; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author yefei + *

+ * 产品服务创建 同步到设备 步骤 + */ +@Slf4j +@Component +@EnableAsync +public class SaveProdSvcEventHandler implements ApplicationListener { + + + @Override + @Async + public void onApplicationEvent(ProductServiceCreateEvent event) { + ProductServiceDto productServiceDto = event.getEventData(); + String prodId = productServiceDto.getRelationId(); + + //查询出 继承了此产品的设备 + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + if (ToolUtil.isEmpty(deviceIds)) { + return; + } + + List productServiceRelationList = new ArrayList<>(); + List productServiceParamList = new ArrayList<>(); + for (String deviceId : deviceIds) { + //保存设备与服务的关联关系 + ProductServiceRelation productServiceRelation = new ProductServiceRelation(); + productServiceRelation.setRelationId(deviceId); + productServiceRelation.setServiceId(productServiceDto.getId()); + productServiceRelation.setInherit("1"); + productServiceRelationList.add(productServiceRelation); + + //保存设备与服务参数的关联关系 + productServiceDto.getProductServiceParamList().forEach(productServiceParam -> { + ProductServiceParam param = new ProductServiceParam(); + ToolUtil.copyProperties(productServiceParam, param); + param.setId(null); + param.setDeviceId(deviceId); + param.setServiceId(productServiceDto.getId()); + productServiceParamList.add(param); + }); + } + DB.saveAll(productServiceRelationList); + DB.saveAll(productServiceParamList); + + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProductEventTriggerEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProductEventTriggerEventHandler.java new file mode 100644 index 00000000..2dd94dc6 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/SaveProductEventTriggerEventHandler.java @@ -0,0 +1,83 @@ +package com.zmops.iot.web.product.service.event; + + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductEventRelation; +import com.zmops.iot.domain.product.ProductEventService; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.enums.InheritStatus; +import com.zmops.iot.web.event.applicationEvent.ProductEventTriggerCreateEvent; +import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.iot.web.product.service.ProductEventRuleService; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 产品服务创建 同步到设备 步骤 + */ +@Slf4j +@Component +@EnableAsync +public class SaveProductEventTriggerEventHandler implements ApplicationListener { + + + @Autowired + ZbxTrigger zbxTrigger; + + @Override + @Async + public void onApplicationEvent(ProductEventTriggerCreateEvent event) { + log.debug("SaveProductEventTriggerWorker…………"); + ProductEventRule productEventRule = event.getEventData(); + String prodId = productEventRule.getProductId(); + + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + List triggers = JSONObject.parseArray(zbxTrigger.triggerGetByName(productEventRule.getEventRuleId() + ""), ProductEventRuleService.Triggers.class); + + Map treiggerMap = triggers.parallelStream().collect(Collectors.toMap(o -> o.getHosts().get(0).getHost(), ProductEventRuleService.Triggers::getTriggerid, (a, b) -> a)); + + List productEventRelationList = new ArrayList<>(); + List addProductEventServiceList = new ArrayList<>(); + + for (String deviceId : deviceIds) { + ProductEventRelation productEventRelation = new ProductEventRelation(); + productEventRelation.setRelationId(deviceId); + productEventRelation.setEventRuleId(productEventRule.getEventRuleId()); + productEventRelation.setInherit(InheritStatus.YES.getCode()); + productEventRelation.setStatus(CommonStatus.ENABLE.getCode()); + productEventRelation.setRemark(productEventRule.getRemark()); + if (null != treiggerMap.get(deviceId)) { + productEventRelation.setZbxId(treiggerMap.get(deviceId)); + } + productEventRelationList.add(productEventRelation); + + productEventRule.getDeviceServices().forEach(productEventService -> { + ProductEventService newProductEventService = new ProductEventService(); + newProductEventService.setDeviceId(deviceId); + newProductEventService.setExecuteDeviceId(deviceId); + newProductEventService.setEventRuleId(productEventRule.getEventRuleId()); + newProductEventService.setServiceId(productEventService.getServiceId()); + addProductEventServiceList.add(newProductEventService); + }); + } + DB.saveAll(productEventRelationList); + + DB.saveAll(addProductEventServiceList); + + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/UpdateAttributeEventEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/UpdateAttributeEventEventHandler.java new file mode 100644 index 00000000..86d0156a --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/UpdateAttributeEventEventHandler.java @@ -0,0 +1,44 @@ +package com.zmops.iot.web.product.service.event; + + +import com.zmops.iot.domain.product.ProductAttributeEvent; +import com.zmops.iot.domain.product.query.QProductAttributeEvent; +import com.zmops.iot.web.event.applicationEvent.ProductAttrCreateEvent; +import com.zmops.iot.web.product.dto.ProductAttr; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @author yefei + *

+ * 产品属性修改 同步到设备 步骤 + */ +@Slf4j +@Component +public class UpdateAttributeEventEventHandler implements ApplicationListener { + + + @Override + @Async + public void onApplicationEvent(ProductAttrCreateEvent event) { + log.debug("UpdateAttributeEventWorker…………"); + ProductAttr productAttr = event.getEventData(); + + List list = new QProductAttributeEvent().templateId.eq(productAttr.getAttrId()).findList(); + + for (ProductAttributeEvent productAttributeEvent : list) { + productAttributeEvent.setName(productAttr.getAttrName()); + productAttributeEvent.setKey(productAttr.getKey()); + productAttributeEvent.setUnits(productAttr.getUnits()); + productAttributeEvent.setValueType(productAttr.getValueType()); + } + DB.updateAll(list); + + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/UpdateProdSvcEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/UpdateProdSvcEventHandler.java new file mode 100644 index 00000000..36f577b3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/UpdateProdSvcEventHandler.java @@ -0,0 +1,59 @@ +package com.zmops.iot.web.product.service.event; + + +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductServiceParam; +import com.zmops.iot.domain.product.query.QProductServiceParam; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.event.applicationEvent.ProductServiceCreateEvent; +import com.zmops.iot.web.product.dto.ProductServiceDto; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author yefei + *

+ * 产品服务修改 同步到设备 步骤 + */ +@Slf4j +@Component +public class UpdateProdSvcEventHandler implements ApplicationListener { + + + @Override + @Async + public void onApplicationEvent(ProductServiceCreateEvent event) { + log.debug("UpdateProdSvcWorker…………"); + ProductServiceDto productServiceDto = event.getEventData(); + String prodId = productServiceDto.getRelationId(); + + //查询出继承了此产品的设备 + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + if (ToolUtil.isEmpty(deviceIds)) { + return; + } + + new QProductServiceParam().serviceId.eq(productServiceDto.getId()).deviceId.in(deviceIds).delete(); + //保存设备与服务参数的 关联关系 + List productServiceParamList = new ArrayList<>(); + for (String deviceId : deviceIds) { + productServiceDto.getProductServiceParamList().forEach(productServiceParam -> { + ProductServiceParam param = new ProductServiceParam(); + ToolUtil.copyProperties(productServiceParam, param); + param.setId(null); + param.setDeviceId(deviceId); + param.setServiceId(productServiceDto.getId()); + productServiceParamList.add(param); + }); + } + DB.saveAll(productServiceParamList); + + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/UpdateProductEventTriggerEventHandler.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/UpdateProductEventTriggerEventHandler.java new file mode 100644 index 00000000..465d5b29 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/event/UpdateProductEventTriggerEventHandler.java @@ -0,0 +1,59 @@ +package com.zmops.iot.web.product.service.event; + + +import com.zmops.iot.domain.device.query.QDevice; +import com.zmops.iot.domain.product.ProductEventService; +import com.zmops.iot.web.event.applicationEvent.ProductEventTriggerCreateEvent; +import com.zmops.iot.web.product.dto.ProductEventRule; +import com.zmops.zeus.driver.service.ZbxTrigger; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author yefei + *

+ * 产品服务创建 同步到设备 步骤 + */ +@Slf4j +@Component +@EnableAsync +public class UpdateProductEventTriggerEventHandler implements ApplicationListener { + + @Autowired + ZbxTrigger zbxTrigger; + + @Override + @Async + public void onApplicationEvent(ProductEventTriggerCreateEvent event) { + log.debug("UpdateProductEventTriggerWorker…………"); + ProductEventRule productEventRule = event.getEventData(); + String prodId = productEventRule.getProductId(); + + List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(Long.parseLong(prodId)).findSingleAttributeList(); + + List addProductEventServiceList = new ArrayList<>(); + + for (String deviceId : deviceIds) { + productEventRule.getDeviceServices().forEach(productEventService -> { + ProductEventService newProductEventService = new ProductEventService(); + newProductEventService.setDeviceId(deviceId); + newProductEventService.setExecuteDeviceId(deviceId); + newProductEventService.setEventRuleId(productEventRule.getEventRuleId()); + newProductEventService.setServiceId(productEventService.getServiceId()); + addProductEventServiceList.add(newProductEventService); + }); + } + + DB.saveAll(addProductEventServiceList); + + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java deleted file mode 100644 index 386ba9a4..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/SaveProdAttrWorker.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.zmops.iot.web.product.service.work; - - -import cn.hutool.core.util.IdUtil; -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.device.query.QDevice; -import com.zmops.iot.domain.product.ProductAttribute; -import com.zmops.iot.util.ToolUtil; -import com.zmops.iot.web.product.dto.ProductAttr; -import io.ebean.DB; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * @author yefei - *

- * 产品属性创建 同步到设备 步骤 - */ -@Slf4j -@Component -public class SaveProdAttrWorker implements IWorker { - - - @Override - public Boolean action(ProductAttr productAttr, Map> map) { - log.debug("处理产品 新增Attr 同步到设备工作…………"); - - Long prodId = productAttr.getProductId(); - - List deviceIds = new QDevice().select(QDevice.Alias.deviceId).productId.eq(prodId).findSingleAttributeList(); - - List productAttributeList = new ArrayList<>(); - - for (Long deviceId : deviceIds) { - ProductAttribute productAttrbute = new ProductAttribute(); - ToolUtil.copyProperties(productAttr, productAttrbute); - productAttrbute.setAttrId(IdUtil.getSnowflake().nextId()); - productAttrbute.setProductId(deviceId); - productAttributeList.add(productAttrbute); - } - DB.saveAll(productAttributeList); - - return true; - } - - - @Override - public Boolean defaultValue() { - return true; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java b/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java deleted file mode 100644 index 10f29167..00000000 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/product/service/work/UpdateAttributeWorker.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.zmops.iot.web.product.service.work; - - -import com.zmops.iot.async.callback.IWorker; -import com.zmops.iot.async.wrapper.WorkerWrapper; -import com.zmops.iot.domain.product.ProductAttribute; -import com.zmops.iot.domain.product.query.QProductAttribute; -import com.zmops.iot.web.product.dto.ProductAttr; -import io.ebean.DB; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Map; - -/** - * @author yefei - *

- * 产品属性修改 同步到设备 步骤 - */ -@Slf4j -@Component -public class UpdateAttributeWorker implements IWorker { - - - @Override - public Boolean action(ProductAttr productAttr, Map> map) { - log.debug("处理产品属性修改 同步到设备工作…………"); - - Long attrId = productAttr.getAttrId(); - - List list = new QProductAttribute().templateId.eq(attrId).findList(); - - for (ProductAttribute productAttribute : list) { - productAttribute.setName(productAttr.getAttrName()); - productAttribute.setKey(productAttr.getKey()); - productAttribute.setUnits(productAttr.getUnits()); - productAttribute.setSource(productAttr.getSource()); - productAttribute.setValueType(productAttr.getValueType()); - } - DB.updateAll(list); - - return true; - } - - - @Override - public Boolean defaultValue() { - return true; - } - -} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolComponentController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolComponentController.java new file mode 100644 index 00000000..4b3544e0 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolComponentController.java @@ -0,0 +1,164 @@ +package com.zmops.iot.web.protocol.controller; + +import com.dtflys.forest.Forest; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.protocol.ProtocolComponent; +import com.zmops.iot.domain.protocol.query.QProtocolComponent; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.protocol.dto.ProtocolComponentDto; +import com.zmops.iot.web.protocol.dto.param.ProtocolComponentParam; +import com.zmops.iot.web.protocol.service.ProtocolComponentService; +import com.zmops.zeus.driver.service.ZeusServer; +import io.ebean.DB; +import io.ebean.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; + +/** + * 协议组件 + * + * @author yefei + **/ +@RestController +@RequestMapping("/protocol/component") +public class ProtocolComponentController { + + @Autowired + ProtocolComponentService protocolComponentService; + + @Autowired + ZeusServer zeusServer; + + /** + * 协议组件分页列表 + */ + @RequestMapping("/getProtocolComponentByPage") + public Pager getProtocolComponentByPage(@RequestBody ProtocolComponentParam protocolComponentParam) { + return protocolComponentService.getProtocolComponentByPage(protocolComponentParam); + } + + /** + * 协议组件列表 + */ + @RequestMapping("/list") + public ResponseData list(@RequestBody ProtocolComponentParam protocolComponentParam) { + return ResponseData.success(protocolComponentService.list(protocolComponentParam)); + } + + + /** + * 协议组件创建 + */ + @RequestMapping("/create") + public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody ProtocolComponentParam protocolComponentParam) { + int count = new QProtocolComponent().name.eq(protocolComponentParam.getName()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_EXISTS); + } + return ResponseData.success(protocolComponentService.create(protocolComponentParam)); + } + + /** + * 协议组件修改 + */ + @RequestMapping("/update") + public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody ProtocolComponentParam protocolComponentParam) { + int count = new QProtocolComponent().name.eq(protocolComponentParam.getName()).protocolComponentId.ne(protocolComponentParam.getProtocolComponentId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_EXISTS); + } + return ResponseData.success(protocolComponentService.update(protocolComponentParam)); + } + + /** + * 协议组件上传 + */ + @RequestMapping("/upload") + public ResponseData upload(@RequestParam("file") MultipartFile file, @RequestParam("protocolComponentId") Long protocolComponentId, HttpServletRequest request) throws IOException, URISyntaxException { + ProtocolComponent protocolComponent = new QProtocolComponent().protocolComponentId.eq(protocolComponentId).findOne(); + if (protocolComponent == null) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_NOT_EXISTS); + } + try { + zeusServer.upload("127.0.0.1", file, progress -> { + System.out.println("total bytes: " + progress.getTotalBytes()); // 文件大小 + System.out.println("current bytes: " + progress.getCurrentBytes()); // 已上传字节数 + System.out.println("progress: " + Math.round(progress.getRate() * 100) + "%"); // 已上传百分比 + if (progress.isDone()) { // 是否上传完成 + System.out.println("-------- Upload Completed! --------"); + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + protocolComponent.setStatus("1"); + protocolComponent.setFileName(file.getOriginalFilename()); + DB.update(protocolComponent); + return ResponseData.success(); + } + + /** + * 协议组件删除 + */ + @RequestMapping("/delete") + public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody ProtocolComponentParam protocolComponentParam) { + protocolComponentService.delete(protocolComponentParam.getProtocolComponentIds()); + return ResponseData.success(protocolComponentParam.getProtocolComponentIds()); + } + + /** + * 协议组件发布 + */ + @RequestMapping("/publish") + @Transactional + public ResponseData publish(@RequestParam("protocolComponentId") Long protocolComponentId) { + ProtocolComponent protocolComponent = new QProtocolComponent().protocolComponentId.eq(protocolComponentId).findOne(); + if (protocolComponent == null) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_NOT_EXISTS); + } + protocolComponent.setStatus("2"); + DB.update(protocolComponent); + //TODO 调用服务发布 + + Map params = new HashMap<>(1); + params.put("protocolComponentId", protocolComponent.getProtocolComponentId() + ""); + params.put("fileName", protocolComponent.getFileName()); + Forest.post("/protocol/component/installArk").host("127.0.0.1").port(12800).addBody(params, "text/html;charset=utf-8").execute(); + + return ResponseData.success(); + } + + /** + * 协议组件取消发布 + */ + @RequestMapping("/unPublish") + @Transactional + public ResponseData unPublish(@RequestParam("protocolComponentId") Long protocolComponentId) { + ProtocolComponent protocolComponent = new QProtocolComponent().protocolComponentId.eq(protocolComponentId).findOne(); + if (protocolComponent == null) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_NOT_EXISTS); + } + protocolComponent.setStatus("1"); + DB.update(protocolComponent); + + Map params = new HashMap<>(1); + params.put("protocolComponentId", protocolComponent.getProtocolComponentId() + ""); + Forest.post("/protocol/component/uninstallArk").host("127.0.0.1").port(12800).addBody(params, "text/html;charset=utf-8").execute(); + + return ResponseData.success(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolGatewayController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolGatewayController.java new file mode 100644 index 00000000..248aab08 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolGatewayController.java @@ -0,0 +1,149 @@ +package com.zmops.iot.web.protocol.controller; + +import com.dtflys.forest.Forest; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.protocol.ProtocolGateway; +import com.zmops.iot.domain.protocol.query.QProtocolComponent; +import com.zmops.iot.domain.protocol.query.QProtocolGateway; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.protocol.dto.ProtocolGatewayDto; +import com.zmops.iot.web.protocol.dto.param.ProtocolGatewayParam; +import com.zmops.iot.web.protocol.service.ProtocolGatewayService; +import com.zmops.zeus.driver.service.ZeusServer; +import io.ebean.DB; +import io.ebean.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +/** + * 协议网关 + * + * @author yefei + **/ +@RestController +@RequestMapping("/protocol/gateway") +public class ProtocolGatewayController { + + @Autowired + ProtocolGatewayService protocolGatewayService; + + @Autowired + ZeusServer zeusServer; + + /** + * 协议网关分页列表 + */ + @RequestMapping("/getProtocolGatewayByPage") + public Pager getProtocolGatewayByPage(@RequestBody ProtocolGatewayParam protocolGatewayParam) { + return protocolGatewayService.getProtocolGatewayByPage(protocolGatewayParam); + } + + /** + * 协议网关列表 + */ + @RequestMapping("/list") + public ResponseData list(@RequestBody ProtocolGatewayParam protocolGatewayParam) { + return ResponseData.success(protocolGatewayService.list(protocolGatewayParam)); + } + + /** + * 协议网关创建 + */ + @RequestMapping("/create") + public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody ProtocolGatewayParam protocolGatewayParam) { + int count = new QProtocolGateway().name.eq(protocolGatewayParam.getName()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_EXISTS); + } + count = new QProtocolGateway().protocolServiceId.eq(protocolGatewayParam.getProtocolServiceId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_SERVICE_HAS_BIND_COMPONENT); + } + if(ToolUtil.isEmpty(protocolGatewayParam.getProtocolGatewayMqttList()) && ToolUtil.isEmpty(protocolGatewayParam.getProtocolComponentId())){ + throw new ServiceException(BizExceptionEnum.PROTOCOL_GATEWAY_HAS_NOT_COMPONENT); + } + return ResponseData.success(protocolGatewayService.create(protocolGatewayParam)); + } + + /** + * 协议网关修改 + */ + @RequestMapping("/update") + public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody ProtocolGatewayParam protocolGatewayParam) { + int count = new QProtocolGateway().name.eq(protocolGatewayParam.getName()).protocolGatewayId.ne(protocolGatewayParam.getProtocolGatewayId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_EXISTS); + } + count = new QProtocolGateway().protocolServiceId.eq(protocolGatewayParam.getProtocolServiceId()).protocolGatewayId.ne(protocolGatewayParam.getProtocolGatewayId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_SERVICE_HAS_BIND_COMPONENT); + } + if(ToolUtil.isEmpty(protocolGatewayParam.getProtocolGatewayMqttList()) && ToolUtil.isEmpty(protocolGatewayParam.getProtocolComponentId())){ + throw new ServiceException(BizExceptionEnum.PROTOCOL_GATEWAY_HAS_NOT_COMPONENT); + } + return ResponseData.success(protocolGatewayService.update(protocolGatewayParam)); + } + + + /** + * 协议网关删除 + */ + @RequestMapping("/delete") + public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody ProtocolGatewayParam protocolGatewayParam) { + protocolGatewayService.delete(protocolGatewayParam.getProtocolGatewayIds()); + return ResponseData.success(protocolGatewayParam.getProtocolGatewayIds()); + } + + /** + * 协议网关启动 + */ + @RequestMapping("/start") + @Transactional + public ResponseData start(@RequestParam("protocolGatewayId") Long protocolGatewayId) { + ProtocolGateway protocolGateway = new QProtocolGateway().protocolGatewayId.eq(protocolGatewayId).findOne(); + if (protocolGateway == null) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_GATEWAY_NOT_EXISTS); + } + protocolGateway.setStatus("0"); + DB.update(protocolGateway); + + Map params = new HashMap<>(1); + params.put("routeId", protocolGatewayId + ""); + Forest.post("/protocol/gateway/startRoute").host("127.0.0.1").port(12800).addBody(params,"text/html;charset=utf-8").execute(); + + return ResponseData.success(); + } + + /** + * 协议网关停止 + */ + @RequestMapping("/stop") + @Transactional + public ResponseData stop(@RequestParam("protocolGatewayId") Long protocolGatewayId) { + ProtocolGateway protocolGateway = new QProtocolGateway().protocolGatewayId.eq(protocolGatewayId).findOne(); + if (protocolGateway == null) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_GATEWAY_NOT_EXISTS); + } + protocolGateway.setStatus("1"); + DB.update(protocolGateway); + + + Map params = new HashMap<>(1); + params.put("routeId", protocolGatewayId + ""); + Forest.post("/protocol/gateway/stopRoute").host("127.0.0.1").port(12800).addBody(params,"text/html;charset=utf-8").execute(); + + return ResponseData.success(); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolServiceController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolServiceController.java new file mode 100644 index 00000000..f120f7c4 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/controller/ProtocolServiceController.java @@ -0,0 +1,89 @@ +package com.zmops.iot.web.protocol.controller; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.protocol.query.QProtocolService; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.protocol.dto.ProtocolServiceDto; +import com.zmops.iot.web.protocol.dto.param.ProtocolServiceParam; +import com.zmops.iot.web.protocol.service.ProtocolSvrService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 协议服务 + * + * @author yefei + **/ +@RestController +@RequestMapping("/protocol/service") +public class ProtocolServiceController { + + @Autowired + ProtocolSvrService protocolSvrService; + + /** + * 协议服务分页列表 + */ + @RequestMapping("/getProtocolServiceByPage") + public Pager getProtocolComponentByPage(@RequestBody ProtocolServiceParam protocolServiceParam) { + return protocolSvrService.getProtocolServiceByPage(protocolServiceParam); + } + + /** + * 协议服务列表 + */ + @RequestMapping("/list") + public ResponseData list(@RequestBody ProtocolServiceParam protocolServiceParam) { + return ResponseData.success(protocolSvrService.list(protocolServiceParam)); + } + + + /** + * 协议服务创建 + */ + @RequestMapping("/create") + public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody ProtocolServiceParam protocolServiceParam) { + int count = new QProtocolService().name.eq(protocolServiceParam.getName()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_SERVICE_EXISTS); + } + count = new QProtocolService().ip.eq(protocolServiceParam.getIp()).port.eq(protocolServiceParam.getPort()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_SERVICE_PORT_EXISTS); + } + return ResponseData.success(protocolSvrService.create(protocolServiceParam)); + } + + /** + * 协议服务修改 + */ + @RequestMapping("/update") + public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody ProtocolServiceParam protocolServiceParam) { + int count = new QProtocolService().name.eq(protocolServiceParam.getName()).protocolServiceId.ne(protocolServiceParam.getProtocolServiceId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_SERVICE_EXISTS); + } + count = new QProtocolService().ip.eq(protocolServiceParam.getIp()).port.eq(protocolServiceParam.getPort()).protocolServiceId.ne(protocolServiceParam.getProtocolServiceId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_SERVICE_PORT_EXISTS); + } + return ResponseData.success(protocolSvrService.update(protocolServiceParam)); + } + + + /** + * 协议服务删除 + */ + @RequestMapping("/delete") + public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody ProtocolServiceParam protocolServiceParam) { + protocolSvrService.delete(protocolServiceParam.getProtocolServiceIds()); + return ResponseData.success(protocolServiceParam.getProtocolServiceIds()); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolComponentDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolComponentDto.java new file mode 100644 index 00000000..99eabcc5 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolComponentDto.java @@ -0,0 +1,38 @@ +package com.zmops.iot.web.protocol.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class ProtocolComponentDto { + private Long protocolComponentId; + private String name; + private String effectProxy; + @CachedValue(value = "PROTOCOL_COMPONENT_STATUS", fieldName = "statusName") + private String status; + private String remark; + private String fileName; + LocalDateTime createTime; + + LocalDateTime updateTime; + + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + Long createUser; + + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + Long updateUser; + + @CachedValue(type = DicType.Tenant, fieldName = "tenantName") + Long tenantId; + + private String uniqueId; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolGatewayDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolGatewayDto.java new file mode 100644 index 00000000..77c888d7 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolGatewayDto.java @@ -0,0 +1,48 @@ +package com.zmops.iot.web.protocol.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.protocol.ProtocolGatewayMqtt; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class ProtocolGatewayDto { + private Long protocolGatewayId; + @NotBlank(groups = {BaseEntity.Create.class}) + private String name; + @CachedValue(value = "PROTOCOL_SERVICE_TYPE", fieldName = "protocolTypeName") + private String protocolType; + @CachedValue(type = DicType.ProtocolService, fieldName = "protocolServiceName") + private Long protocolServiceId; + @CachedValue(value = "PROTOCOL_GATEWAY_STATUS", fieldName = "statusName") + private String status; + private Long protocolComponentId; + private String remark; + private Integer qos; + + LocalDateTime createTime; + + LocalDateTime updateTime; + + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + Long createUser; + + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + Long updateUser; + + @CachedValue(type = DicType.Tenant, fieldName = "tenantName") + Long tenantId; + + private List protocolGatewayMqttList; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolOption.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolOption.java new file mode 100644 index 00000000..e2f76afe --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolOption.java @@ -0,0 +1,19 @@ +package com.zmops.iot.web.protocol.dto; + +import lombok.Data; + +import java.util.Map; + +/** + * @author yefei + **/ +@Data +public class ProtocolOption { + private String routeId; + + private String protocol; + +// private ProtocolAction action; + + private Map options; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolServiceDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolServiceDto.java new file mode 100644 index 00000000..6a446631 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/ProtocolServiceDto.java @@ -0,0 +1,40 @@ +package com.zmops.iot.web.protocol.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class ProtocolServiceDto { + private Long protocolServiceId; + private String name; + private String effectProxy; + @CachedValue(value = "PROTOCOL_TYPE", fieldName = "protocolTypeName") + private String protocolType; + private String remark; + private String url; + private String ip; + private Integer port; + private Integer msgLength; + private String clientId; + LocalDateTime createTime; + + LocalDateTime updateTime; + + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + Long createUser; + + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + Long updateUser; + + @CachedValue(type = DicType.Tenant, fieldName = "tenantName") + Long tenantId; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolComponentParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolComponentParam.java new file mode 100644 index 00000000..5aba24b7 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolComponentParam.java @@ -0,0 +1,29 @@ +package com.zmops.iot.web.protocol.dto.param; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class ProtocolComponentParam extends BaseQueryParam { + @NotNull(groups = BaseEntity.Update.class) + private Long protocolComponentId; + @NotBlank(groups = {BaseEntity.Create.class}) + private String name; + private String effectProxy; + private String source; + private String status; + private String remark; + private Long tenantId; + private String fileName; + + @NotNull(groups = BaseEntity.Delete.class) + private List protocolComponentIds; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolGatewayParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolGatewayParam.java new file mode 100644 index 00000000..0bd3a48b --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolGatewayParam.java @@ -0,0 +1,32 @@ +package com.zmops.iot.web.protocol.dto.param; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.protocol.ProtocolGatewayMqtt; +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class ProtocolGatewayParam extends BaseQueryParam { + @NotNull(groups = BaseEntity.Update.class) + private Long protocolGatewayId; + @NotBlank(groups = {BaseEntity.Create.class}) + private String name; + private String protocolType; + @NotNull(groups = BaseEntity.Create.class) + private Long protocolServiceId; + private Long protocolComponentId; + private List protocolGatewayMqttList; + private String remark; + private Long tenantId; + private Integer qos; + + @NotNull(groups = BaseEntity.Delete.class) + private List protocolGatewayIds; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolServiceParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolServiceParam.java new file mode 100644 index 00000000..d77ee40d --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/dto/param/ProtocolServiceParam.java @@ -0,0 +1,32 @@ +package com.zmops.iot.web.protocol.dto.param; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class ProtocolServiceParam extends BaseQueryParam { + @NotNull(groups = BaseEntity.Update.class) + private Long protocolServiceId; + @NotBlank(groups = {BaseEntity.Create.class}) + private String name; + private String effectProxy; + private String protocolType; + private String remark; + private Long tenantId; + private String url; + private String ip; + private Integer port; + private Integer msgLength; + private String clientId; + + @NotNull(groups = BaseEntity.Delete.class) + private List protocolServiceIds; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/enums/ProtocolEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/enums/ProtocolEnum.java new file mode 100644 index 00000000..40d27e03 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/enums/ProtocolEnum.java @@ -0,0 +1,38 @@ +package com.zmops.iot.web.protocol.enums; + +import lombok.Getter; + +/** + * @author yefei + **/ +public enum ProtocolEnum { + HttpServer("5","HttpServer"), + MqttClient("1","MqttClient"), + TcpServer("2","TcpServer"), + UdpServer("4","UdpServer"), + CoapServer("9","CoapServer"), + WebSocketServer("7","WebSocketServer"); + + @Getter + String code; + @Getter + String message; + + ProtocolEnum(String code, String message) { + this.code = code; + this.message = message; + } + + public static String getDescription(String status) { + if (status == null) { + return ""; + } else { + for (ProtocolEnum s : ProtocolEnum.values()) { + if (s.getCode().equals(status)) { + return s.getMessage(); + } + } + return ""; + } + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolComponentService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolComponentService.java new file mode 100644 index 00000000..f3b061f7 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolComponentService.java @@ -0,0 +1,99 @@ +package com.zmops.iot.web.protocol.service; + +import cn.hutool.core.util.IdUtil; +import com.dtflys.forest.Forest; +import com.zmops.iot.domain.protocol.ProtocolComponent; +import com.zmops.iot.domain.protocol.query.QProtocolComponent; +import com.zmops.iot.domain.protocol.query.QProtocolGateway; +import com.zmops.iot.domain.protocol.query.QProtocolGatewayMqtt; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.protocol.dto.ProtocolComponentDto; +import com.zmops.iot.web.protocol.dto.param.ProtocolComponentParam; +import io.ebean.DB; +import io.ebean.PagedList; +import io.ebean.annotation.Transactional; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author yefei + **/ +@Service +public class ProtocolComponentService { + + public Pager getProtocolComponentByPage(ProtocolComponentParam protocolComponentParam) { + QProtocolComponent qProtocolComponent = new QProtocolComponent(); + + if (ToolUtil.isNotEmpty(protocolComponentParam.getName())) { + qProtocolComponent.name.contains(protocolComponentParam.getName()); + } + + if (ToolUtil.isNotEmpty(protocolComponentParam.getStatus())) { + qProtocolComponent.status.eq(protocolComponentParam.getStatus()); + } + + PagedList pagedList = qProtocolComponent.setFirstRow((protocolComponentParam.getPage() - 1) * protocolComponentParam.getMaxRow()) + .setMaxRows(protocolComponentParam.getMaxRow()).findPagedList(); + + List protocolComponentDtoList = ToolUtil.convertBean(pagedList.getList(), ProtocolComponentDto.class); + + return new Pager<>(protocolComponentDtoList, pagedList.getTotalCount()); + } + + public List list(ProtocolComponentParam protocolComponentParam) { + QProtocolComponent qProtocolComponent = new QProtocolComponent(); + qProtocolComponent.status.eq("2"); + if (ToolUtil.isNotEmpty(protocolComponentParam.getName())) { + qProtocolComponent.name.contains(protocolComponentParam.getName()); + } + + if (ToolUtil.isNotEmpty(protocolComponentParam.getStatus())) { + qProtocolComponent.status.eq(protocolComponentParam.getStatus()); + } + return qProtocolComponent.findList(); + } + + @Transactional + public ProtocolComponent create(ProtocolComponentParam protocolComponentParam) { + ProtocolComponent protocolComponent = new ProtocolComponent(); + ToolUtil.copyProperties(protocolComponentParam, protocolComponent); + protocolComponent.setStatus("0"); + protocolComponent.setUniqueId(IdUtil.getSnowflake().nextId() + ""); + DB.insert(protocolComponent); + + Map params = new HashMap<>(1); + params.put("protocolComponentId", protocolComponent.getProtocolComponentId() + ""); + params.put("uniqueId", protocolComponent.getUniqueId()); + Forest.post("/protocol/component/saveProtocolComponent").host("127.0.0.1").port(12800).addBody(params, "text/html;charset=utf-8").execute(); + return protocolComponent; + } + + public ProtocolComponent update(ProtocolComponentParam protocolComponentParam) { + ProtocolComponent protocolComponent = new ProtocolComponent(); + ToolUtil.copyProperties(protocolComponentParam, protocolComponent); + DB.update(protocolComponent); + return protocolComponent; + } + + public void delete(List protocolComponentIds) { + int count = new QProtocolGateway().protocolComponentId.in(protocolComponentIds).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_HAS_BIND_GATEWAY); + } + + count = new QProtocolGatewayMqtt().protocolComponentId.in(protocolComponentIds).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_COMPONENT_HAS_BIND_GATEWAY); + } + + new QProtocolComponent().protocolComponentId.in(protocolComponentIds).delete(); + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java new file mode 100644 index 00000000..f6762610 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolGatewayService.java @@ -0,0 +1,155 @@ +package com.zmops.iot.web.protocol.service; + +import com.alibaba.fastjson.JSON; +import com.dtflys.forest.Forest; +import com.zmops.iot.domain.protocol.ProtocolGateway; +import com.zmops.iot.domain.protocol.ProtocolGatewayMqtt; +import com.zmops.iot.domain.protocol.ProtocolService; +import com.zmops.iot.domain.protocol.query.QProtocolGateway; +import com.zmops.iot.domain.protocol.query.QProtocolGatewayMqtt; +import com.zmops.iot.domain.protocol.query.QProtocolService; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.protocol.dto.ProtocolGatewayDto; +import com.zmops.iot.web.protocol.dto.param.ProtocolGatewayParam; +import com.zmops.iot.web.protocol.enums.ProtocolEnum; +import io.ebean.DB; +import io.ebean.PagedList; +import io.ebean.annotation.Transactional; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Service +public class ProtocolGatewayService { + + public Pager getProtocolGatewayByPage(ProtocolGatewayParam protocolGatewayParam) { + QProtocolGateway qProtocolGateway = new QProtocolGateway(); + + if (ToolUtil.isNotEmpty(protocolGatewayParam.getName())) { + qProtocolGateway.name.contains(protocolGatewayParam.getName()); + } + + if (ToolUtil.isNotEmpty(protocolGatewayParam.getProtocolType())) { + qProtocolGateway.protocolType.eq(protocolGatewayParam.getProtocolType()); + } + + PagedList pagedList = qProtocolGateway.setFirstRow((protocolGatewayParam.getPage() - 1) * protocolGatewayParam.getMaxRow()) + .setMaxRows(protocolGatewayParam.getMaxRow()).findPagedList(); + + List protocolGatewayDtoList = ToolUtil.convertBean(pagedList.getList(), ProtocolGatewayDto.class); + + //关联mqtt协议组件 + List ids = protocolGatewayDtoList.parallelStream().map(ProtocolGatewayDto::getProtocolGatewayId).collect(Collectors.toList()); + List topicList = new QProtocolGatewayMqtt().protocolGatewayId.in(ids).findList(); + Map> topicMap = topicList.parallelStream().collect(Collectors.groupingBy(ProtocolGatewayMqtt::getProtocolGatewayId)); + + protocolGatewayDtoList.forEach(protocolGatewayDto -> { + if (ToolUtil.isNotEmpty(topicMap.get(protocolGatewayDto.getProtocolGatewayId()))) { + protocolGatewayDto.setProtocolGatewayMqttList(topicMap.get(protocolGatewayDto.getProtocolGatewayId())); + } + }); + + return new Pager<>(protocolGatewayDtoList, pagedList.getTotalCount()); + } + + public List list(ProtocolGatewayParam protocolGatewayParam) { + QProtocolGateway qProtocolGateway = new QProtocolGateway(); + if (ToolUtil.isNotEmpty(protocolGatewayParam.getName())) { + qProtocolGateway.name.contains(protocolGatewayParam.getName()); + } + + if (ToolUtil.isNotEmpty(protocolGatewayParam.getProtocolType())) { + qProtocolGateway.protocolType.eq(protocolGatewayParam.getProtocolType()); + } + return qProtocolGateway.findList(); + } + + @Transactional + public ProtocolGateway create(ProtocolGatewayParam protocolGatewayParam) { + ProtocolGateway protocolGateway = new ProtocolGateway(); + ToolUtil.copyProperties(protocolGatewayParam, protocolGateway); + protocolGateway.setStatus("0"); + DB.insert(protocolGateway); + + saveMqtt(protocolGatewayParam.getProtocolGatewayMqttList(), protocolGateway.getProtocolGatewayId()); + + Map option = initOptionMap(protocolGatewayParam); + +// ProtocolOption protocolOption = new ProtocolOption(); +// protocolOption.setRouteId(ProtocolGateway.getProtocolGatewayId() + ""); +// protocolOption.setProtocol(ProtocolEnum.getDescription(protocolGatewayParam.getProtocolType())); +// protocolOption.setOptions(option); + + Map params = new HashMap<>(7); + params.put("routeId", protocolGateway.getProtocolGatewayId() + ""); + params.put("name", protocolGateway.getName()); + params.put("protocolServiceId", protocolGatewayParam.getProtocolServiceId() + ""); + params.put("protocolComponentId", protocolGatewayParam.getProtocolComponentId() + ""); + params.put("status", protocolGateway.getStatus()); + params.put("protocol", ProtocolEnum.getDescription(protocolGatewayParam.getProtocolType())); + params.put("option", JSON.toJSONString(option)); + params.put("mqttList", JSON.toJSONString(protocolGatewayParam.getProtocolGatewayMqttList())); + + Forest.post("/protocol/gateway/createProtocolGateway").host("127.0.0.1").port(12800).addBody(params, "text/html;charset=utf-8").execute(); + return protocolGateway; + } + + private Map initOptionMap(ProtocolGatewayParam protocolGatewayParam) { + Map option = new HashMap<>(3); + ProtocolService protocolService = new QProtocolService().protocolServiceId.eq(protocolGatewayParam.getProtocolServiceId()).findOne(); + option.put("hostIp", protocolService.getIp()); + option.put("port", protocolService.getPort()); + if (ToolUtil.isNotEmpty(protocolGatewayParam.getProtocolGatewayMqttList())) { + String topics = protocolGatewayParam.getProtocolGatewayMqttList().parallelStream().map(ProtocolGatewayMqtt::getTopic).collect(Collectors.joining(",")); + option.put("topicNames", topics); + } + + option.put("port", protocolService.getPort()); + option.put("mqttList", protocolGatewayParam.getProtocolGatewayMqttList()); + + return option; + } + + @Transactional + public ProtocolGateway update(ProtocolGatewayParam protocolGatewayParam) { + ProtocolGateway protocolGateway = new ProtocolGateway(); + ToolUtil.copyProperties(protocolGatewayParam, protocolGateway); + DB.update(protocolGateway); + + new QProtocolGatewayMqtt().protocolGatewayId.eq(protocolGatewayParam.getProtocolGatewayId()).delete(); + saveMqtt(protocolGatewayParam.getProtocolGatewayMqttList(), protocolGatewayParam.getProtocolGatewayId()); + + return protocolGateway; + } + + private void saveMqtt(List protocolGatewayMqtts, Long protocolGatewayId) { + if (ToolUtil.isNotEmpty(protocolGatewayMqtts)) { + List protocolGatewayMqttList = new ArrayList<>(); + protocolGatewayMqtts.forEach(mqtt -> { + mqtt.setProtocolGatewayId(protocolGatewayId); + protocolGatewayMqttList.add(mqtt); + }); + DB.insertAll(protocolGatewayMqttList); + } + } + + public void delete(List protocolGatewayIds) { +// int count = new QProtocolGateway().protocolServiceId.in(protocolServiceIds).findCount(); +// if (count > 0) { +// throw new ServiceException(BizExceptionEnum.PROTOCOL_SERVICE_HAS_BIND_GATEWAY); +// } + + new QProtocolGateway().protocolGatewayId.in(protocolGatewayIds).delete(); + new QProtocolGatewayMqtt().protocolGatewayId.in(protocolGatewayIds).delete(); + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java new file mode 100644 index 00000000..2190cdbb --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/protocol/service/ProtocolSvrService.java @@ -0,0 +1,129 @@ +package com.zmops.iot.web.protocol.service; + +import com.dtflys.forest.Forest; +import com.zmops.iot.domain.protocol.ProtocolService; +import com.zmops.iot.domain.protocol.query.QProtocolGateway; +import com.zmops.iot.domain.protocol.query.QProtocolService; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.protocol.dto.ProtocolServiceDto; +import com.zmops.iot.web.protocol.dto.param.ProtocolServiceParam; +import com.zmops.iot.web.protocol.enums.ProtocolEnum; +import io.ebean.DB; +import io.ebean.PagedList; +import io.ebean.annotation.Transactional; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author yefei + **/ +@Service +public class ProtocolSvrService implements CommandLineRunner { + + public Pager getProtocolServiceByPage(ProtocolServiceParam protocolServiceParam) { + QProtocolService qProtocolService = new QProtocolService(); + + if (ToolUtil.isNotEmpty(protocolServiceParam.getName())) { + qProtocolService.name.contains(protocolServiceParam.getName()); + } + + if (ToolUtil.isNotEmpty(protocolServiceParam.getProtocolType())) { + qProtocolService.protocolType.eq(protocolServiceParam.getProtocolType()); + } + + PagedList pagedList = qProtocolService.setFirstRow((protocolServiceParam.getPage() - 1) * protocolServiceParam.getMaxRow()) + .setMaxRows(protocolServiceParam.getMaxRow()).findPagedList(); + + List protocolComponentDtoList = ToolUtil.convertBean(pagedList.getList(), ProtocolServiceDto.class); + + return new Pager<>(protocolComponentDtoList, pagedList.getTotalCount()); + } + + public List list(ProtocolServiceParam protocolServiceParam) { + QProtocolService qProtocolService = new QProtocolService(); + if (ToolUtil.isNotEmpty(protocolServiceParam.getName())) { + qProtocolService.name.contains(protocolServiceParam.getName()); + } + + if (ToolUtil.isNotEmpty(protocolServiceParam.getProtocolType())) { + qProtocolService.protocolType.eq(protocolServiceParam.getProtocolType()); + } + return qProtocolService.findList(); + } + + @Transactional + public ProtocolService create(ProtocolServiceParam protocolServiceParam) { + ProtocolService ProtocolService = new ProtocolService(); + ToolUtil.copyProperties(protocolServiceParam, ProtocolService); + DB.insert(ProtocolService); + + Map params = new HashMap<>(1); + params.put("protocolServiceId", ProtocolService.getProtocolServiceId() + ""); + params.put("name", ProtocolService.getName()); + params.put("url", ProtocolService.getUrl()); + params.put("ip", ProtocolService.getIp()); + params.put("port", ProtocolService.getPort() + ""); + params.put("msgLength", ProtocolService.getMsgLength() + ""); + params.put("clientId", ProtocolService.getClientId()); + params.put("protocol", ProtocolEnum.getDescription(ProtocolService.getProtocolType())); + params.put("remark", ProtocolService.getRemark()); + Forest.post("/protocol/service/saveProtocolService").host("127.0.0.1").port(12800).addBody(params, "text/html;charset=utf-8").execute(); + + updateProtocolServiceEvent(); + return ProtocolService; + } + + @Transactional + public ProtocolService update(ProtocolServiceParam protocolServiceParam) { + ProtocolService ProtocolService = new ProtocolService(); + ToolUtil.copyProperties(protocolServiceParam, ProtocolService); + DB.update(ProtocolService); + + Map params = new HashMap<>(1); + params.put("protocolServiceId", ProtocolService.getProtocolServiceId() + ""); + params.put("name", ProtocolService.getName()); + params.put("url", ProtocolService.getUrl()); + params.put("ip", ProtocolService.getIp()); + params.put("port", ProtocolService.getPort() + ""); + params.put("msgLength", ProtocolService.getMsgLength() + ""); + params.put("clientId", ProtocolService.getClientId()); + params.put("protocol", ProtocolEnum.getDescription(ProtocolService.getProtocolType())); + params.put("remark", ProtocolService.getRemark()); + Forest.post("/protocol/service/updateProtocolService").host("127.0.0.1").port(12800).addBody(params, "text/html;charset=utf-8").execute(); + + + updateProtocolServiceEvent(); + return ProtocolService; + } + + public void delete(List protocolServiceIds) { + int count = new QProtocolGateway().protocolServiceId.in(protocolServiceIds).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROTOCOL_SERVICE_HAS_BIND_GATEWAY); + } + + new QProtocolService().protocolServiceId.in(protocolServiceIds).delete(); + updateProtocolServiceEvent(); + } + + public void updateProtocolServiceEvent() { + List serviceList = new QProtocolService().findList(); + Map map = serviceList.parallelStream().collect(Collectors.toMap(ProtocolService::getProtocolServiceId, ProtocolService::getName, (a, b) -> a)); + DefinitionsUtil.updateProtocolServiceCache(map); + } + + @Override + public void run(String... args) throws Exception { + //updateProtocolServiceEvent(); + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/controller/ProxyController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/controller/ProxyController.java new file mode 100644 index 00000000..c4b856b0 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/controller/ProxyController.java @@ -0,0 +1,89 @@ +package com.zmops.iot.web.proxy.controller; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.proxy.query.QProxy; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.proxy.dto.ProxyDto; +import com.zmops.iot.web.proxy.dto.param.ProxyParam; +import com.zmops.iot.web.proxy.service.ProxyService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 代理服务 + */ + +@RestController +@RequestMapping("/proxy") +public class ProxyController { + + @Autowired + ProxyService proxyService; + + /** + * 代理服务分页列表 + */ + @RequestMapping("/getProxyByPage") + public Pager getProxyByPage(@RequestBody ProxyParam proxyParam) { + return proxyService.getProxyByPage(proxyParam); + } + + /** + * 代理服务列表 + */ + @RequestMapping("/list") + public ResponseData list(@RequestBody ProxyParam proxyParam) { + return ResponseData.success(proxyService.list(proxyParam)); + } + + + /** + * 代理服务创建 + */ + @RequestMapping("/create") + public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody ProxyDto proxyDto) { + int count = new QProxy().name.eq(proxyDto.getName()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROXY_EXISTS); + } + return ResponseData.success(proxyService.create(proxyDto)); + } + + /** + * 代理服务修改 + */ + @RequestMapping("/update") + public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody ProxyDto proxyDto) { + int count = new QProxy().name.eq(proxyDto.getName()).id.ne(proxyDto.getId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.PROXY_EXISTS); + } + return ResponseData.success(proxyService.update(proxyDto)); + } + + /** + * 代理服务删除 + */ + @RequestMapping("/delete") + public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody ProxyDto proxyDto) { + proxyService.delete(proxyDto.getIds()); + return ResponseData.success(proxyDto.getIds()); + } + + /** + * 监控信息 + */ + @RequestMapping("/monitor/info") + public ResponseData monitorInfo() { + + return ResponseData.success(proxyService.monitorInfo()); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ProxyDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ProxyDto.java new file mode 100644 index 00000000..3de3d6c1 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ProxyDto.java @@ -0,0 +1,57 @@ +package com.zmops.iot.web.proxy.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class ProxyDto { + + @NotNull(groups = BaseEntity.Update.class) + private Long id; + + @NotBlank(groups = BaseEntity.Create.class) + private String name; + + private String mode; + + private String address; + + private String remark; + + private Integer tlsAccept; + + private String lastAccess; + + private String autoCompress; + + private String zbxId; + + LocalDateTime createTime; + + LocalDateTime updateTime; + + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + Long createUser; + + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + Long updateUser; + + @CachedValue(type = DicType.Tenant, fieldName = "tenantName") + Long tenantId; + + @NotNull(groups = BaseEntity.Delete.class) + private List ids; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ProxyMonitorInfo.java b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ProxyMonitorInfo.java new file mode 100644 index 00000000..c4cc77f7 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ProxyMonitorInfo.java @@ -0,0 +1,41 @@ +package com.zmops.iot.web.proxy.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class ProxyMonitorInfo { + private int hostStatusEnable; + private int hostStatusDisable; + private int hostStatusTotal; + + private int itemStatusEnable; + private int itemStatusDisable; + private int itemStatusUnSupport; + private int itemStatusTotal; + + private int triggerStatusEnable; + private int triggerStatusDisable; + private int triggerStatusTotal; + + private String nvps; + + private String proxyId; + private String proxyName; + + public int getHostStatusTotal() { + return this.hostStatusEnable + this.hostStatusDisable; + } + + public int getItemStatusTotal() { + return this.itemStatusEnable + this.itemStatusDisable + itemStatusUnSupport; + } + + public int getTriggerStatusTotal() { + return this.triggerStatusEnable + this.triggerStatusDisable; + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ZbxProxyInfo.java b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ZbxProxyInfo.java new file mode 100644 index 00000000..1c7fcff9 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ZbxProxyInfo.java @@ -0,0 +1,17 @@ +package com.zmops.iot.web.proxy.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class ZbxProxyInfo { + + private String proxyid; + + private String lastaccess; + + private String auto_compress; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ZbxServerInfo.java b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ZbxServerInfo.java new file mode 100644 index 00000000..e8251e1f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/ZbxServerInfo.java @@ -0,0 +1,19 @@ +package com.zmops.iot.web.proxy.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class ZbxServerInfo { + private String count; + private Attributes attributes; + + @Data + public static class Attributes{ + private String proxyid; + private int status; + private int state; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/param/ProxyParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/param/ProxyParam.java new file mode 100644 index 00000000..62a011ca --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/dto/param/ProxyParam.java @@ -0,0 +1,15 @@ +package com.zmops.iot.web.proxy.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class ProxyParam extends BaseQueryParam { + + private String name; + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/service/ProxyService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/service/ProxyService.java new file mode 100644 index 00000000..e102afa8 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/proxy/service/ProxyService.java @@ -0,0 +1,276 @@ +package com.zmops.iot.web.proxy.service; + +import cn.hutool.core.util.IdUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.dtflys.forest.Forest; +import com.dtflys.forest.config.ForestConfiguration; +import com.dtflys.forest.http.ForestRequest; +import com.zmops.iot.core.auth.context.LoginContextHolder; +import com.zmops.iot.domain.proxy.Proxy; +import com.zmops.iot.domain.proxy.query.QProxy; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.proxy.dto.ProxyDto; +import com.zmops.iot.web.proxy.dto.ProxyMonitorInfo; +import com.zmops.iot.web.proxy.dto.ZbxProxyInfo; +import com.zmops.iot.web.proxy.dto.ZbxServerInfo; +import com.zmops.iot.web.proxy.dto.param.ProxyParam; +import com.zmops.zeus.driver.service.ZbxProxy; +import io.ebean.DB; +import lombok.Data; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * @author yefei + *

+ * 产品 物模型 服务 + **/ +@Service +public class ProxyService { + + @Autowired + ZbxProxy zbxProxy; + + /** + * 代理服务分页列表 + * + * @param proxyParam + * @return + */ + public Pager getProxyByPage(ProxyParam proxyParam) { + QProxy qProxy = new QProxy(); + if (ToolUtil.isNotEmpty(proxyParam.getName())) { + qProxy.name.contains(proxyParam.getName()); + } + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + qProxy.tenantId.eq(tenantId); + } + qProxy.orderBy(" create_time desc"); + List productServiceDtoList = qProxy.setFirstRow((proxyParam.getPage() - 1) * proxyParam.getMaxRow()) + .setMaxRows(proxyParam.getMaxRow()).asDto(ProxyDto.class).findList(); + + if (ToolUtil.isNotEmpty(productServiceDtoList)) { + List collect = productServiceDtoList.parallelStream().map(ProxyDto::getZbxId).collect(Collectors.toList()); + String s = zbxProxy.get(collect.toString()); + + List zbxProxyInfoList = JSONObject.parseArray(s, ZbxProxyInfo.class); + Map map = zbxProxyInfoList.parallelStream().collect(Collectors.toMap(ZbxProxyInfo::getProxyid, o -> o)); + productServiceDtoList.forEach(proxyDto -> { + if (map.get(proxyDto.getZbxId()) != null) { + ZbxProxyInfo zbxProxyInfo = map.get(proxyDto.getZbxId()); + proxyDto.setLastAccess(LocalDateTimeUtils.convertTimeToString(Integer.parseInt(zbxProxyInfo.getLastaccess()), "yyyy-MM-dd HH:mm:ss")); + proxyDto.setAutoCompress("1".equals(zbxProxyInfo.getAuto_compress()) ? "是" : "否"); + } + }); + } + + return new Pager<>(productServiceDtoList, qProxy.findCount()); + } + + /** + * 代理服务列表 + * + * @param proxyParam + * @return + */ + public List list(ProxyParam proxyParam) { + QProxy qProxy = new QProxy(); + if (ToolUtil.isNotEmpty(proxyParam.getName())) { + qProxy.name.contains(proxyParam.getName()); + } + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + qProxy.tenantId.eq(tenantId); + } + qProxy.orderBy(" create_time desc"); + return qProxy.findList(); + } + + /** + * 代理服务创建 + * + * @param proxyDto + * @return + */ + @Transactional(rollbackFor = Exception.class) + public ProxyDto create(ProxyDto proxyDto) { + + Long id = IdUtil.getSnowflake().nextId(); + + String result = zbxProxy.proxyCreate(id + ""); + String zbxId = JSON.parseObject(result, Proxyids.class).getProxyids()[0]; + + proxyDto.setId(id); + proxyDto.setZbxId(zbxId); + Proxy proxy = new Proxy(); + ToolUtil.copyProperties(proxyDto, proxy); + DB.save(proxy); + + return proxyDto; + } + + /** + * 代理服务修改 + * + * @param proxyDto + * @return + */ + public ProxyDto update(ProxyDto proxyDto) { + + Proxy proxy = new Proxy(); + ToolUtil.copyProperties(proxyDto, proxy); + DB.update(proxy); + + return proxyDto; + } + + /** + * 代理服务删除 + * + * @param ids + * @return + */ + public void delete(List ids) { + List zbxIds = new QProxy().select(QProxy.alias().zbxId).id.in(ids).findSingleAttributeList(); + if (ToolUtil.isNotEmpty(zbxIds)) { + zbxProxy.proxyDelete(zbxIds); + } + + new QProxy().id.in(ids).delete(); + + } + + public Object monitorInfo() { + List proxyList = list(new ProxyParam()); + if (ToolUtil.isEmpty(proxyList)) { + return new HashMap<>(0); + } + + Map proxyMonitorInfoMap = new ConcurrentHashMap<>(); + + String host = "127.0.0.1"; + String zbxApiToken = ForestConfiguration.configuration().getVariableValue("zbxApiToken").toString(); + + +// String body = "{\"request\":\"queue.get\",\"type\":\"details\",\"sid\":\"" + zbxApiToken + "\",\"limit\":10}"; +// Forest.post("/zabbix/monitor").host(host).port(12800).contentTypeJson().addBody(body).executeAsMap(); +// body = "{\"request\":\"queue.get\",\"type\":\"overview by proxy\",\"sid\":\"" + zbxApiToken + "\"}"; +// objectObjectMap = Forest.post("/zabbix/monitor").host(host).port(12800).contentTypeJson().addBody(body).executeAsMap(); + + +// body = "{\"request\":\"queue.get\",\"type\":\"overview\",\"sid\":\"" + zbxApiToken + "\"}"; +// objectObjectMap = Forest.post("/zabbix/monitor").host(host).port(12800).contentTypeJson().addBody(body).executeAsMap(); + + ForestRequest forestRequest = Forest.post("/zabbix/monitor").host(host).port(12800).contentTypeJson(); + String body = "{\"request\":\"status.get\",\"type\":\"full\",\"sid\":\"" + zbxApiToken + "\"}"; + Map objectObjectMap = forestRequest.addBody(body).executeAsMap(); + formatStr(objectObjectMap.get("data").toString(), proxyMonitorInfoMap, proxyList); + + +// body = "{\"request\":\"status.get\",\"type\":\"ping\",\"sid\":\"" + zbxApiToken + "\"}"; +// objectObjectMap = Forest.post("/zabbix/monitor").host(host).port(12800).contentTypeJson().addBody(body).executeAsMap(); + + return proxyMonitorInfoMap.values(); + } + + public void formatStr(String data, Map proxyMonitorInfoMap, List proxyList) { + if (ToolUtil.isEmpty(data)) { + return; + } + proxyList.forEach(proxy -> { + ProxyMonitorInfo proxyMonitorInfo = new ProxyMonitorInfo(); + proxyMonitorInfo.setProxyId(proxy.getZbxId()); + proxyMonitorInfo.setProxyName(proxy.getName()); + proxyMonitorInfoMap.put(proxy.getZbxId(), proxyMonitorInfo); + }); + + formatHosts(data, proxyMonitorInfoMap); + formatItems(data, proxyMonitorInfoMap); +// formatTriggers(data, proxyMonitorInfoMap); + formatNvps(data, proxyMonitorInfoMap); + } + + private void formatNvps(String data, Map proxyMonitorInfoMap) { + List stats = JSONObject.parseArray(JSONObject.parseObject(data).getString("required performance"), ZbxServerInfo.class); + + for (ZbxServerInfo performance : stats) { + String proxyid = performance.getAttributes().getProxyid(); + if ("0".equals(proxyid)) { + continue; + } + + proxyMonitorInfoMap.get(proxyid).setNvps(String.format("%.2f", Float.parseFloat(performance.getCount()))); + + } + } + +// private void formatTriggers(String data, Map proxyMonitorInfoMap) { +// List stats = JSONObject.parseArray(JSONObject.parseObject(data).getString("trigger stats"), ZbxServerInfo.class); +// +// for (ZbxServerInfo triggerStat : stats) { +// String proxyid = triggerStat.getAttributes().getProxyid(); +// if ("0".equals(proxyid)) { +// continue; +// } +// if (triggerStat.getAttributes().getStatus() == 0) { +// proxyMonitorInfoMap.get(proxyid).setTriggerStatusEnable(triggerStat.getCount()); +// } else { +// proxyMonitorInfoMap.get(proxyid).setTriggerStatusDisable(triggerStat.getCount()); +// } +// } +// } + + private void formatItems(String data, Map proxyMonitorInfoMap) { + List stats = JSONObject.parseArray(JSONObject.parseObject(data).getString("item stats"), ZbxServerInfo.class); + + for (ZbxServerInfo itemsStat : stats) { + String proxyid = itemsStat.getAttributes().getProxyid(); + if ("0".equals(proxyid)) { + continue; + } + if (itemsStat.getAttributes().getStatus() == 0) { + if (itemsStat.getAttributes().getState() == 0) { + proxyMonitorInfoMap.get(proxyid).setItemStatusEnable(Integer.parseInt(itemsStat.getCount())); + } else { + proxyMonitorInfoMap.get(proxyid).setItemStatusUnSupport(Integer.parseInt(itemsStat.getCount())); + } + } else { + proxyMonitorInfoMap.get(proxyid).setItemStatusDisable(Integer.parseInt(itemsStat.getCount())); + } + } + } + + public void formatHosts(String data, Map proxyMonitorInfoMap) { + + List hostStats = JSONObject.parseArray(JSONObject.parseObject(data).getString("host stats"), ZbxServerInfo.class); + + for (ZbxServerInfo hostStat : hostStats) { + String proxyid = hostStat.getAttributes().getProxyid(); + if ("0".equals(proxyid)) { + continue; + } + if (hostStat.getAttributes().getStatus() == 0) { + proxyMonitorInfoMap.get(proxyid).setHostStatusEnable(Integer.parseInt(hostStat.getCount())); + } else { + proxyMonitorInfoMap.get(proxyid).setHostStatusDisable(Integer.parseInt(hostStat.getCount())); + } + } + } + + + @Data + static class Proxyids { + private String[] proxyids; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/MisfireStrategyEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/MisfireStrategyEnum.java new file mode 100644 index 00000000..f99213b8 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/MisfireStrategyEnum.java @@ -0,0 +1,34 @@ +package com.zmops.iot.web.schedule; + +public enum MisfireStrategyEnum { + + /** + * do nothing + */ + DO_NOTHING("Do nothing"), + + /** + * fire once now + */ + FIRE_ONCE_NOW("Fire once now"); + + private final String title; + + MisfireStrategyEnum(String title) { + this.title = title; + } + + public String getTitle() { + return title; + } + + public static MisfireStrategyEnum match(String name, MisfireStrategyEnum defaultItem) { + for (MisfireStrategyEnum item : MisfireStrategyEnum.values()) { + if (item.name().equals(name)) { + return item; + } + } + return defaultItem; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/ScheduleTypeEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/ScheduleTypeEnum.java new file mode 100644 index 00000000..ac1a9475 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/ScheduleTypeEnum.java @@ -0,0 +1,34 @@ +package com.zmops.iot.web.schedule; + +/** + * 调度任务类型 + */ +public enum ScheduleTypeEnum { + + NONE("None"), + + /** + * schedule by cron + */ + CRON("Cron"); + + private final String title; + + ScheduleTypeEnum(String title) { + this.title = title; + } + + public String getTitle() { + return title; + } + + public static ScheduleTypeEnum match(String name, ScheduleTypeEnum defaultItem) { + for (ScheduleTypeEnum item : ScheduleTypeEnum.values()) { + if (item.name().equals(name)) { + return item; + } + } + return defaultItem; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java new file mode 100644 index 00000000..475d46bf --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskScheduleImpl.java @@ -0,0 +1,261 @@ +package com.zmops.iot.web.schedule; + +import com.zmops.iot.domain.schedule.Task; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.web.schedule.config.ScheduleConfig; +import com.zmops.iot.schedule.cron.CronExpression; +import io.ebean.DB; +import lombok.extern.slf4j.Slf4j; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +/** + * @author nantian created at 2021/11/12 10:54 + */ + +@Slf4j +public class TaskScheduleImpl { + + private final ScheduleConfig scheduleConfig; + + public TaskScheduleImpl(ScheduleConfig scheduleConfig) { + this.scheduleConfig = scheduleConfig; + } + + public static final long PRE_READ_MS = 5000; // pre read + + private Thread scheduleThread; + private Thread ringThread; + private volatile boolean scheduleThreadToStop = false; + private volatile boolean ringThreadToStop = false; + private static final Map> ringData = new ConcurrentHashMap<>(); + + + public void start() { + scheduleThread = new Thread(() -> { + try { + TimeUnit.MILLISECONDS.sleep(5000 - System.currentTimeMillis() % 1000); + } catch (InterruptedException e) { + if (!scheduleThreadToStop) { + log.error(e.getMessage(), e); + } + } + + int preReadCount = (scheduleConfig.getTriggerPoolFastMax() + scheduleConfig.getTriggerPoolSlowMax()) * 20; + + while (!scheduleThreadToStop) { + long start = System.currentTimeMillis(); + boolean preReadSuc = true; + + try { + DB.beginTransaction(); + + long nowTime = System.currentTimeMillis(); + List taskList = DB.findNative(Task.class, + "SELECT T.ID, T.remark, T.trigger_status, T.trigger_next_time, T.schedule_type, T.schedule_conf " + + " FROM task_info AS T " + + " WHERE T.trigger_status = '"+ CommonStatus.ENABLE.getCode() +"' " + + " and t.trigger_next_time <= :nextTime " + + " ORDER BY ID ASC " + + " LIMIT :preReadCount") + .setParameter("nextTime", nowTime + PRE_READ_MS) + .setParameter("preReadCount", preReadCount) + .findList(); + + if (taskList.size() > 0) { + for (Task task : taskList) { + + if (nowTime > task.getTriggerNextTime() + PRE_READ_MS) { + MisfireStrategyEnum misfireStrategyEnum = MisfireStrategyEnum.match(task.getMisfireStrategy(), MisfireStrategyEnum.DO_NOTHING); + + if (MisfireStrategyEnum.FIRE_ONCE_NOW == misfireStrategyEnum) { + TaskTriggerPool.trigger(task.getId(), TriggerTypeEnum.MISFIRE, -1, task.getExecutorParam(), null); + } + refreshNextValidTime(task, new Date()); + + } else if (nowTime > task.getTriggerNextTime()) { + + TaskTriggerPool.trigger(task.getId(), TriggerTypeEnum.CRON, -1, task.getExecutorParam(), null); + refreshNextValidTime(task, new Date()); + + if (CommonStatus.ENABLE.getCode().equals(task.getTriggerStatus()) && nowTime + PRE_READ_MS > task.getTriggerNextTime()) { + int ringSecond = (int) ((task.getTriggerNextTime() / 1000) % 60); + pushTimeRing(ringSecond, task.getExecutorParam()); + refreshNextValidTime(task, new Date(task.getTriggerNextTime())); + } + } else { + int ringSecond = (int) ((task.getTriggerNextTime() / 1000) % 60); + pushTimeRing(ringSecond, task.getExecutorParam()); + refreshNextValidTime(task, new Date(task.getTriggerNextTime())); + } + } + DB.updateAll(taskList); + + } else { + preReadSuc = false; + } + + } catch (Exception e) { + if (!scheduleThreadToStop) { + log.error("JobScheduleHelper error: {}", e.getMessage()); + } + } finally { + DB.commitTransaction(); + } + + long cost = System.currentTimeMillis() - start; + + if (cost < 1000) { // scan-overtime, not wait + try { + TimeUnit.MILLISECONDS.sleep((preReadSuc ? 1000 : PRE_READ_MS) - System.currentTimeMillis() % 1000); + } catch (InterruptedException e) { + if (!scheduleThreadToStop) { + log.error(e.getMessage(), e); + } + } + } + } + log.info("JobScheduleHelper#scheduleThread stop"); + }); + + scheduleThread.setDaemon(true); + scheduleThread.setName("JobScheduleHelper#scheduleThread"); + scheduleThread.start(); + + ringThread = new Thread(() -> { + while (!ringThreadToStop) { + + try { + TimeUnit.MILLISECONDS.sleep(1000 - System.currentTimeMillis() % 1000); + } catch (InterruptedException e) { + if (!ringThreadToStop) { + log.error(e.getMessage(), e); + } + } + + try { + List ringItemData = new ArrayList<>(); + int nowSecond = Calendar.getInstance().get(Calendar.SECOND); // 避免处理耗时太长,跨过刻度,向前校验一个刻度; + for (int i = 0; i < 2; i++) { + List tmpData = ringData.remove((nowSecond + 60 - i) % 60); + if (tmpData != null) { + ringItemData.addAll(tmpData); + } + } + + log.debug("time-ring beat : " + nowSecond + " = " + Collections.singletonList(ringItemData)); + if (ringItemData.size() > 0) { + + for (String param : ringItemData) { + TaskTriggerPool.trigger(0, TriggerTypeEnum.CRON, -1, param, null); + } + ringItemData.clear(); + } + } catch (Exception e) { + if (!ringThreadToStop) { + log.error("JobScheduleHelper#ringThread error:{}", e.getMessage()); + } + } + } + log.info("JobScheduleHelper#ringThread stop"); + }); + ringThread.setDaemon(true); + ringThread.setName("admin JobScheduleHelper#ringThread"); + ringThread.start(); + } + + private void refreshNextValidTime(Task task, Date fromTime) throws Exception { + Date nextValidTime = generateNextValidTime(task, fromTime); + if (nextValidTime != null) { + task.setTriggerLastTime(task.getTriggerNextTime()); + task.setTriggerNextTime(nextValidTime.getTime()); + } else { + task.setTriggerStatus(CommonStatus.DISABLE.getCode()); + task.setTriggerLastTime(0L); + task.setTriggerNextTime(0L); + log.warn("refreshNextValidTime fail for job: jobId={}, scheduleType={}, scheduleConf={}", task.getId(), task.getScheduleType(), task.getScheduleConf()); + } + } + + private void pushTimeRing(int ringSecond, String executeParam) { + List ringItemData = ringData.computeIfAbsent(ringSecond, k -> new ArrayList()); + ringItemData.add(executeParam); + } + + + /** + * 停止任务调度 + */ + public void toStop() { + + scheduleThreadToStop = true; + try { + TimeUnit.SECONDS.sleep(1); // wait + } catch (InterruptedException e) { + log.error(e.getMessage(), e); + } + if (scheduleThread.getState() != Thread.State.TERMINATED) { + scheduleThread.interrupt(); + try { + scheduleThread.join(); + } catch (InterruptedException e) { + log.error(e.getMessage(), e); + } + } + + boolean hasRingData = false; + if (!ringData.isEmpty()) { + for (int second : ringData.keySet()) { + List tmpData = ringData.get(second); + if (tmpData != null && tmpData.size() > 0) { + hasRingData = true; + break; + } + } + } + if (hasRingData) { + try { + TimeUnit.SECONDS.sleep(8); + } catch (InterruptedException e) { + log.error(e.getMessage(), e); + } + } + + ringThreadToStop = true; + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + log.error(e.getMessage(), e); + } + if (ringThread.getState() != Thread.State.TERMINATED) { + ringThread.interrupt(); + try { + ringThread.join(); + } catch (InterruptedException e) { + log.error(e.getMessage(), e); + } + } + + log.info("JobScheduleHelper stop"); + } + + /** + * 根据表达式,获取下次任务调度执行时间 + * + * @param task + * @param fromTime + * @return + * @throws Exception + */ + public static Date generateNextValidTime(Task task, Date fromTime) throws Exception { + ScheduleTypeEnum scheduleTypeEnum = ScheduleTypeEnum.match(task.getScheduleType(), null); + if (ScheduleTypeEnum.CRON == scheduleTypeEnum) { + return new CronExpression(task.getScheduleConf()).getNextValidTimeAfter(fromTime); + } + + return null; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java new file mode 100644 index 00000000..9d8ddc56 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskStarter.java @@ -0,0 +1,45 @@ +package com.zmops.iot.web.schedule; + + +import com.zmops.iot.web.device.service.SceneScheduleProcessor; +import com.zmops.iot.web.schedule.config.ScheduleConfig; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; + +/** + * @author nantian created at 2021/11/12 22:35 + */ + +@Component +public class TaskStarter implements InitializingBean, DisposableBean { + + private TaskTriggerPool triggerPool; + private TaskScheduleImpl schedule; + + @Autowired + SceneScheduleProcessor sceneScheduleProcessor; + + @Autowired + private ApplicationEventPublisher publisher; + + @Override + public void destroy() throws Exception { + schedule.toStop(); + triggerPool.stop(); + } + + @Override + public void afterPropertiesSet() throws Exception { + + ScheduleConfig scheduleConfig = new ScheduleConfig(); + + triggerPool = new TaskTriggerPool(scheduleConfig, publisher); + triggerPool.start(); + + schedule = new TaskScheduleImpl(scheduleConfig); + schedule.start(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java new file mode 100644 index 00000000..eb735e19 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TaskTriggerPool.java @@ -0,0 +1,106 @@ +package com.zmops.iot.web.schedule; + +import com.zmops.iot.web.event.applicationEvent.SceneEvent; +import com.zmops.iot.web.event.applicationEvent.dto.SceneEventData; +import com.zmops.iot.web.schedule.config.ScheduleConfig; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEventPublisher; + +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author nantian created at 2021/11/12 22:10 + */ + +@Slf4j +public class TaskTriggerPool { + + private ThreadPoolExecutor fastTriggerPool = null; + private ThreadPoolExecutor slowTriggerPool = null; + + private ApplicationEventPublisher publisher; + + private final ScheduleConfig scheduleConfig; + + public TaskTriggerPool(ScheduleConfig scheduleConfig, ApplicationEventPublisher publisher) { + this.scheduleConfig = scheduleConfig; + this.publisher = publisher; + helper = this; + } + + public void start() { + fastTriggerPool = new ThreadPoolExecutor( + 10, + scheduleConfig.getTriggerPoolFastMax(), + 60L, + TimeUnit.SECONDS, + new LinkedBlockingQueue<>(1000), + r -> new Thread(r, "JobTriggerPoolHelper-fastTriggerPool-" + r.hashCode())); + + slowTriggerPool = new ThreadPoolExecutor( + 10, + scheduleConfig.getTriggerPoolSlowMax(), + 60L, + TimeUnit.SECONDS, + new LinkedBlockingQueue<>(2000), + r -> new Thread(r, "JobTriggerPoolHelper-slowTriggerPool-" + r.hashCode())); + } + + + public void stop() { + fastTriggerPool.shutdownNow(); + slowTriggerPool.shutdownNow(); + } + + private volatile long minTim = System.currentTimeMillis() / 60000; + private final ConcurrentMap jobTimeoutCountMap = new ConcurrentHashMap<>(); + + + public void addTrigger(final int jobId, + final TriggerTypeEnum triggerType, + final int failRetryCount, + final String executorParam, + final String addressList) { + + ThreadPoolExecutor triggerPool_ = fastTriggerPool; + AtomicInteger jobTimeoutCount = jobTimeoutCountMap.get(jobId); + if (jobTimeoutCount != null && jobTimeoutCount.get() > 10) { // job-timeout 10 times in 1 min + triggerPool_ = slowTriggerPool; + } + + triggerPool_.execute(() -> { + long start = System.currentTimeMillis(); + + try { + log.info("jobid : {},executeParam : {}", jobId,executorParam); + + publisher.publishEvent(new SceneEvent(this,new SceneEventData(executorParam))); + + } catch (Exception e) { + log.error(e.getMessage(), e); + } finally { + + long minTim_now = System.currentTimeMillis() / 60000; + if (minTim != minTim_now) { + minTim = minTim_now; + jobTimeoutCountMap.clear(); + } + + long cost = System.currentTimeMillis() - start; + if (cost > 500) { + AtomicInteger timeoutCount = jobTimeoutCountMap.putIfAbsent(jobId, new AtomicInteger(1)); + if (timeoutCount != null) { + timeoutCount.incrementAndGet(); + } + } + } + }); + } + + private static TaskTriggerPool helper; + + public static void trigger(int jobId, TriggerTypeEnum triggerType, int failRetryCount, String executorParam, String addressList) { + helper.addTrigger(jobId, triggerType, failRetryCount, executorParam, addressList); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TriggerTypeEnum.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TriggerTypeEnum.java new file mode 100644 index 00000000..57f365bd --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/TriggerTypeEnum.java @@ -0,0 +1,24 @@ +package com.zmops.iot.web.schedule; + +/** + * 触发类型 + */ +public enum TriggerTypeEnum { + + MANUAL("Manual trigger"), + CRON("Cron trigger"), + RETRY("Fail retry trigger"), + PARENT("Parent job trigger"), + MISFIRE("Misfire compensation trigger"); + + private TriggerTypeEnum(String title) { + this.title = title; + } + + private final String title; + + public String getTitle() { + return title; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/config/ScheduleConfig.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/config/ScheduleConfig.java new file mode 100644 index 00000000..98b24386 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/config/ScheduleConfig.java @@ -0,0 +1,40 @@ +package com.zmops.iot.web.schedule.config; + +import lombok.Data; + +/** + * @author nantian created at 2021/11/12 12:07 + */ + +@Data +public class ScheduleConfig { + + private int triggerPoolFastMax = 200; + + private int triggerPoolSlowMax = 100; + + private int logretentiondays = 30; + + + public int getTriggerPoolFastMax() { + if (triggerPoolFastMax < 200) { + return 200; + } + return triggerPoolFastMax; + } + + public int getTriggerPoolSlowMax() { + if (triggerPoolSlowMax < 100) { + return 100; + } + return triggerPoolSlowMax; + } + + + public int getLogretentiondays() { + if (logretentiondays < 7) { + return -1; // Limit greater than or equal to 7, otherwise close + } + return logretentiondays; + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/cron/CronExpression.java b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/cron/CronExpression.java new file mode 100644 index 00000000..12739cc3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/schedule/cron/CronExpression.java @@ -0,0 +1,1657 @@ +/* + * All content copyright Terracotta, Inc., unless otherwise indicated. All rights reserved. + * + * 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 + * + * http://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.zmops.iot.schedule.cron; + +import java.io.Serializable; +import java.text.ParseException; +import java.util.*; + +/** + * Provides a parser and evaluator for unix-like cron expressions. Cron + * expressions provide the ability to specify complex time combinations such as + * "At 8:00am every Monday through Friday" or "At 1:30am every + * last Friday of the month". + *

+ * Cron expressions are comprised of 6 required fields and one optional field + * separated by white space. The fields respectively are described as follows: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Field Name Allowed Values Allowed Special Characters
Seconds  + * 0-59  + * , - * /
Minutes  + * 0-59  + * , - * /
Hours  + * 0-23  + * , - * /
Day-of-month  + * 1-31  + * , - * ? / L W
Month  + * 0-11 or JAN-DEC  + * , - * /
Day-of-Week  + * 1-7 or SUN-SAT  + * , - * ? / L #
Year (Optional)  + * empty, 1970-2199  + * , - * /
+ *

+ * The '*' character is used to specify all values. For example, "*" + * in the minute field means "every minute". + *

+ * The '?' character is allowed for the day-of-month and day-of-week fields. It + * is used to specify 'no specific value'. This is useful when you need to + * specify something in one of the two fields, but not the other. + *

+ * The '-' character is used to specify ranges For example "10-12" in + * the hour field means "the hours 10, 11 and 12". + *

+ * The ',' character is used to specify additional values. For example + * "MON,WED,FRI" in the day-of-week field means "the days Monday, + * Wednesday, and Friday". + *

+ * The '/' character is used to specify increments. For example "0/15" + * in the seconds field means "the seconds 0, 15, 30, and 45". And + * "5/15" in the seconds field means "the seconds 5, 20, 35, and + * 50". Specifying '*' before the '/' is equivalent to specifying 0 is + * the value to start with. Essentially, for each field in the expression, there + * is a set of numbers that can be turned on or off. For seconds and minutes, + * the numbers range from 0 to 59. For hours 0 to 23, for days of the month 0 to + * 31, and for months 0 to 11 (JAN to DEC). The "/" character simply helps you turn + * on every "nth" value in the given set. Thus "7/6" in the + * month field only turns on month "7", it does NOT mean every 6th + * month, please note that subtlety. + *

+ * The 'L' character is allowed for the day-of-month and day-of-week fields. + * This character is short-hand for "last", but it has different + * meaning in each of the two fields. For example, the value "L" in + * the day-of-month field means "the last day of the month" - day 31 + * for January, day 28 for February on non-leap years. If used in the + * day-of-week field by itself, it simply means "7" or + * "SAT". But if used in the day-of-week field after another value, it + * means "the last xxx day of the month" - for example "6L" + * means "the last friday of the month". You can also specify an offset + * from the last day of the month, such as "L-3" which would mean the third-to-last + * day of the calendar month. When using the 'L' option, it is important not to + * specify lists, or ranges of values, as you'll get confusing/unexpected results. + *

+ * The 'W' character is allowed for the day-of-month field. This character + * is used to specify the weekday (Monday-Friday) nearest the given day. As an + * example, if you were to specify "15W" as the value for the + * day-of-month field, the meaning is: "the nearest weekday to the 15th of + * the month". So if the 15th is a Saturday, the trigger will fire on + * Friday the 14th. If the 15th is a Sunday, the trigger will fire on Monday the + * 16th. If the 15th is a Tuesday, then it will fire on Tuesday the 15th. + * However if you specify "1W" as the value for day-of-month, and the + * 1st is a Saturday, the trigger will fire on Monday the 3rd, as it will not + * 'jump' over the boundary of a month's days. The 'W' character can only be + * specified when the day-of-month is a single day, not a range or list of days. + *

+ * The 'L' and 'W' characters can also be combined for the day-of-month + * expression to yield 'LW', which translates to "last weekday of the + * month". + *

+ * The '#' character is allowed for the day-of-week field. This character is + * used to specify "the nth" XXX day of the month. For example, the + * value of "6#3" in the day-of-week field means the third Friday of + * the month (day 6 = Friday and "#3" = the 3rd one in the month). + * Other examples: "2#1" = the first Monday of the month and + * "4#5" = the fifth Wednesday of the month. Note that if you specify + * "#5" and there is not 5 of the given day-of-week in the month, then + * no firing will occur that month. If the '#' character is used, there can + * only be one expression in the day-of-week field ("3#1,6#3" is + * not valid, since there are two expressions). + *

+ * + *

+ * The legal characters and the names of months and days of the week are not + * case sensitive. + * + *

+ * NOTES: + *

    + *
  • Support for specifying both a day-of-week and a day-of-month value is + * not complete (you'll need to use the '?' character in one of these fields). + *
  • + *
  • Overflowing ranges is supported - that is, having a larger number on + * the left hand side than the right. You might do 22-2 to catch 10 o'clock + * at night until 2 o'clock in the morning, or you might have NOV-FEB. It is + * very important to note that overuse of overflowing ranges creates ranges + * that don't make sense and no effort has been made to determine which + * interpretation CronExpression chooses. An example would be + * "0 0 14-6 ? * FRI-MON".
  • + *
+ *

+ * + * + * @author Sharada Jambula, James House + * @author Contributions from Mads Henderson + * @author Refactoring from CronTrigger to CronExpression by Aaron Craven + * + * Borrowed from quartz v2.3.1 + * + */ +public final class CronExpression implements Serializable, Cloneable { + + private static final long serialVersionUID = 12423409423L; + + protected static final int SECOND = 0; + protected static final int MINUTE = 1; + protected static final int HOUR = 2; + protected static final int DAY_OF_MONTH = 3; + protected static final int MONTH = 4; + protected static final int DAY_OF_WEEK = 5; + protected static final int YEAR = 6; + protected static final int ALL_SPEC_INT = 99; // '*' + protected static final int NO_SPEC_INT = 98; // '?' + protected static final Integer ALL_SPEC = ALL_SPEC_INT; + protected static final Integer NO_SPEC = NO_SPEC_INT; + + protected static final Map monthMap = new HashMap(20); + protected static final Map dayMap = new HashMap(60); + static { + monthMap.put("JAN", 0); + monthMap.put("FEB", 1); + monthMap.put("MAR", 2); + monthMap.put("APR", 3); + monthMap.put("MAY", 4); + monthMap.put("JUN", 5); + monthMap.put("JUL", 6); + monthMap.put("AUG", 7); + monthMap.put("SEP", 8); + monthMap.put("OCT", 9); + monthMap.put("NOV", 10); + monthMap.put("DEC", 11); + + dayMap.put("SUN", 1); + dayMap.put("MON", 2); + dayMap.put("TUE", 3); + dayMap.put("WED", 4); + dayMap.put("THU", 5); + dayMap.put("FRI", 6); + dayMap.put("SAT", 7); + } + + private final String cronExpression; + private TimeZone timeZone = null; + protected transient TreeSet seconds; + protected transient TreeSet minutes; + protected transient TreeSet hours; + protected transient TreeSet daysOfMonth; + protected transient TreeSet months; + protected transient TreeSet daysOfWeek; + protected transient TreeSet years; + + protected transient boolean lastdayOfWeek = false; + protected transient int nthdayOfWeek = 0; + protected transient boolean lastdayOfMonth = false; + protected transient boolean nearestWeekday = false; + protected transient int lastdayOffset = 0; + protected transient boolean expressionParsed = false; + + public static final int MAX_YEAR = Calendar.getInstance().get(Calendar.YEAR) + 100; + + /** + * Constructs a new CronExpression based on the specified + * parameter. + * + * @param cronExpression String representation of the cron expression the + * new object should represent + * @throws ParseException + * if the string expression cannot be parsed into a valid + * CronExpression + */ + public CronExpression(String cronExpression) throws ParseException { + if (cronExpression == null) { + throw new IllegalArgumentException("cronExpression cannot be null"); + } + + this.cronExpression = cronExpression.toUpperCase(Locale.US); + + buildExpression(this.cronExpression); + } + + /** + * Constructs a new {@code CronExpression} as a copy of an existing + * instance. + * + * @param expression + * The existing cron expression to be copied + */ + public CronExpression(CronExpression expression) { + /* + * We don't call the other constructor here since we need to swallow the + * ParseException. We also elide some of the sanity checking as it is + * not logically trippable. + */ + this.cronExpression = expression.getCronExpression(); + try { + buildExpression(cronExpression); + } catch (ParseException ex) { + throw new AssertionError(); + } + if (expression.getTimeZone() != null) { + setTimeZone((TimeZone) expression.getTimeZone().clone()); + } + } + + /** + * Indicates whether the given date satisfies the cron expression. Note that + * milliseconds are ignored, so two Dates falling on different milliseconds + * of the same second will always have the same result here. + * + * @param date the date to evaluate + * @return a boolean indicating whether the given date satisfies the cron + * expression + */ + public boolean isSatisfiedBy(Date date) { + Calendar testDateCal = Calendar.getInstance(getTimeZone()); + testDateCal.setTime(date); + testDateCal.set(Calendar.MILLISECOND, 0); + Date originalDate = testDateCal.getTime(); + + testDateCal.add(Calendar.SECOND, -1); + + Date timeAfter = getTimeAfter(testDateCal.getTime()); + + return ((timeAfter != null) && (timeAfter.equals(originalDate))); + } + + /** + * Returns the next date/time after the given date/time which + * satisfies the cron expression. + * + * @param date the date/time at which to begin the search for the next valid + * date/time + * @return the next valid date/time + */ + public Date getNextValidTimeAfter(Date date) { + return getTimeAfter(date); + } + + /** + * Returns the next date/time after the given date/time which does + * not satisfy the expression + * + * @param date the date/time at which to begin the search for the next + * invalid date/time + * @return the next valid date/time + */ + public Date getNextInvalidTimeAfter(Date date) { + long difference = 1000; + + //move back to the nearest second so differences will be accurate + Calendar adjustCal = Calendar.getInstance(getTimeZone()); + adjustCal.setTime(date); + adjustCal.set(Calendar.MILLISECOND, 0); + Date lastDate = adjustCal.getTime(); + + Date newDate; + + //FUTURE_TODO: (QUARTZ-481) IMPROVE THIS! The following is a BAD solution to this problem. Performance will be very bad here, depending on the cron expression. It is, however A solution. + + //keep getting the next included time until it's farther than one second + // apart. At that point, lastDate is the last valid fire time. We return + // the second immediately following it. + while (difference == 1000) { + newDate = getTimeAfter(lastDate); + if(newDate == null) + break; + + difference = newDate.getTime() - lastDate.getTime(); + + if (difference == 1000) { + lastDate = newDate; + } + } + + return new Date(lastDate.getTime() + 1000); + } + + /** + * Returns the time zone for which this CronExpression + * will be resolved. + */ + public TimeZone getTimeZone() { + if (timeZone == null) { + timeZone = TimeZone.getDefault(); + } + + return timeZone; + } + + /** + * Sets the time zone for which this CronExpression + * will be resolved. + */ + public void setTimeZone(TimeZone timeZone) { + this.timeZone = timeZone; + } + + /** + * Returns the string representation of the CronExpression + * + * @return a string representation of the CronExpression + */ + @Override + public String toString() { + return cronExpression; + } + + /** + * Indicates whether the specified cron expression can be parsed into a + * valid cron expression + * + * @param cronExpression the expression to evaluate + * @return a boolean indicating whether the given expression is a valid cron + * expression + */ + public static boolean isValidExpression(String cronExpression) { + + try { + new CronExpression(cronExpression); + } catch (ParseException pe) { + return false; + } + + return true; + } + + public static void validateExpression(String cronExpression) throws ParseException { + + new CronExpression(cronExpression); + } + + + //////////////////////////////////////////////////////////////////////////// + // + // Expression Parsing Functions + // + //////////////////////////////////////////////////////////////////////////// + + protected void buildExpression(String expression) throws ParseException { + expressionParsed = true; + + try { + + if (seconds == null) { + seconds = new TreeSet(); + } + if (minutes == null) { + minutes = new TreeSet(); + } + if (hours == null) { + hours = new TreeSet(); + } + if (daysOfMonth == null) { + daysOfMonth = new TreeSet(); + } + if (months == null) { + months = new TreeSet(); + } + if (daysOfWeek == null) { + daysOfWeek = new TreeSet(); + } + if (years == null) { + years = new TreeSet(); + } + + int exprOn = SECOND; + + StringTokenizer exprsTok = new StringTokenizer(expression, " \t", + false); + + while (exprsTok.hasMoreTokens() && exprOn <= YEAR) { + String expr = exprsTok.nextToken().trim(); + + // throw an exception if L is used with other days of the month + if(exprOn == DAY_OF_MONTH && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(",")) { + throw new ParseException("Support for specifying 'L' and 'LW' with other days of the month is not implemented", -1); + } + // throw an exception if L is used with other days of the week + if(exprOn == DAY_OF_WEEK && expr.indexOf('L') != -1 && expr.length() > 1 && expr.contains(",")) { + throw new ParseException("Support for specifying 'L' with other days of the week is not implemented", -1); + } + if(exprOn == DAY_OF_WEEK && expr.indexOf('#') != -1 && expr.indexOf('#', expr.indexOf('#') +1) != -1) { + throw new ParseException("Support for specifying multiple \"nth\" days is not implemented.", -1); + } + + StringTokenizer vTok = new StringTokenizer(expr, ","); + while (vTok.hasMoreTokens()) { + String v = vTok.nextToken(); + storeExpressionVals(0, v, exprOn); + } + + exprOn++; + } + + if (exprOn <= DAY_OF_WEEK) { + throw new ParseException("Unexpected end of expression.", + expression.length()); + } + + if (exprOn <= YEAR) { + storeExpressionVals(0, "*", YEAR); + } + + TreeSet dow = getSet(DAY_OF_WEEK); + TreeSet dom = getSet(DAY_OF_MONTH); + + // Copying the logic from the UnsupportedOperationException below + boolean dayOfMSpec = !dom.contains(NO_SPEC); + boolean dayOfWSpec = !dow.contains(NO_SPEC); + + if (!dayOfMSpec || dayOfWSpec) { + if (!dayOfWSpec || dayOfMSpec) { + throw new ParseException( + "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.", 0); + } + } + } catch (ParseException pe) { + throw pe; + } catch (Exception e) { + throw new ParseException("Illegal cron expression format (" + + e.toString() + ")", 0); + } + } + + protected int storeExpressionVals(int pos, String s, int type) + throws ParseException { + + int incr = 0; + int i = skipWhiteSpace(pos, s); + if (i >= s.length()) { + return i; + } + char c = s.charAt(i); + if ((c >= 'A') && (c <= 'Z') && (!s.equals("L")) && (!s.equals("LW")) && (!s.matches("^L-[0-9]*[W]?"))) { + String sub = s.substring(i, i + 3); + int sval = -1; + int eval = -1; + if (type == MONTH) { + sval = getMonthNumber(sub) + 1; + if (sval <= 0) { + throw new ParseException("Invalid Month value: '" + sub + "'", i); + } + if (s.length() > i + 3) { + c = s.charAt(i + 3); + if (c == '-') { + i += 4; + sub = s.substring(i, i + 3); + eval = getMonthNumber(sub) + 1; + if (eval <= 0) { + throw new ParseException("Invalid Month value: '" + sub + "'", i); + } + } + } + } else if (type == DAY_OF_WEEK) { + sval = getDayOfWeekNumber(sub); + if (sval < 0) { + throw new ParseException("Invalid Day-of-Week value: '" + + sub + "'", i); + } + if (s.length() > i + 3) { + c = s.charAt(i + 3); + if (c == '-') { + i += 4; + sub = s.substring(i, i + 3); + eval = getDayOfWeekNumber(sub); + if (eval < 0) { + throw new ParseException( + "Invalid Day-of-Week value: '" + sub + + "'", i); + } + } else if (c == '#') { + try { + i += 4; + nthdayOfWeek = Integer.parseInt(s.substring(i)); + if (nthdayOfWeek < 1 || nthdayOfWeek > 5) { + throw new Exception(); + } + } catch (Exception e) { + throw new ParseException( + "A numeric value between 1 and 5 must follow the '#' option", + i); + } + } else if (c == 'L') { + lastdayOfWeek = true; + i++; + } + } + + } else { + throw new ParseException( + "Illegal characters for this position: '" + sub + "'", + i); + } + if (eval != -1) { + incr = 1; + } + addToSet(sval, eval, incr, type); + return (i + 3); + } + + if (c == '?') { + i++; + if ((i + 1) < s.length() + && (s.charAt(i) != ' ' && s.charAt(i + 1) != '\t')) { + throw new ParseException("Illegal character after '?': " + + s.charAt(i), i); + } + if (type != DAY_OF_WEEK && type != DAY_OF_MONTH) { + throw new ParseException( + "'?' can only be specified for Day-of-Month or Day-of-Week.", + i); + } + if (type == DAY_OF_WEEK && !lastdayOfMonth) { + int val = daysOfMonth.last(); + if (val == NO_SPEC_INT) { + throw new ParseException( + "'?' can only be specified for Day-of-Month -OR- Day-of-Week.", + i); + } + } + + addToSet(NO_SPEC_INT, -1, 0, type); + return i; + } + + if (c == '*' || c == '/') { + if (c == '*' && (i + 1) >= s.length()) { + addToSet(ALL_SPEC_INT, -1, incr, type); + return i + 1; + } else if (c == '/' + && ((i + 1) >= s.length() || s.charAt(i + 1) == ' ' || s + .charAt(i + 1) == '\t')) { + throw new ParseException("'/' must be followed by an integer.", i); + } else if (c == '*') { + i++; + } + c = s.charAt(i); + if (c == '/') { // is an increment specified? + i++; + if (i >= s.length()) { + throw new ParseException("Unexpected end of string.", i); + } + + incr = getNumericValue(s, i); + + i++; + if (incr > 10) { + i++; + } + checkIncrementRange(incr, type, i); + } else { + incr = 1; + } + + addToSet(ALL_SPEC_INT, -1, incr, type); + return i; + } else if (c == 'L') { + i++; + if (type == DAY_OF_MONTH) { + lastdayOfMonth = true; + } + if (type == DAY_OF_WEEK) { + addToSet(7, 7, 0, type); + } + if(type == DAY_OF_MONTH && s.length() > i) { + c = s.charAt(i); + if(c == '-') { + ValueSet vs = getValue(0, s, i+1); + lastdayOffset = vs.value; + if(lastdayOffset > 30) + throw new ParseException("Offset from last day must be <= 30", i+1); + i = vs.pos; + } + if(s.length() > i) { + c = s.charAt(i); + if(c == 'W') { + nearestWeekday = true; + i++; + } + } + } + return i; + } else if (c >= '0' && c <= '9') { + int val = Integer.parseInt(String.valueOf(c)); + i++; + if (i >= s.length()) { + addToSet(val, -1, -1, type); + } else { + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(val, s, i); + val = vs.value; + i = vs.pos; + } + i = checkNext(i, s, val, type); + return i; + } + } else { + throw new ParseException("Unexpected character: " + c, i); + } + + return i; + } + + private void checkIncrementRange(int incr, int type, int idxPos) throws ParseException { + if (incr > 59 && (type == SECOND || type == MINUTE)) { + throw new ParseException("Increment > 60 : " + incr, idxPos); + } else if (incr > 23 && (type == HOUR)) { + throw new ParseException("Increment > 24 : " + incr, idxPos); + } else if (incr > 31 && (type == DAY_OF_MONTH)) { + throw new ParseException("Increment > 31 : " + incr, idxPos); + } else if (incr > 7 && (type == DAY_OF_WEEK)) { + throw new ParseException("Increment > 7 : " + incr, idxPos); + } else if (incr > 12 && (type == MONTH)) { + throw new ParseException("Increment > 12 : " + incr, idxPos); + } + } + + protected int checkNext(int pos, String s, int val, int type) + throws ParseException { + + int end = -1; + int i = pos; + + if (i >= s.length()) { + addToSet(val, end, -1, type); + return i; + } + + char c = s.charAt(pos); + + if (c == 'L') { + if (type == DAY_OF_WEEK) { + if(val < 1 || val > 7) + throw new ParseException("Day-of-Week values must be between 1 and 7", -1); + lastdayOfWeek = true; + } else { + throw new ParseException("'L' option is not valid here. (pos=" + i + ")", i); + } + TreeSet set = getSet(type); + set.add(val); + i++; + return i; + } + + if (c == 'W') { + if (type == DAY_OF_MONTH) { + nearestWeekday = true; + } else { + throw new ParseException("'W' option is not valid here. (pos=" + i + ")", i); + } + if(val > 31) + throw new ParseException("The 'W' option does not make sense with values larger than 31 (max number of days in a month)", i); + TreeSet set = getSet(type); + set.add(val); + i++; + return i; + } + + if (c == '#') { + if (type != DAY_OF_WEEK) { + throw new ParseException("'#' option is not valid here. (pos=" + i + ")", i); + } + i++; + try { + nthdayOfWeek = Integer.parseInt(s.substring(i)); + if (nthdayOfWeek < 1 || nthdayOfWeek > 5) { + throw new Exception(); + } + } catch (Exception e) { + throw new ParseException( + "A numeric value between 1 and 5 must follow the '#' option", + i); + } + + TreeSet set = getSet(type); + set.add(val); + i++; + return i; + } + + if (c == '-') { + i++; + c = s.charAt(i); + int v = Integer.parseInt(String.valueOf(c)); + end = v; + i++; + if (i >= s.length()) { + addToSet(val, end, 1, type); + return i; + } + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(v, s, i); + end = vs.value; + i = vs.pos; + } + if (i < s.length() && ((c = s.charAt(i)) == '/')) { + i++; + c = s.charAt(i); + int v2 = Integer.parseInt(String.valueOf(c)); + i++; + if (i >= s.length()) { + addToSet(val, end, v2, type); + return i; + } + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(v2, s, i); + int v3 = vs.value; + addToSet(val, end, v3, type); + i = vs.pos; + return i; + } else { + addToSet(val, end, v2, type); + return i; + } + } else { + addToSet(val, end, 1, type); + return i; + } + } + + if (c == '/') { + if ((i + 1) >= s.length() || s.charAt(i + 1) == ' ' || s.charAt(i + 1) == '\t') { + throw new ParseException("'/' must be followed by an integer.", i); + } + + i++; + c = s.charAt(i); + int v2 = Integer.parseInt(String.valueOf(c)); + i++; + if (i >= s.length()) { + checkIncrementRange(v2, type, i); + addToSet(val, end, v2, type); + return i; + } + c = s.charAt(i); + if (c >= '0' && c <= '9') { + ValueSet vs = getValue(v2, s, i); + int v3 = vs.value; + checkIncrementRange(v3, type, i); + addToSet(val, end, v3, type); + i = vs.pos; + return i; + } else { + throw new ParseException("Unexpected character '" + c + "' after '/'", i); + } + } + + addToSet(val, end, 0, type); + i++; + return i; + } + + public String getCronExpression() { + return cronExpression; + } + + public String getExpressionSummary() { + StringBuilder buf = new StringBuilder(); + + buf.append("seconds: "); + buf.append(getExpressionSetSummary(seconds)); + buf.append("\n"); + buf.append("minutes: "); + buf.append(getExpressionSetSummary(minutes)); + buf.append("\n"); + buf.append("hours: "); + buf.append(getExpressionSetSummary(hours)); + buf.append("\n"); + buf.append("daysOfMonth: "); + buf.append(getExpressionSetSummary(daysOfMonth)); + buf.append("\n"); + buf.append("months: "); + buf.append(getExpressionSetSummary(months)); + buf.append("\n"); + buf.append("daysOfWeek: "); + buf.append(getExpressionSetSummary(daysOfWeek)); + buf.append("\n"); + buf.append("lastdayOfWeek: "); + buf.append(lastdayOfWeek); + buf.append("\n"); + buf.append("nearestWeekday: "); + buf.append(nearestWeekday); + buf.append("\n"); + buf.append("NthDayOfWeek: "); + buf.append(nthdayOfWeek); + buf.append("\n"); + buf.append("lastdayOfMonth: "); + buf.append(lastdayOfMonth); + buf.append("\n"); + buf.append("years: "); + buf.append(getExpressionSetSummary(years)); + buf.append("\n"); + + return buf.toString(); + } + + protected String getExpressionSetSummary(java.util.Set set) { + + if (set.contains(NO_SPEC)) { + return "?"; + } + if (set.contains(ALL_SPEC)) { + return "*"; + } + + StringBuilder buf = new StringBuilder(); + + Iterator itr = set.iterator(); + boolean first = true; + while (itr.hasNext()) { + Integer iVal = itr.next(); + String val = iVal.toString(); + if (!first) { + buf.append(","); + } + buf.append(val); + first = false; + } + + return buf.toString(); + } + + protected String getExpressionSetSummary(java.util.ArrayList list) { + + if (list.contains(NO_SPEC)) { + return "?"; + } + if (list.contains(ALL_SPEC)) { + return "*"; + } + + StringBuilder buf = new StringBuilder(); + + Iterator itr = list.iterator(); + boolean first = true; + while (itr.hasNext()) { + Integer iVal = itr.next(); + String val = iVal.toString(); + if (!first) { + buf.append(","); + } + buf.append(val); + first = false; + } + + return buf.toString(); + } + + protected int skipWhiteSpace(int i, String s) { + for (; i < s.length() && (s.charAt(i) == ' ' || s.charAt(i) == '\t'); i++) { + } + + return i; + } + + protected int findNextWhiteSpace(int i, String s) { + for (; i < s.length() && (s.charAt(i) != ' ' || s.charAt(i) != '\t'); i++) { + } + + return i; + } + + protected void addToSet(int val, int end, int incr, int type) + throws ParseException { + + TreeSet set = getSet(type); + + if (type == SECOND || type == MINUTE) { + if ((val < 0 || val > 59 || end > 59) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Minute and Second values must be between 0 and 59", + -1); + } + } else if (type == HOUR) { + if ((val < 0 || val > 23 || end > 23) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Hour values must be between 0 and 23", -1); + } + } else if (type == DAY_OF_MONTH) { + if ((val < 1 || val > 31 || end > 31) && (val != ALL_SPEC_INT) + && (val != NO_SPEC_INT)) { + throw new ParseException( + "Day of month values must be between 1 and 31", -1); + } + } else if (type == MONTH) { + if ((val < 1 || val > 12 || end > 12) && (val != ALL_SPEC_INT)) { + throw new ParseException( + "Month values must be between 1 and 12", -1); + } + } else if (type == DAY_OF_WEEK) { + if ((val == 0 || val > 7 || end > 7) && (val != ALL_SPEC_INT) + && (val != NO_SPEC_INT)) { + throw new ParseException( + "Day-of-Week values must be between 1 and 7", -1); + } + } + + if ((incr == 0 || incr == -1) && val != ALL_SPEC_INT) { + if (val != -1) { + set.add(val); + } else { + set.add(NO_SPEC); + } + + return; + } + + int startAt = val; + int stopAt = end; + + if (val == ALL_SPEC_INT && incr <= 0) { + incr = 1; + set.add(ALL_SPEC); // put in a marker, but also fill values + } + + if (type == SECOND || type == MINUTE) { + if (stopAt == -1) { + stopAt = 59; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 0; + } + } else if (type == HOUR) { + if (stopAt == -1) { + stopAt = 23; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 0; + } + } else if (type == DAY_OF_MONTH) { + if (stopAt == -1) { + stopAt = 31; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } + } else if (type == MONTH) { + if (stopAt == -1) { + stopAt = 12; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } + } else if (type == DAY_OF_WEEK) { + if (stopAt == -1) { + stopAt = 7; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1; + } + } else if (type == YEAR) { + if (stopAt == -1) { + stopAt = MAX_YEAR; + } + if (startAt == -1 || startAt == ALL_SPEC_INT) { + startAt = 1970; + } + } + + // if the end of the range is before the start, then we need to overflow into + // the next day, month etc. This is done by adding the maximum amount for that + // type, and using modulus max to determine the value being added. + int max = -1; + if (stopAt < startAt) { + switch (type) { + case SECOND : max = 60; break; + case MINUTE : max = 60; break; + case HOUR : max = 24; break; + case MONTH : max = 12; break; + case DAY_OF_WEEK : max = 7; break; + case DAY_OF_MONTH : max = 31; break; + case YEAR : throw new IllegalArgumentException("Start year must be less than stop year"); + default : throw new IllegalArgumentException("Unexpected type encountered"); + } + stopAt += max; + } + + for (int i = startAt; i <= stopAt; i += incr) { + if (max == -1) { + // ie: there's no max to overflow over + set.add(i); + } else { + // take the modulus to get the real value + int i2 = i % max; + + // 1-indexed ranges should not include 0, and should include their max + if (i2 == 0 && (type == MONTH || type == DAY_OF_WEEK || type == DAY_OF_MONTH) ) { + i2 = max; + } + + set.add(i2); + } + } + } + + TreeSet getSet(int type) { + switch (type) { + case SECOND: + return seconds; + case MINUTE: + return minutes; + case HOUR: + return hours; + case DAY_OF_MONTH: + return daysOfMonth; + case MONTH: + return months; + case DAY_OF_WEEK: + return daysOfWeek; + case YEAR: + return years; + default: + return null; + } + } + + protected ValueSet getValue(int v, String s, int i) { + char c = s.charAt(i); + StringBuilder s1 = new StringBuilder(String.valueOf(v)); + while (c >= '0' && c <= '9') { + s1.append(c); + i++; + if (i >= s.length()) { + break; + } + c = s.charAt(i); + } + ValueSet val = new ValueSet(); + + val.pos = (i < s.length()) ? i : i + 1; + val.value = Integer.parseInt(s1.toString()); + return val; + } + + protected int getNumericValue(String s, int i) { + int endOfVal = findNextWhiteSpace(i, s); + String val = s.substring(i, endOfVal); + return Integer.parseInt(val); + } + + protected int getMonthNumber(String s) { + Integer integer = monthMap.get(s); + + if (integer == null) { + return -1; + } + + return integer; + } + + protected int getDayOfWeekNumber(String s) { + Integer integer = dayMap.get(s); + + if (integer == null) { + return -1; + } + + return integer; + } + + //////////////////////////////////////////////////////////////////////////// + // + // Computation Functions + // + //////////////////////////////////////////////////////////////////////////// + + public Date getTimeAfter(Date afterTime) { + + // Computation is based on Gregorian year only. + Calendar cl = new java.util.GregorianCalendar(getTimeZone()); + + // move ahead one second, since we're computing the time *after* the + // given time + afterTime = new Date(afterTime.getTime() + 1000); + // CronTrigger does not deal with milliseconds + cl.setTime(afterTime); + cl.set(Calendar.MILLISECOND, 0); + + boolean gotOne = false; + // loop until we've computed the next time, or we've past the endTime + while (!gotOne) { + + //if (endTime != null && cl.getTime().after(endTime)) return null; + if(cl.get(Calendar.YEAR) > 2999) { // prevent endless loop... + return null; + } + + SortedSet st = null; + int t = 0; + + int sec = cl.get(Calendar.SECOND); + int min = cl.get(Calendar.MINUTE); + + // get second................................................. + st = seconds.tailSet(sec); + if (st != null && st.size() != 0) { + sec = st.first(); + } else { + sec = seconds.first(); + min++; + cl.set(Calendar.MINUTE, min); + } + cl.set(Calendar.SECOND, sec); + + min = cl.get(Calendar.MINUTE); + int hr = cl.get(Calendar.HOUR_OF_DAY); + t = -1; + + // get minute................................................. + st = minutes.tailSet(min); + if (st != null && st.size() != 0) { + t = min; + min = st.first(); + } else { + min = minutes.first(); + hr++; + } + if (min != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, min); + setCalendarHour(cl, hr); + continue; + } + cl.set(Calendar.MINUTE, min); + + hr = cl.get(Calendar.HOUR_OF_DAY); + int day = cl.get(Calendar.DAY_OF_MONTH); + t = -1; + + // get hour................................................... + st = hours.tailSet(hr); + if (st != null && st.size() != 0) { + t = hr; + hr = st.first(); + } else { + hr = hours.first(); + day++; + } + if (hr != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + setCalendarHour(cl, hr); + continue; + } + cl.set(Calendar.HOUR_OF_DAY, hr); + + day = cl.get(Calendar.DAY_OF_MONTH); + int mon = cl.get(Calendar.MONTH) + 1; + // '+ 1' because calendar is 0-based for this field, and we are + // 1-based + t = -1; + int tmon = mon; + + // get day................................................... + boolean dayOfMSpec = !daysOfMonth.contains(NO_SPEC); + boolean dayOfWSpec = !daysOfWeek.contains(NO_SPEC); + if (dayOfMSpec && !dayOfWSpec) { // get day by day of month rule + st = daysOfMonth.tailSet(day); + if (lastdayOfMonth) { + if(!nearestWeekday) { + t = day; + day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + day -= lastdayOffset; + if(t > day) { + mon++; + if(mon > 12) { + mon = 1; + tmon = 3333; // ensure test of mon != tmon further below fails + cl.add(Calendar.YEAR, 1); + } + day = 1; + } + } else { + t = day; + day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + day -= lastdayOffset; + + Calendar tcal = Calendar.getInstance(getTimeZone()); + tcal.set(Calendar.SECOND, 0); + tcal.set(Calendar.MINUTE, 0); + tcal.set(Calendar.HOUR_OF_DAY, 0); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + tcal.set(Calendar.YEAR, cl.get(Calendar.YEAR)); + + int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + int dow = tcal.get(Calendar.DAY_OF_WEEK); + + if(dow == Calendar.SATURDAY && day == 1) { + day += 2; + } else if(dow == Calendar.SATURDAY) { + day -= 1; + } else if(dow == Calendar.SUNDAY && day == ldom) { + day -= 2; + } else if(dow == Calendar.SUNDAY) { + day += 1; + } + + tcal.set(Calendar.SECOND, sec); + tcal.set(Calendar.MINUTE, min); + tcal.set(Calendar.HOUR_OF_DAY, hr); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + Date nTime = tcal.getTime(); + if(nTime.before(afterTime)) { + day = 1; + mon++; + } + } + } else if(nearestWeekday) { + t = day; + day = daysOfMonth.first(); + + Calendar tcal = Calendar.getInstance(getTimeZone()); + tcal.set(Calendar.SECOND, 0); + tcal.set(Calendar.MINUTE, 0); + tcal.set(Calendar.HOUR_OF_DAY, 0); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + tcal.set(Calendar.YEAR, cl.get(Calendar.YEAR)); + + int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + int dow = tcal.get(Calendar.DAY_OF_WEEK); + + if(dow == Calendar.SATURDAY && day == 1) { + day += 2; + } else if(dow == Calendar.SATURDAY) { + day -= 1; + } else if(dow == Calendar.SUNDAY && day == ldom) { + day -= 2; + } else if(dow == Calendar.SUNDAY) { + day += 1; + } + + + tcal.set(Calendar.SECOND, sec); + tcal.set(Calendar.MINUTE, min); + tcal.set(Calendar.HOUR_OF_DAY, hr); + tcal.set(Calendar.DAY_OF_MONTH, day); + tcal.set(Calendar.MONTH, mon - 1); + Date nTime = tcal.getTime(); + if(nTime.before(afterTime)) { + day = daysOfMonth.first(); + mon++; + } + } else if (st != null && st.size() != 0) { + t = day; + day = st.first(); + // make sure we don't over-run a short month, such as february + int lastDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + if (day > lastDay) { + day = daysOfMonth.first(); + mon++; + } + } else { + day = daysOfMonth.first(); + mon++; + } + + if (day != t || mon != tmon) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, and we + // are 1-based + continue; + } + } else if (dayOfWSpec && !dayOfMSpec) { // get day by day of week rule + if (lastdayOfWeek) { // are we looking for the last XXX day of + // the month? + int dow = daysOfWeek.first(); // desired + // d-o-w + int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int daysToAdd = 0; + if (cDow < dow) { + daysToAdd = dow - cDow; + } + if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } + + int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + + if (day + daysToAdd > lDay) { // did we already miss the + // last one? + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon); + // no '- 1' here because we are promoting the month + continue; + } + + // find date of last occurrence of this day in this month... + while ((day + daysToAdd + 7) <= lDay) { + daysToAdd += 7; + } + + day += daysToAdd; + + if (daysToAdd > 0) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' here because we are not promoting the month + continue; + } + + } else if (nthdayOfWeek != 0) { + // are we looking for the Nth XXX day in the month? + int dow = daysOfWeek.first(); // desired + // d-o-w + int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int daysToAdd = 0; + if (cDow < dow) { + daysToAdd = dow - cDow; + } else if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } + + boolean dayShifted = false; + if (daysToAdd > 0) { + dayShifted = true; + } + + day += daysToAdd; + int weekOfMonth = day / 7; + if (day % 7 > 0) { + weekOfMonth++; + } + + daysToAdd = (nthdayOfWeek - weekOfMonth) * 7; + day += daysToAdd; + if (daysToAdd < 0 + || day > getLastDayOfMonth(mon, cl + .get(Calendar.YEAR))) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon); + // no '- 1' here because we are promoting the month + continue; + } else if (daysToAdd > 0 || dayShifted) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' here because we are NOT promoting the month + continue; + } + } else { + int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int dow = daysOfWeek.first(); // desired + // d-o-w + st = daysOfWeek.tailSet(cDow); + if (st != null && st.size() > 0) { + dow = st.first(); + } + + int daysToAdd = 0; + if (cDow < dow) { + daysToAdd = dow - cDow; + } + if (cDow > dow) { + daysToAdd = dow + (7 - cDow); + } + + int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + + if (day + daysToAdd > lDay) { // will we pass the end of + // the month? + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon); + // no '- 1' here because we are promoting the month + continue; + } else if (daysToAdd > 0) { // are we swithing days? + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, day + daysToAdd); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, + // and we are 1-based + continue; + } + } + } else { // dayOfWSpec && !dayOfMSpec + throw new UnsupportedOperationException( + "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented."); + } + cl.set(Calendar.DAY_OF_MONTH, day); + + mon = cl.get(Calendar.MONTH) + 1; + // '+ 1' because calendar is 0-based for this field, and we are + // 1-based + int year = cl.get(Calendar.YEAR); + t = -1; + + // test for expressions that never generate a valid fire date, + // but keep looping... + if (year > MAX_YEAR) { + return null; + } + + // get month................................................... + st = months.tailSet(mon); + if (st != null && st.size() != 0) { + t = mon; + mon = st.first(); + } else { + mon = months.first(); + year++; + } + if (mon != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, and we are + // 1-based + cl.set(Calendar.YEAR, year); + continue; + } + cl.set(Calendar.MONTH, mon - 1); + // '- 1' because calendar is 0-based for this field, and we are + // 1-based + + year = cl.get(Calendar.YEAR); + t = -1; + + // get year................................................... + st = years.tailSet(year); + if (st != null && st.size() != 0) { + t = year; + year = st.first(); + } else { + return null; // ran out of years... + } + + if (year != t) { + cl.set(Calendar.SECOND, 0); + cl.set(Calendar.MINUTE, 0); + cl.set(Calendar.HOUR_OF_DAY, 0); + cl.set(Calendar.DAY_OF_MONTH, 1); + cl.set(Calendar.MONTH, 0); + // '- 1' because calendar is 0-based for this field, and we are + // 1-based + cl.set(Calendar.YEAR, year); + continue; + } + cl.set(Calendar.YEAR, year); + + gotOne = true; + } // while( !done ) + + return cl.getTime(); + } + + /** + * Advance the calendar to the particular hour paying particular attention + * to daylight saving problems. + * + * @param cal the calendar to operate on + * @param hour the hour to set + */ + protected void setCalendarHour(Calendar cal, int hour) { + cal.set(Calendar.HOUR_OF_DAY, hour); + if (cal.get(Calendar.HOUR_OF_DAY) != hour && hour != 24) { + cal.set(Calendar.HOUR_OF_DAY, hour + 1); + } + } + + /** + * NOT YET IMPLEMENTED: Returns the time before the given time + * that the CronExpression matches. + */ + public Date getTimeBefore(Date endTime) { + // FUTURE_TODO: implement QUARTZ-423 + return null; + } + + /** + * NOT YET IMPLEMENTED: Returns the final time that the + * CronExpression will match. + */ + public Date getFinalFireTime() { + // FUTURE_TODO: implement QUARTZ-423 + return null; + } + + protected boolean isLeapYear(int year) { + return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)); + } + + protected int getLastDayOfMonth(int monthNum, int year) { + + switch (monthNum) { + case 1: + return 31; + case 2: + return (isLeapYear(year)) ? 29 : 28; + case 3: + return 31; + case 4: + return 30; + case 5: + return 31; + case 6: + return 30; + case 7: + return 31; + case 8: + return 31; + case 9: + return 30; + case 10: + return 31; + case 11: + return 30; + case 12: + return 31; + default: + throw new IllegalArgumentException("Illegal month number: " + + monthNum); + } + } + + + private void readObject(java.io.ObjectInputStream stream) + throws java.io.IOException, ClassNotFoundException { + + stream.defaultReadObject(); + try { + buildExpression(cronExpression); + } catch (Exception ignore) { + } // never happens + } + + @Override + @Deprecated + public Object clone() { + return new CronExpression(this); + } +} + +class ValueSet { + public int value; + + public int pos; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictController.java index 538c4a24..233f96cd 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictController.java @@ -3,6 +3,7 @@ import com.zmops.iot.core.log.BussinessLog; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.param.DictParam; import com.zmops.iot.web.sys.service.DictService; import com.zmops.iot.web.sys.service.DictTypeService; @@ -28,6 +29,7 @@ public class DictController { /** * 新增字典项 */ + @Permission(code = "dict") @RequestMapping("/create") @BussinessLog("新增字典项") public ResponseData addItem(@Validated(BaseEntity.Create.class) @RequestBody DictParam dictParam) { @@ -37,6 +39,7 @@ public ResponseData addItem(@Validated(BaseEntity.Create.class) @RequestBody Dic /** * 编辑字典项 */ + @Permission(code = "dict") @RequestMapping("/update") @BussinessLog("编辑字典项") public ResponseData editItem(@Validated(BaseEntity.Update.class) @RequestBody DictParam dictParam) { @@ -48,6 +51,7 @@ public ResponseData editItem(@Validated(BaseEntity.Update.class) @RequestBody Di * * @author stylefeng */ + @Permission(code = "dict") @RequestMapping("/delete") @BussinessLog("删除字典项") public ResponseData delete(@Validated(BaseEntity.MassRemove.class) @RequestBody DictParam dictParam) { @@ -58,6 +62,7 @@ public ResponseData delete(@Validated(BaseEntity.MassRemove.class) @RequestBody /** * 获取某个字典类型下的所有字典 */ + @Permission(code = "dict") @ResponseBody @RequestMapping("/listDicts") public ResponseData listDicts(@RequestParam("dictTypeId") Long dictTypeId) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictTypeController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictTypeController.java index 99c6c582..e5c6877a 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictTypeController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/DictTypeController.java @@ -4,11 +4,15 @@ import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.param.DictTypeParam; import com.zmops.iot.web.sys.service.DictTypeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; /** @@ -24,6 +28,7 @@ public class DictTypeController { /** * 新增字典 */ + @Permission(code = "dict") @RequestMapping("/create") @BussinessLog("新增字典") public ResponseData addItem(@Validated(BaseEntity.Create.class) @RequestBody DictTypeParam dictTypeParam) { @@ -33,6 +38,7 @@ public ResponseData addItem(@Validated(BaseEntity.Create.class) @RequestBody Dic /** * 编辑字典 */ + @Permission(code = "dict") @RequestMapping("/update") @BussinessLog("编辑字典") public ResponseData editItem(@Validated(BaseEntity.Update.class) @RequestBody DictTypeParam dictTypeParam) { @@ -42,6 +48,7 @@ public ResponseData editItem(@Validated(BaseEntity.Update.class) @RequestBody Di /** * 删除字典 */ + @Permission(code = "dict") @RequestMapping("/delete") @BussinessLog("删除字典") public ResponseData delete(@Validated(BaseEntity.MassRemove.class) @RequestBody DictTypeParam dictTypeParam) { @@ -53,6 +60,7 @@ public ResponseData delete(@Validated(BaseEntity.MassRemove.class) @RequestBody /** * 查询列表 */ + @Permission(code = "dict") @PostMapping("/getDictTypeByPage") public Pager list(@RequestBody DictTypeParam dictTypeParam) { return dictTypeService.findPageBySpec(dictTypeParam); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/KaptchaController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/KaptchaController.java index e691e208..523f106f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/KaptchaController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/KaptchaController.java @@ -55,7 +55,7 @@ public void index(HttpServletRequest request, HttpServletResponse response) { session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText); // create the image with the text - BufferedImage bi = producer.createImage(capText); + BufferedImage bi = producer.createImage(capText); ServletOutputStream out = null; try { out = response.getOutputStream(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java index 78ce093b..71173dab 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LogController.java @@ -1,7 +1,8 @@ package com.zmops.iot.web.sys.controller; -import com.zmops.iot.domain.sys.SysOperationLog; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.web.auth.Permission; +import com.zmops.iot.web.sys.dto.SysOperationLogDto; import com.zmops.iot.web.sys.service.OperationLogService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; @@ -22,14 +23,15 @@ public class LogController { /** * 查询操作日志列表 */ + @Permission(code = "businessLog") @RequestMapping("/getOperationLogByPage") @ResponseBody - public Pager list(@RequestParam(required = false) Long beginTime, - @RequestParam(required = false) Long endTime, - @RequestParam(required = false) String logName, - @RequestParam(required = false) String logType, - @RequestParam(required = false, defaultValue = "1") int page, - @RequestParam(required = false, defaultValue = "20") int maxRow) { + public Pager list(@RequestParam(required = false) Long beginTime, + @RequestParam(required = false) Long endTime, + @RequestParam(required = false) String logName, + @RequestParam(required = false) String logType, + @RequestParam(required = false, defaultValue = "1") int page, + @RequestParam(required = false, defaultValue = "20") int maxRow) { return operationLogService.list(beginTime, endTime, logName, logType, page, maxRow); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java index 9e764618..f3b48ed9 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginController.java @@ -2,6 +2,7 @@ import com.google.code.kaptcha.Constants; import com.zmops.iot.constant.ConstantsContext; +import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.core.web.base.BaseController; import com.zmops.iot.model.exception.InvalidKaptchaException; import com.zmops.iot.model.response.ResponseData; @@ -9,54 +10,95 @@ import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.auth.AuthService; import com.zmops.iot.web.sys.dto.param.LoginParam; +import com.zmops.iot.web.sys.service.SysUserService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; import javax.validation.Valid; +import java.util.Map; /** * @author nantian created at 2021/7/29 19:55 *

* 登陆 */ -@RestController +@Controller public class LoginController extends BaseController { @Autowired private AuthService authService; + @Autowired + private SysUserService userService; + + /** + * 跳转到主页 + */ + @RequestMapping(value = "/", method = RequestMethod.GET) + public String reindex(Model model) { + if (LoginContextHolder.getContext().hasLogin()) { + Map userIndexInfo = userService.getUserIndexInfo(); + + if (userIndexInfo == null) { + return "/login"; + } else { + model.addAllAttributes(userIndexInfo); + return "/index"; + } + } else { + return "/index"; + } + } + + + /** + * 跳转到登录页面 + */ + @RequestMapping(value = "/login", method = RequestMethod.GET) + public String login() { + if (LoginContextHolder.getContext().hasLogin()) { + return REDIRECT + "/"; + } else { + return "/index"; + } + } + /** * 登录返回用户信息 * - * @param vo + * @param loginParam 登陆参数 * @return */ - @PostMapping(value = "/login") - public ResponseData loginVali(@Valid @RequestBody LoginParam vo) { - - String username = vo.getUsername(); - String password = vo.getPassword(); - + @ResponseBody + @RequestMapping(value = "/login", method = RequestMethod.POST) + public ResponseData loginVali(@Valid @RequestBody LoginParam loginParam) { + String username = loginParam.getUsername(); + String password = loginParam.getPassword(); if (ConstantsContext.getKaptchaOpen()) { String kaptcha = super.getPara("kaptcha").trim(); - String code = (String) super.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY); + String code = (String) super.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY); if (ToolUtil.isEmpty(kaptcha) || !kaptcha.equalsIgnoreCase(code)) { throw new InvalidKaptchaException(); } } - //登录并返回登录用户信息 return new SuccessResponseData(authService.login(username, password)); } /** * 退出登录 */ - @RequestMapping(value = "/logout") @ResponseBody + @RequestMapping(value = "/logout") public ResponseData logOut() { authService.logout(); return new SuccessResponseData(); } + } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java index 0301eabd..05673912 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/LoginLogController.java @@ -1,7 +1,8 @@ package com.zmops.iot.web.sys.controller; -import com.zmops.iot.domain.sys.SysLoginLog; import com.zmops.iot.model.page.Pager; +import com.zmops.iot.web.auth.Permission; +import com.zmops.iot.web.sys.dto.SysLoginLogDto; import com.zmops.iot.web.sys.service.LoginLogService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; @@ -22,13 +23,14 @@ public class LoginLogController { /** * 登录日志列表 */ + @Permission(code = "businessLog") @RequestMapping("/getLoginLogByPage") @ResponseBody - public Pager list(@RequestParam(required = false) Long beginTime, - @RequestParam(required = false) Long endTime, - @RequestParam(required = false) String logName, - @RequestParam(required = false, defaultValue = "1") int page, - @RequestParam(required = false, defaultValue = "20") int maxRow) { + public Pager list(@RequestParam(required = false) Long beginTime, + @RequestParam(required = false) Long endTime, + @RequestParam(required = false) String logName, + @RequestParam(required = false, defaultValue = "1") int page, + @RequestParam(required = false, defaultValue = "20") int maxRow) { return loginLogService.list(beginTime, endTime, logName, page, maxRow); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysMenuController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysMenuController.java index aea1ebb6..95c6d3c0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysMenuController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysMenuController.java @@ -33,7 +33,7 @@ public class SysMenuController { */ @RequestMapping("/list") public ResponseData getMenuList() { - LoginUser user = LoginContextHolder.getContext().getUser(); + LoginUser user = LoginContextHolder.getContext().getUser(); List roleList = user.getRoleList(); if (ToolUtil.isEmpty(roleList)) { throw new ServiceException(BizExceptionEnum.USER_NOT_BIND_ROLE); @@ -54,8 +54,8 @@ public ResponseData getMenuList() { " ORDER BY" + " m1.menu_id ASC"; - List menuList = DB.sqlQuery(sql).setParameter("roleIds", roleList).findList(); - Map map = new HashMap<>(2); + List menuList = DB.sqlQuery(sql).setParameter("roleIds", roleList).findList(); + Map map = new HashMap<>(2); map.put("menu", menuList.parallelStream().filter(x -> "Y".equals(x.getString("menu_flag"))).collect(Collectors.toList())); map.put("button", menuList.parallelStream().filter(x -> "N".equals(x.getString("menu_flag"))).map(x -> x.getString("url")).collect(Collectors.toList())); return ResponseData.success(map); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysParamController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysParamController.java index 6bacc4c6..50ac7b2b 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysParamController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysParamController.java @@ -2,6 +2,7 @@ import com.zmops.iot.core.log.BussinessLog; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.SysParamDto; import com.zmops.iot.web.sys.service.SysParamService; import org.springframework.beans.factory.annotation.Autowired; @@ -23,6 +24,7 @@ public class SysParamController { /** * 参数列表 */ + @Permission(code = "sysParam") @GetMapping("/list") public ResponseData list() { return ResponseData.success(sysParamService.list()); @@ -31,6 +33,7 @@ public ResponseData list() { /** * 参数修改 */ + @Permission(code = "sysParam") @PostMapping("/update") @BussinessLog(value = "系统参数修改") public ResponseData update(@Validated @RequestBody SysParamDto sysParamDto) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysRoleController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysRoleController.java index 3bfe6fdf..75bdf134 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysRoleController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysRoleController.java @@ -3,6 +3,7 @@ import com.zmops.iot.core.log.BussinessLog; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.SysRoleDto; import com.zmops.iot.web.sys.dto.param.RoleParam; import com.zmops.iot.web.sys.service.SysRoleService; @@ -38,6 +39,7 @@ public ResponseData list(@RequestParam(value = "name", required = false) String /** * 角色新增 */ + @Permission(code = "role") @RequestMapping("/create") @BussinessLog(value = "角色新增") public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody SysRoleDto sysRoleDto) { @@ -47,6 +49,7 @@ public ResponseData create(@Validated(BaseEntity.Create.class) @RequestBody SysR /** * 角色修改 */ + @Permission(code = "role") @RequestMapping("/update") @BussinessLog(value = "角色修改") public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody SysRoleDto sysRoleDto) { @@ -56,6 +59,7 @@ public ResponseData update(@Validated(BaseEntity.Update.class) @RequestBody SysR /** * 角色删除 */ + @Permission(code = "role") @RequestMapping("/delete") @BussinessLog(value = "角色删除") public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody RoleParam sysRoleParam) { @@ -68,6 +72,7 @@ public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody Role * * @return */ + @Permission(code = "role") @RequestMapping("/bindMenu") @BussinessLog(value = "角色绑定菜单") public ResponseData bindMenu(@Validated @RequestBody RoleParam roleParam) { @@ -78,6 +83,7 @@ public ResponseData bindMenu(@Validated @RequestBody RoleParam roleParam) { /** * 角色已绑定的菜单 */ + @Permission(code = "role") @RequestMapping("/bindedMenu") public ResponseData bindMenu(@RequestParam(value = "roleId") Long roleId) { return ResponseData.success(sysRoleService.bindedMenu(roleId)); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java index ef0ecebb..a3b2d67f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserController.java @@ -1,22 +1,24 @@ package com.zmops.iot.web.sys.controller; -import com.zmops.iot.constant.ConstantsContext; import com.zmops.iot.core.log.BussinessLog; -import com.zmops.iot.core.util.SaltUtil; import com.zmops.iot.domain.BaseEntity; import com.zmops.iot.domain.sys.SysUser; import com.zmops.iot.domain.sys.query.QSysUser; +import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.auth.Permission; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.sys.dto.UserDto; import com.zmops.iot.web.sys.dto.param.UserParam; import com.zmops.iot.web.sys.service.SysUserService; -import io.ebean.DB; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; +import java.util.List; /** * @author nantian created at 2021/8/1 21:56 @@ -31,20 +33,37 @@ public class SysUserController { SysUserService sysUserService; /** - * 用户列表 + * 用户分页列表 * * @return */ + @Permission(code = "mgr") @PostMapping("/getUserByPage") public Pager userList(@RequestBody UserParam userParam) { return sysUserService.userList(userParam); } + /** + * 用户列表 + * + * @return + */ + @Permission(code = "mgr") + @PostMapping("/list") + public ResponseData list(@RequestBody UserParam userParam) { + QSysUser qSysUser = new QSysUser(); + if (ToolUtil.isNotEmpty(userParam.getName())) { + qSysUser.name.contains(userParam.getName()); + } + return ResponseData.success(qSysUser.findList()); + } + /** * 创建用户 * * @return */ + @Permission(code = "mgr") @PostMapping("/create") @BussinessLog(value = "创建用户") public ResponseData createUser(@Validated(BaseEntity.Create.class) @RequestBody UserDto sysUser) { @@ -57,6 +76,7 @@ public ResponseData createUser(@Validated(BaseEntity.Create.class) @RequestBody * * @return */ + @Permission(code = "mgr") @PostMapping("/update") @BussinessLog(value = "更新用户") public ResponseData updateUser(@Validated(value = BaseEntity.Update.class) @RequestBody UserDto userDto) { @@ -68,6 +88,7 @@ public ResponseData updateUser(@Validated(value = BaseEntity.Update.class) @Requ * * @return */ + @Permission(code = "mgr") @PostMapping("/delete") @BussinessLog(value = "删除用户") public ResponseData deleteUser(@Validated(BaseEntity.Delete.class) @RequestBody UserParam user) { @@ -78,6 +99,7 @@ public ResponseData deleteUser(@Validated(BaseEntity.Delete.class) @RequestBody /** * 修改密码 */ + @Permission(code = "mgr") @PostMapping("/changePwd") @BussinessLog(value = "修改密码") public ResponseData changePwd(@Valid @RequestBody UserParam user) { @@ -88,13 +110,14 @@ public ResponseData changePwd(@Valid @RequestBody UserParam user) { /** * 重置管理员的密码 */ + @Permission(code = "mgr") @RequestMapping("/reset") @BussinessLog(value = "重置密码") public ResponseData reset(@RequestParam("userId") Long userId) { - SysUser user = new QSysUser().userId.eq(userId).findOne(); - user.setSalt(SaltUtil.getRandomSalt()); - user.setPassword(SaltUtil.md5Encrypt(ConstantsContext.getDefaultPassword(), user.getSalt())); - DB.update(user); + if (userId == 1) { + throw new ServiceException(BizExceptionEnum.CANT_CHANGE_ADMIN_PWD); + } + sysUserService.reset(userId); return ResponseData.success(); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserGroupController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserGroupController.java index 952937d2..f59f3c5f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserGroupController.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/SysUserGroupController.java @@ -2,9 +2,9 @@ import com.zmops.iot.core.log.BussinessLog; import com.zmops.iot.domain.BaseEntity; -import com.zmops.iot.domain.sys.SysUserGroup; import com.zmops.iot.model.page.Pager; import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; import com.zmops.iot.web.sys.dto.UserGroupDto; import com.zmops.iot.web.sys.dto.param.UserGroupParam; import com.zmops.iot.web.sys.service.SysUserGroupService; @@ -32,8 +32,9 @@ public class SysUserGroupController { * * @return */ + @Permission(code = "usrGrp") @PostMapping("/getUsrGrpByPage") - public Pager getUsrGrpByPage(@RequestBody UserGroupParam userGroupParam) { + public Pager getUsrGrpByPage(@RequestBody UserGroupParam userGroupParam) { return sysUserGroupService.userGroupPageList(userGroupParam); } @@ -42,6 +43,7 @@ public Pager getUsrGrpByPage(@RequestBody UserGroupParam userGroup * * @return */ + @Permission(code = "usrGrp") @PostMapping("/list") public ResponseData userGroupList() { return ResponseData.success(sysUserGroupService.userGroupList()); @@ -52,6 +54,7 @@ public ResponseData userGroupList() { * * @return */ + @Permission(code = "usrGrp") @PostMapping("/create") @BussinessLog(value = "创建用户组") public ResponseData createUserGroup(@Validated @RequestBody UserGroupDto userGroup) { @@ -64,6 +67,7 @@ public ResponseData createUserGroup(@Validated @RequestBody UserGroupDto userGro * * @return */ + @Permission(code = "usrGrp") @PostMapping("/update") @BussinessLog(value = "更新用户组") public ResponseData updateUserGroup(@Validated(BaseEntity.Update.class) @RequestBody UserGroupDto userGroup) { @@ -75,6 +79,7 @@ public ResponseData updateUserGroup(@Validated(BaseEntity.Update.class) @Request * * @return */ + @Permission(code = "usrGrp") @PostMapping("/delete") @BussinessLog(value = "删除用户组") public ResponseData deleteUserGroup(@Validated @RequestBody UserGroupParam userGroup) { @@ -87,6 +92,7 @@ public ResponseData deleteUserGroup(@Validated @RequestBody UserGroupParam userG * * @return */ + @Permission(code = "usrGrp") @PostMapping("/bindHostGrp") @BussinessLog(value = "用户组绑定主机组") public ResponseData bindHostGrp(@Validated(BaseEntity.BindDevice.class) @RequestBody UserGroupParam userGroup) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/TenantController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/TenantController.java new file mode 100644 index 00000000..8381604f --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/controller/TenantController.java @@ -0,0 +1,134 @@ +package com.zmops.iot.web.sys.controller; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.sys.SysUser; +import com.zmops.iot.domain.sys.query.QSysUser; +import com.zmops.iot.domain.tenant.TenantInfo; +import com.zmops.iot.domain.tenant.query.QTenantInfo; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.auth.Permission; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.sys.dto.TenantInfoDto; +import com.zmops.iot.web.sys.dto.param.TenantInfoParam; +import com.zmops.iot.web.sys.service.SysUserService; +import com.zmops.iot.web.sys.service.Tenantervice; +import io.ebean.DB; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * @author yefei + **/ +@RestController +@RequestMapping("/tenant") +public class TenantController { + + @Autowired + Tenantervice tenantervice; + + @Autowired + SysUserService sysUserService; + + /** + * 租户列表 + * + * @return + */ + @Permission(code = "tenant_list") + @PostMapping("/getTenantByPage") + public Pager userList(@RequestBody TenantInfoParam tenantInfoParam) { + return tenantervice.getTenantByPage(tenantInfoParam); + } + + /** + * 创建租户 + * + * @return + */ + @Permission(code = "tenant_add") + @PostMapping("/create") + public ResponseData createTenant(@Validated(BaseEntity.Create.class) @RequestBody TenantInfoParam tenantInfoParam) { + int count = new QTenantInfo().name.eq(tenantInfoParam.getName()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.TENANT_NAME_EXISTS); + } + + count = new QTenantInfo().account.eq(tenantInfoParam.getAccount()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.TENANT_ACCOUNT_EXISTS); + } + + return ResponseData.success(tenantervice.createTenant(tenantInfoParam)); + } + + + /** + * 更新租户 + * + * @return + */ + @Permission(code = "tenant_update") + @PostMapping("/update") + public ResponseData updateTenant(@Validated(value = BaseEntity.Update.class) @RequestBody TenantInfoParam tenantInfoParam) { + int count = new QTenantInfo().name.eq(tenantInfoParam.getName()).tenantId.ne(tenantInfoParam.getTenantId()).findCount(); + if (count > 0) { + throw new ServiceException(BizExceptionEnum.TENANT_NAME_EXISTS); + } + return ResponseData.success(tenantervice.updateTenant(tenantInfoParam)); + } + + /** + * 删除租户 + * + * @return + */ + @Permission(code = "tenant_delete") + @PostMapping("/delete") + public ResponseData deleteTenant(@Validated(BaseEntity.Delete.class) @RequestBody TenantInfoParam tenantInfoParam) { + tenantervice.deleteTenant(tenantInfoParam); + return ResponseData.success(); + } + + /** + * 租户状态修改 + * + * @return + */ + @Permission(code = "tenant_update") + @RequestMapping("/status") + public ResponseData status(@RequestParam("tenantId") Long tenantId, @RequestParam("status") String status) { + tenantervice.status(tenantId,status); + return ResponseData.success(); + } + + /** + * 租户详情 + * + * @return + */ + @Permission(code = "tenant_update") + @RequestMapping("/detail") + public ResponseData detail(@RequestParam Long tenantId) { + TenantInfoDto tenantInfoDto = new QTenantInfo().tenantId.eq(tenantId).asDto(TenantInfoDto.class).findOne(); + return ResponseData.success(tenantInfoDto); + } + + /** + * 重置密码 + * + * @return + */ + @RequestMapping("/reset") + @Permission(code = "reset") + public ResponseData reset(@RequestParam("account") String account) { + SysUser sysUser = new QSysUser().account.eq(account).findOne(); + if (sysUser == null) { + throw new ServiceException(BizExceptionEnum.TENANT_NOT_EXISTS); + } + sysUserService.reset(sysUser.getUserId()); + return ResponseData.success(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/LoginUserDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/LoginUserDto.java index 04ed816b..cd6b5218 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/LoginUserDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/LoginUserDto.java @@ -30,6 +30,8 @@ public class LoginUserDto { private String account; + private Long tenantId; + private String name; private String token; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java new file mode 100644 index 00000000..5f885c19 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictDto.java @@ -0,0 +1,64 @@ +package com.zmops.iot.web.sys.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 基础字典 + *

+ */ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class SysDictDto { + + /** + * 字典id + */ + private Long dictId; + + /** + * 所属字典类型的id + */ + private Long dictTypeId; + + /** + * 字典编码 + */ + private String code; + + /** + * 字典名称 + */ + private String name; + + /** + * 状态 + */ + @CachedValue(value = "STATUS", fieldName = "statusName") + private String status; + + /** + * 排序 + */ + private Integer sort; + + /** + * 字典的描述 + */ + private String remark; + + private String groups; + + LocalDateTime createTime; + + LocalDateTime updateTime; + + Long createUser; + + Long updateUser; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java new file mode 100644 index 00000000..dac2615e --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysDictTypeDto.java @@ -0,0 +1,63 @@ +package com.zmops.iot.web.sys.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + *

+ * 字典类型表 + *

+ */ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class SysDictTypeDto { + + /** + * 字典类型id + */ + private Long dictTypeId; + + /** + * 字典类型编码 + */ + private String code; + + /** + * 字典类型名称 + */ + private String name; + + /** + * 字典描述 + */ + private String remark; + + /** + * 是否是系统字典,Y-是,N-否 + */ + private String systemFlag = "N"; + + /** + * 状态 + */ + @CachedValue(value = "STATUS", fieldName = "statusName") + private String status; + + /** + * 排序 + */ + private Integer sort; + + LocalDateTime createTime; + + LocalDateTime updateTime; + + Long createUser; + + Long updateUser; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java new file mode 100644 index 00000000..1172cdc3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysLoginLogDto.java @@ -0,0 +1,35 @@ +package com.zmops.iot.web.sys.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import java.time.LocalDateTime; + + +/** + * @author nantian created at 2021/7/31 18:20 + */ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class SysLoginLogDto { + + long loginLogId; + + String logName; + + @CachedValue(type = DicType.SysUserName, fieldName = "userName") + Long userId; + + LocalDateTime createTime; + + String succeed; + + String message; + + String ipAddress; + + private Long tenantId; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java new file mode 100644 index 00000000..10781706 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/SysOperationLogDto.java @@ -0,0 +1,39 @@ +package com.zmops.iot.web.sys.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author nantian created at 2021/8/1 22:04 + */ + +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class SysOperationLogDto { + + private Long operationLogId; + + private String logType; + + private String logName; + + @CachedValue(type = DicType.SysUserName, fieldName = "userName") + private Long userId; + + private String className; + + private String method; + + private String succeed; + + private String message; + + private LocalDateTime createTime; + + private Long tenantId; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/TenantInfoDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/TenantInfoDto.java new file mode 100644 index 00000000..aceb9a5c --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/TenantInfoDto.java @@ -0,0 +1,65 @@ +package com.zmops.iot.web.sys.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * @author yefei + */ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class TenantInfoDto implements Serializable { + + + /** + * 主键id + */ + private Long tenantId; + + /** + * 租户名称 + */ + private String name; + + /** + * 备注 + */ + private String remark; + + /** + * 租户管理员账号 + */ + private String account; + + + /** + * 租户联系人 + */ + private String contact; + + /** + * 租户联系人电话 + */ + private String phone; + + private int userNum; + + LocalDateTime createTime; + + LocalDateTime updateTime; + + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + Long createUser; + + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + Long updateUser; + + @CachedValue(value = "STATUS", fieldName = "statusName") + private String status; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java index 7da64383..c5e6feee 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserDto.java @@ -15,7 +15,11 @@ */ package com.zmops.iot.web.sys.dto; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; import lombok.Data; import javax.validation.constraints.NotBlank; @@ -27,15 +31,16 @@ * @author stylefeng */ @Data +@JsonSerialize(using = CachedValueFilter.class) public class UserDto { @NotNull(groups = BaseEntity.Update.class) private Long userId; - @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + @NotBlank(groups = {BaseEntity.Create.class}) private String account; - @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) + @NotBlank(groups = {BaseEntity.Create.class}) private String password; @NotBlank(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) @@ -48,15 +53,21 @@ public class UserDto { @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private Long userGroupId; + @CachedValue(value = "STATUS", fieldName = "statusName") private String status; @NotNull(groups = {BaseEntity.Create.class, BaseEntity.Update.class}) private Long roleId; + @CachedValue(type = DicType.Tenant, fieldName = "tenantName") + private Long tenantId; private String roleName; private String userGroupName; - private String createUser; + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + private Long createUser; private String createTime; - private String updateUser; + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + private Long updateUser; private String updateTime; + private String remark; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java index 091b7c10..5bae54fa 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/UserGroupDto.java @@ -15,11 +15,17 @@ */ package com.zmops.iot.web.sys.dto; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.util.List; /** * 用户组传输bean @@ -27,6 +33,7 @@ * @author yefei */ @Data +@JsonSerialize(using = CachedValueFilter.class) public class UserGroupDto { @NotNull(groups = BaseEntity.Update.class) @@ -35,8 +42,26 @@ public class UserGroupDto { @NotBlank private String groupName; + @CachedValue(value = "STATUS", fieldName = "statusName") private String status; private String remark; + private List deviceGroupIds; + + //列表返回的设备组ID + private String groupIds; + + LocalDateTime createTime; + + LocalDateTime updateTime; + + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + Long createUser; + + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + Long updateUser; + + @CachedValue(type = DicType.Tenant, fieldName = "tenantName") + private Long tenantId; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/BaseQueryParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/BaseQueryParam.java index 2aa50804..4f614a21 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/BaseQueryParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/BaseQueryParam.java @@ -7,6 +7,6 @@ **/ @Data public class BaseQueryParam { - private int page = 1; + private int page = 1; private int maxRow = 10; } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/TenantInfoParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/TenantInfoParam.java new file mode 100644 index 00000000..abf39de3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/TenantInfoParam.java @@ -0,0 +1,59 @@ +package com.zmops.iot.web.sys.dto.param; + +import com.zmops.iot.domain.BaseEntity; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; + + +/** + * @author yefei + */ +@Data +public class TenantInfoParam extends BaseQueryParam { + + /** + * 主键id + */ + @NotNull(groups = {BaseEntity.Update.class, BaseEntity.Delete.class}) + private Long tenantId; + + /** + * 租户名称 + */ + @NotBlank(groups = {BaseEntity.Update.class, BaseEntity.Create.class}) + private String name; + + private String status; + /** + * 备注 + */ + private String remark; + + /** + * 租户管理员账号 + */ + @NotBlank(groups = BaseEntity.Create.class) + private String account; + + /** + * 租户管理员账号密码 + */ + @NotBlank(groups = BaseEntity.Create.class) + private String password; + + /** + * 租户联系人 + */ + private String contact; + + /** + * 租户联系人电话 + */ + @Pattern(regexp = "^[1][3,4,5,7,8][0-9]{9}$",message = "电话号码格式不正确") + private String phone; + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/UserGroupParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/UserGroupParam.java index 54063ff7..376b9d55 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/UserGroupParam.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/dto/param/UserGroupParam.java @@ -16,7 +16,10 @@ package com.zmops.iot.web.sys.dto.param; import com.zmops.iot.domain.BaseEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; +import lombok.NoArgsConstructor; import javax.validation.constraints.NotNull; import java.util.List; @@ -27,6 +30,9 @@ * @author yefei */ @Data +@Builder +@NoArgsConstructor +@AllArgsConstructor public class UserGroupParam extends BaseQueryParam { private String groupName; diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java index 264c40fd..9498863f 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/factory/UserFactory.java @@ -74,6 +74,12 @@ public static SysUser editUser(UserDto newUser, SysUser oldUser) { if (ToolUtil.isNotEmpty(newUser.getPhone())) { oldUser.setPhone(newUser.getPhone()); } + if (ToolUtil.isNotEmpty(newUser.getStatus())) { + oldUser.setStatus(newUser.getStatus()); + } + if (ToolUtil.isNotEmpty(newUser.getRemark())) { + oldUser.setRemark(newUser.getRemark()); + } return oldUser; } } @@ -104,6 +110,8 @@ public static LoginUser createLoginUser(SysUser user) { loginUser.setId(user.getUserId()); loginUser.setAccount(user.getAccount()); + loginUser.setUserGroupId(user.getUserGroupId()); + loginUser.setTenantId(user.getTenantId()); // loginUser.setDeptId(user.getDeptId()); // loginUser.setDeptName(ConstantFactory.me().getDeptName(user.getDeptId())); loginUser.setName(user.getName()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java index 435c39f5..a16e8fa0 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictService.java @@ -11,6 +11,7 @@ import com.zmops.iot.util.DefinitionsUtil; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.sys.dto.SysDictDto; import com.zmops.iot.web.sys.dto.param.DictParam; import io.ebean.DB; import org.springframework.beans.factory.annotation.Autowired; @@ -112,14 +113,14 @@ public SysDict update(DictParam param) { /** * 查询字典列表,通过字典ID */ - public List listDicts(Long dictTypeId) { - return new QSysDict().dictTypeId.eq(dictTypeId).orderBy(" sort desc").findList(); + public List listDicts(Long dictTypeId) { + return new QSysDict().dictTypeId.eq(dictTypeId).orderBy(" sort desc").asDto(SysDictDto.class).findList(); } /** * 查询字典列表,通过字典编码 */ - public List listDicts(String dictTypeCode) { + public List listDicts(String dictTypeCode) { Long dictTypeId = new QSysDictType().select(QSysDictType.alias().dictTypeId).code.eq(dictTypeCode).findSingleAttribute(); return listDicts(dictTypeId); } @@ -127,20 +128,20 @@ public List listDicts(String dictTypeCode) { /** * 分组查询字典列表,通过字典编码 */ - public Map> groupDictByCode(String dictTypeCode) { - Long dictTypeId = new QSysDictType().select(QSysDictType.alias().dictTypeId).code.eq(dictTypeCode).findSingleAttribute(); - List sysDicts = listDicts(dictTypeId); + public Map> groupDictByCode(String dictTypeCode) { + Long dictTypeId = new QSysDictType().select(QSysDictType.alias().dictTypeId).code.eq(dictTypeCode).findSingleAttribute(); + List sysDicts = listDicts(dictTypeId); if (ToolUtil.isEmpty(sysDicts)) { return new HashMap<>(); } - return sysDicts.parallelStream().collect(Collectors.groupingBy(SysDict::getGroups)); + return sysDicts.parallelStream().collect(Collectors.groupingBy(SysDictDto::getGroups)); } private void updateDictionaries() { - List dictTypes = new QSysDictType().findList(); - Map map = dictTypes.parallelStream().collect(Collectors.toMap(SysDictType::getDictTypeId, SysDictType::getCode)); - List collect = dictTypes.stream().map(SysDictType::getDictTypeId).collect(Collectors.toList()); - List dictList = new QSysDict().dictTypeId.in(collect).findList(); + List dictTypes = new QSysDictType().findList(); + Map map = dictTypes.parallelStream().collect(Collectors.toMap(SysDictType::getDictTypeId, SysDictType::getCode, (a, b) -> a)); + List collect = dictTypes.stream().map(SysDictType::getDictTypeId).collect(Collectors.toList()); + List dictList = new QSysDict().dictTypeId.in(collect).findList(); Table dictionaryValues = HashBasedTable.create(); for (SysDict dict : dictList) { dictionaryValues.put(map.get(dict.getDictTypeId()), dict.getCode(), dict.getName()); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictTypeService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictTypeService.java index 500f4601..db4b237d 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictTypeService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/DictTypeService.java @@ -8,13 +8,15 @@ import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.ToolUtil; import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.sys.dto.SysDictTypeDto; import com.zmops.iot.web.sys.dto.param.DictTypeParam; import io.ebean.DB; -import io.ebean.PagedList; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + /** *

* 字典类型表 服务实现类 @@ -95,8 +97,8 @@ public Pager findPageBySpec(DictTypeParam param) { } qSysDictType.orderBy("create_time desc"); qSysDictType.setFirstRow((param.getPage() - 1) * param.getMaxRow()).setMaxRows(param.getMaxRow()); - PagedList pagedList = qSysDictType.findPagedList(); - return new Pager<>(pagedList.getList(), pagedList.getTotalCount()); + List pagedList = qSysDictType.asDto(SysDictTypeDto.class).findList(); + return new Pager<>(pagedList, qSysDictType.findCount()); } private SysDictType getEntity(DictTypeParam param) { diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/LoginLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/LoginLogService.java index eb5de5ab..63816cab 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/LoginLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/LoginLogService.java @@ -1,20 +1,22 @@ package com.zmops.iot.web.sys.service; -import com.zmops.iot.domain.sys.SysLoginLog; +import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.domain.sys.query.QSysLoginLog; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; -import io.ebean.PagedList; +import com.zmops.iot.web.sys.dto.SysLoginLogDto; import org.springframework.stereotype.Service; +import java.util.List; + /** * @author yefei **/ @Service public class LoginLogService { - public Pager list(Long beginTime, Long endTime, String logName, int page, int maxRow) { + public Pager list(Long beginTime, Long endTime, String logName, int page, int maxRow) { QSysLoginLog qSysLoginLog = new QSysLoginLog(); if (ToolUtil.isNotEmpty(beginTime)) { qSysLoginLog.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(beginTime)); @@ -25,8 +27,12 @@ public Pager list(Long beginTime, Long endTime, String logName, int if (ToolUtil.isNotEmpty(logName)) { qSysLoginLog.logName.eq(logName); } + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + qSysLoginLog.tenantId.eq(tenantId); + } qSysLoginLog.setFirstRow((page - 1) * maxRow).setMaxRows(maxRow); - PagedList pagedList = qSysLoginLog.orderBy("create_time desc").findPagedList(); - return new Pager<>(pagedList.getList(), pagedList.getTotalCount()); + List pagedList = qSysLoginLog.orderBy("create_time desc").asDto(SysLoginLogDto.class).findList(); + return new Pager<>(pagedList, qSysLoginLog.findCount()); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/OperationLogService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/OperationLogService.java index 1b931d81..e67bb420 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/OperationLogService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/OperationLogService.java @@ -1,20 +1,22 @@ package com.zmops.iot.web.sys.service; -import com.zmops.iot.domain.sys.SysOperationLog; +import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.domain.sys.query.QSysOperationLog; import com.zmops.iot.model.page.Pager; import com.zmops.iot.util.LocalDateTimeUtils; import com.zmops.iot.util.ToolUtil; -import io.ebean.PagedList; +import com.zmops.iot.web.sys.dto.SysOperationLogDto; import org.springframework.stereotype.Service; +import java.util.List; + /** * @author yefei **/ @Service public class OperationLogService { - public Pager list(Long beginTime, Long endTime, String logName, String logType, int page, int maxRow) { + public Pager list(Long beginTime, Long endTime, String logName, String logType, int page, int maxRow) { QSysOperationLog qSysOperationLog = new QSysOperationLog(); if (ToolUtil.isNotEmpty(beginTime)) { qSysOperationLog.createTime.ge(LocalDateTimeUtils.getLDTByMilliSeconds(beginTime)); @@ -23,13 +25,17 @@ public Pager list(Long beginTime, Long endTime, String logName, qSysOperationLog.createTime.le(LocalDateTimeUtils.getLDTByMilliSeconds(endTime)); } if (ToolUtil.isNotEmpty(logName)) { - qSysOperationLog.logName.eq(logName); + qSysOperationLog.logName.contains(logName); } if (ToolUtil.isNotEmpty(logType)) { qSysOperationLog.logType.eq(logType); } + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + qSysOperationLog.tenantId.eq(tenantId); + } qSysOperationLog.setFirstRow((page - 1) * maxRow).setMaxRows(maxRow); - PagedList pagedList = qSysOperationLog.orderBy("create_time desc").findPagedList(); - return new Pager<>(pagedList.getList(), pagedList.getTotalCount()); + List pagedList = qSysOperationLog.orderBy("create_time desc").asDto(SysOperationLogDto.class).findList(); + return new Pager<>(pagedList, qSysOperationLog.findCount()); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java index 535847cd..2412afdb 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysParamService.java @@ -2,8 +2,11 @@ import com.zmops.iot.domain.sys.SysConfig; import com.zmops.iot.domain.sys.query.QSysConfig; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.web.init.SysConfigInit; import com.zmops.iot.web.sys.dto.SysParamDto; import io.ebean.DB; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @@ -16,13 +19,16 @@ @Service public class SysParamService { + @Autowired + SysConfigInit sysConfigInit; + public List list() { - return new QSysConfig().orderBy().id.desc().findList(); + return new QSysConfig().status.eq(CommonStatus.ENABLE.getCode()).orderBy().id.desc().findList(); } public void update(SysParamDto sysParamDto) { - Map sysParamMap = sysParamDto.getSysParamList().parallelStream().collect(Collectors.toMap(SysParamDto.SysParam::getId, o -> o)); - List sysParamList = list(); + Map sysParamMap = sysParamDto.getSysParamList().parallelStream().collect(Collectors.toMap(SysParamDto.SysParam::getId, o -> o)); + List sysParamList = list(); for (SysConfig sysConfig : sysParamList) { SysParamDto.SysParam sysParam = sysParamMap.get(sysConfig.getId()); sysConfig.setName(sysParam.getName()); @@ -30,5 +36,7 @@ public void update(SysParamDto sysParamDto) { sysConfig.setRemark(sysParam.getRemark()); } DB.saveAll(sysParamList); + + sysConfigInit.initConfigConst(); } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java index f0427aa9..140eeff3 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysRoleService.java @@ -6,6 +6,7 @@ import com.zmops.iot.core.tree.DefaultTreeBuildFactory; import com.zmops.iot.domain.sys.SysRole; import com.zmops.iot.domain.sys.SysRoleMenu; +import com.zmops.iot.domain.sys.query.QSysMenu; import com.zmops.iot.domain.sys.query.QSysRole; import com.zmops.iot.domain.sys.query.QSysRoleMenu; import com.zmops.iot.domain.sys.query.QSysUser; @@ -40,7 +41,7 @@ public List list(String name) { if (ToolUtil.isNotEmpty(name)) { qSysRole.name.contains(name); } - return qSysRole.orderBy("create_time desc").findList(); + return qSysRole.roleId.ne(1L).orderBy("create_time desc").findList(); } /** @@ -83,8 +84,8 @@ public void delete(RoleParam sysRoleParam) { if (count > 0) { throw new ServiceException(BizExceptionEnum.ROLE_HAS_BIND_USER); } - new QSysRoleMenu().roleId.in(sysRoleParam.getRoleIds()).delete(); - new QSysRole().roleId.in(sysRoleParam.getRoleIds()).delete(); + new QSysRoleMenu().roleId.in(sysRoleParam.getRoleIds()).roleId.ne(1L).delete(); + new QSysRole().roleId.in(sysRoleParam.getRoleIds()).roleId.ne(1L).delete(); } /** @@ -94,6 +95,7 @@ public void delete(RoleParam sysRoleParam) { */ @Transactional(rollbackFor = Exception.class) public void bindMenu(RoleParam roleParam) { + checkRoleId(roleParam.getRoleId()); checkMenuId(roleParam.getMenuIds()); new QSysRoleMenu().roleId.eq(roleParam.getRoleId()).delete(); List sysRoleMenuList = new ArrayList<>(); @@ -106,15 +108,27 @@ public void bindMenu(RoleParam roleParam) { DB.saveAll(sysRoleMenuList); } + private void checkRoleId(Long roleId) { + LoginUser user = LoginContextHolder.getContext().getUser(); + if (null == user) { + return; + } + if (user.getRoleList().contains(roleId)) { + throw new ServiceException(BizExceptionEnum.CANNOT_MODIFY_OWNER_MENUS); + } + } + /** * 检查授权的菜单 是否存在或是否有权授权此菜单 */ private void checkMenuId(List menuIds) { List paramMuenuIds = new ArrayList<>(menuIds); - LoginUser user = LoginContextHolder.getContext().getUser(); + LoginUser user = LoginContextHolder.getContext().getUser(); if (null == user) { throw new ServiceException(AuthExceptionEnum.NOT_LOGIN_ERROR); } + List adminMenuIds = new QSysMenu().select(QSysMenu.alias().menuId).adminFlag.eq("Y").findSingleAttributeList(); + menuIds.removeAll(adminMenuIds); List lists = new QSysRoleMenu().select(QSysRoleMenu.Alias.menuId).menuId.in(menuIds).roleId.in(user.getRoleList()).findSingleAttributeList(); paramMuenuIds.removeAll(lists); if (ToolUtil.isNotEmpty(paramMuenuIds)) { @@ -156,11 +170,12 @@ public List bindedMenu(Long roleId) { " LEFT JOIN sys_menu m2 ON m1.pcode = m2.CODE " + " WHERE" + " m1.status = 'ENABLE' " + -// " AND " + -// " m1.menu_id in (select menu_id from sys_role_menu where role_id in (:roleIds) )" + + " AND m1.admin_flag = 'N' " + + " AND " + + " m1.menu_id in (select menu_id from sys_role_menu where role_id in (:roleIds))" + " ORDER BY" + " m1.sort ASC"; - List allMenuList = DB.findDto(TreeNode.class, sql).findList(); + List allMenuList = DB.findDto(TreeNode.class, sql).setParameter("roleIds", user.getRoleList()).findList(); //取被授权用户 已授权的菜单 List selectMenuIdList = new QSysRoleMenu().select(QSysRoleMenu.Alias.menuId).roleId.eq(roleId).findSingleAttributeList(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java index 3cd71f58..ce296c41 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserGroupService.java @@ -3,6 +3,7 @@ import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.domain.device.DeviceGroup; import com.zmops.iot.domain.device.SysUserGrpDevGrp; import com.zmops.iot.domain.device.query.QDeviceGroup; @@ -17,12 +18,14 @@ import com.zmops.iot.web.exception.enums.BizExceptionEnum; import com.zmops.iot.web.sys.dto.UserGroupDto; import com.zmops.iot.web.sys.dto.param.UserGroupParam; +import com.zmops.zeus.driver.entity.ZbxUserGrpInfo; import com.zmops.zeus.driver.service.ZbxUserGroup; import io.ebean.DB; -import io.ebean.PagedList; +import io.ebean.DtoQuery; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; @@ -44,15 +47,37 @@ public class SysUserGroupService { * @param userGroupParam * @return */ - public Pager userGroupPageList(UserGroupParam userGroupParam) { - + public Pager userGroupPageList(UserGroupParam userGroupParam) { QSysUserGroup qSysUserGroup = new QSysUserGroup(); + StringBuilder sql = new StringBuilder("SELECT " + + " sug.group_name, sug.remark, sug.create_time, sug.create_user, sug.update_time, sug.update_user, sug.status, sug.user_group_id, sug.tenant_id," + + " dg.groupIds " + + "FROM " + + " sys_user_group sug " + + " LEFT JOIN ( SELECT user_group_id, array_to_string( ARRAY_AGG ( device_group_id ), ',' ) groupIds FROM sys_usrgrp_devicegrp GROUP BY user_group_id ) dg " + + " ON dg.user_group_id = sug.user_group_id"); + sql.append(" where 1=1 "); + if (ToolUtil.isNotEmpty(userGroupParam.getGroupName())) { + sql.append(" and sug.group_name like :groupName"); + } + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + sql.append(" and sug.tenant_id = :tenantId"); + } + sql.append(" order by sug.create_time desc "); + + DtoQuery dto = DB.findDto(UserGroupDto.class, sql.toString()); if (ToolUtil.isNotEmpty(userGroupParam.getGroupName())) { + dto.setParameter("groupName", "%" + userGroupParam.getGroupName() + "%"); qSysUserGroup.groupName.contains(userGroupParam.getGroupName()); } - qSysUserGroup.setFirstRow((userGroupParam.getPage() - 1) * userGroupParam.getMaxRow()).setMaxRows(userGroupParam.getMaxRow()); - PagedList pagedList = qSysUserGroup.orderBy("create_time desc").findPagedList(); - return new Pager<>(pagedList.getList(), pagedList.getTotalCount()); + if (null != tenantId) { + dto.setParameter("tenantId", tenantId); + qSysUserGroup.tenantId.eq(tenantId); + } + List list = dto.setFirstRow((userGroupParam.getPage() - 1) * userGroupParam.getMaxRow()) + .setMaxRows(userGroupParam.getMaxRow()).findList(); + return new Pager<>(list, qSysUserGroup.findCount()); } /** @@ -65,16 +90,22 @@ public List userGroupList() { // if (ToolUtil.isNotEmpty(userGroupParam.getGroupName())) { // qSysUserGroup.groupName.contains(userGroupParam.getGroupName()); // } + QSysUserGroup qSysUserGroup = new QSysUserGroup(); - return new QSysUserGroup().findList(); + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (null != tenantId) { + qSysUserGroup.tenantId.eq(tenantId); + } + return qSysUserGroup.findList(); } /** * 添加用戶組 */ + @Transactional(rollbackFor = Exception.class) public SysUserGroup createUserGroup(UserGroupDto userGroup) { // 判断用户组是否重复 - checkByGroupName(userGroup.getGroupName(), -1L); + checkByGroupName(userGroup.getGroupName(), -1L, userGroup.getTenantId()); long usrGrpId = IdUtil.getSnowflake().nextId(); SysUserGroup newUserGroup = new SysUserGroup(); @@ -82,11 +113,15 @@ public SysUserGroup createUserGroup(UserGroupDto userGroup) { newUserGroup.setUserGroupId(usrGrpId); newUserGroup.setStatus(CommonStatus.ENABLE.getCode()); //回填 ZBX用户组ID - JSONObject result = JSONObject.parseObject(zbxUserGroup.userGrpAdd(String.valueOf(usrGrpId))); - JSONArray userGrpids = result.getJSONArray("usrgrpids"); + JSONObject result = JSONObject.parseObject(zbxUserGroup.userGrpAdd(String.valueOf(usrGrpId))); + JSONArray userGrpids = result.getJSONArray("usrgrpids"); newUserGroup.setZbxId(userGrpids.get(0).toString()); DB.save(newUserGroup); + if (ToolUtil.isNotEmpty(userGroup.getDeviceGroupIds())) { + bindHostGrp(UserGroupParam.builder().userGroupId(usrGrpId).deviceGroupIds(userGroup.getDeviceGroupIds()).build()); + } + return newUserGroup; } @@ -98,11 +133,14 @@ public SysUserGroup createUserGroup(UserGroupDto userGroup) { */ public SysUserGroup updateUserGroup(UserGroupDto userGroup) { // 判断用户组是否重复 - checkByGroupName(userGroup.getGroupName(), userGroup.getUserGroupId()); + checkByGroupName(userGroup.getGroupName(), userGroup.getUserGroupId(), userGroup.getTenantId()); SysUserGroup newUserGroup = new SysUserGroup(); BeanUtils.copyProperties(userGroup, newUserGroup); DB.update(newUserGroup); + + bindHostGrp(UserGroupParam.builder().userGroupId(userGroup.getUserGroupId()).deviceGroupIds(userGroup.getDeviceGroupIds()).build()); + return newUserGroup; } @@ -112,12 +150,12 @@ public SysUserGroup updateUserGroup(UserGroupDto userGroup) { * * @param groupName */ - private void checkByGroupName(String groupName, Long userGroupId) { + private void checkByGroupName(String groupName, Long userGroupId, Long tenantId) { int count; if (userGroupId > 0) { - count = new QSysUserGroup().groupName.equalTo(groupName).userGroupId.ne(userGroupId).findCount(); + count = new QSysUserGroup().groupName.eq(groupName).tenantId.eq(tenantId).userGroupId.ne(userGroupId).findCount(); } else { - count = new QSysUserGroup().groupName.equalTo(groupName).findCount(); + count = new QSysUserGroup().groupName.eq(groupName).tenantId.eq(tenantId).findCount(); } if (count > 0) { throw new ServiceException(BizExceptionEnum.USERGROUP_HAS_EXIST); @@ -141,8 +179,14 @@ public void deleteUserGroup(UserGroupParam userGroupParam) { } List zbxUsrGrpIds = list.parallelStream().map(SysUserGroup::getZbxId).collect(Collectors.toList()); - zbxUserGroup.userGrpDelete(zbxUsrGrpIds); + //删除 zbx 用户组数据 + if (ToolUtil.isNotEmpty(zbxUsrGrpIds)) { + List zbxUserGrpList = JSONObject.parseArray(zbxUserGroup.getUserGrp(zbxUsrGrpIds.toString()), ZbxUserGrpInfo.class); + if (ToolUtil.isNotEmpty(zbxUserGrpList)) { + zbxUserGroup.userGrpDelete(zbxUserGrpList.parallelStream().map(ZbxUserGrpInfo::getUsrgrpid).collect(Collectors.toList())); + } + } // 删除 与设备组关联 new QSysUserGrpDevGrp().userGroupId.in(userGroupParam.getUserGroupIds()).delete(); new QSysUserGroup().userGroupId.in(userGroupParam.getUserGroupIds()).delete(); @@ -165,11 +209,12 @@ public String getZabUsrGrpId(Long usrGrpId) { * @param userGroup */ public void bindHostGrp(UserGroupParam userGroup) { - //修改ZBX 用户组绑定主机组 - String usrGrpZbxId = getZabUsrGrpId(userGroup.getUserGroupId()); - List list = new QDeviceGroup().deviceGroupId.in(userGroup.getDeviceGroupIds()).findList(); - List hostGrpZbxIds = list.parallelStream().map(DeviceGroup::getZbxId).collect(Collectors.toList()); - zbxUserGroup.userGrpBindHostGroup(hostGrpZbxIds, usrGrpZbxId); + new QSysUserGrpDevGrp().userGroupId.eq(userGroup.getUserGroupId()).delete(); + + if (ToolUtil.isEmpty(userGroup.getDeviceGroupIds())) { + return; + } + List lists = new ArrayList<>(); for (Long deviceGroupId : userGroup.getDeviceGroupIds()) { SysUserGrpDevGrp devicesGroups = new SysUserGrpDevGrp(); diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java index 6f07ba08..fbf12a20 100644 --- a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/SysUserService.java @@ -2,12 +2,13 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.constant.ConstantsContext; import com.zmops.iot.core.auth.context.LoginContextHolder; import com.zmops.iot.core.auth.exception.enums.AuthExceptionEnum; import com.zmops.iot.core.auth.model.LoginUser; -import com.zmops.iot.core.util.RsaUtil; import com.zmops.iot.core.util.SaltUtil; import com.zmops.iot.domain.sys.SysUser; +import com.zmops.iot.domain.sys.query.QSysRole; import com.zmops.iot.domain.sys.query.QSysUser; import com.zmops.iot.model.exception.ServiceException; import com.zmops.iot.model.page.Pager; @@ -17,18 +18,24 @@ import com.zmops.iot.web.sys.dto.UserDto; import com.zmops.iot.web.sys.dto.param.UserParam; import com.zmops.iot.web.sys.factory.UserFactory; +import com.zmops.zeus.driver.entity.ZbxUserInfo; import com.zmops.zeus.driver.service.ZbxUser; import io.ebean.DB; import io.ebean.DtoQuery; +import org.apache.commons.codec.binary.Hex; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; +import static com.zmops.iot.web.init.DeviceSatusScriptInit.GLOBAL_ADMIN_ROLE_CODE; + /** * @author yefei *

@@ -44,6 +51,23 @@ public class SysUserService implements CommandLineRunner { @Autowired private SysUserGroupService sysUserGroupService; + + public Map getUserIndexInfo() { + + //获取当前用户角色列表 + LoginUser user = LoginContextHolder.getContext().getUser(); + List roleList = user.getRoleList(); + + //用户没有角色无法显示首页信息 + if (roleList == null || roleList.size() == 0) { + return null; + } + + HashMap result = new HashMap<>(); + result.put("name", user.getName()); + return result; + } + /** * 用户列表 * @@ -52,24 +76,38 @@ public class SysUserService implements CommandLineRunner { */ public Pager userList(UserParam userParam) { QSysUser qSysUser = new QSysUser(); - StringBuilder sql = new StringBuilder("select u.account, u.name, u.email, u.phone, u.role_id,r.name role_name," + - "u.user_group_id,g.group_name user_group_name, u.status, u.create_user, u.update_user, u.create_time, u.update_time, u.user_id FROM sys_user u"); + StringBuilder sql = new StringBuilder( + "select u.account, u.name, u.email, u.phone, u.role_id,r.name role_name," + + "u.user_group_id,g.group_name user_group_name, u.status, u.create_user, " + + "u.update_user, u.create_time, u.update_time, u.user_id,u.tenant_id,u.remark FROM sys_user u"); + sql.append(" LEFT JOIN sys_role r ON r.role_id = u.role_id "); sql.append(" LEFT JOIN sys_user_group g ON g.user_group_id = u.user_group_id "); - + sql.append(" where 1=1 "); if (ToolUtil.isNotEmpty(userParam.getName())) { - sql.append(" where u.name like ?"); + sql.append(" and u.name like :name"); qSysUser.name.contains(userParam.getName()); } + Long tenantId = LoginContextHolder.getContext().getUser().getTenantId(); + if (tenantId != null) { + sql.append(" and u.tenant_id = :tenantId"); + qSysUser.tenantId.eq(tenantId); + } + sql.append(" order by u.create_time desc "); DtoQuery dto = DB.findDto(UserDto.class, sql.toString()); if (ToolUtil.isNotEmpty(userParam.getName())) { - dto.setParameter("%" + userParam.getName() + "%"); + dto.setParameter("name", "%" + userParam.getName() + "%"); + } + if (tenantId != null) { + dto.setParameter("tenantId", tenantId); } List pagedList = dto.setFirstRow((userParam.getPage() - 1) * userParam.getMaxRow()).setMaxRows(userParam.getMaxRow()).findList(); - int count = qSysUser.findCount(); + + int count = qSysUser.findCount(); + return new Pager<>(pagedList, count); } @@ -80,12 +118,14 @@ public Pager userList(UserParam userParam) { public SysUser createUser(UserDto user) { // 判断账号是否重复 checkByAccount(user.getAccount()); + //判断角色是否存在 + checkByRole(user.getRoleId()); // 完善账号信息 - String password = user.getPassword(); + String password = user.getPassword(); String decryptPwd = ""; try { - password = RsaUtil.decryptPwd(password); + password = new String(Hex.decodeHex(password)); decryptPwd = password; } catch (Exception e) { throw new ServiceException(BizExceptionEnum.PWD_DECRYPT_ERR); @@ -95,13 +135,18 @@ public SysUser createUser(UserDto user) { password = SaltUtil.md5Encrypt(password, salt); SysUser newUser = UserFactory.createUser(user, password, salt); + //取对应的ZBX用户组ID - String usrZbxId = sysUserGroupService.getZabUsrGrpId(user.getUserGroupId()); - JSONObject result = JSONObject.parseObject(zbxUser.userAdd(user.getAccount(), decryptPwd, usrZbxId)); - JSONArray userids = result.getJSONArray("userids"); + String usrZbxId = sysUserGroupService.getZabUsrGrpId(user.getUserGroupId()); + JSONObject result = JSONObject.parseObject( + zbxUser.userAdd(user.getAccount(), decryptPwd, usrZbxId, ConstantsContext.getConstntsMap().get(GLOBAL_ADMIN_ROLE_CODE).toString())); + + JSONArray userids = result.getJSONArray("userids"); newUser.setZbxId(String.valueOf(userids.get(0))); + DB.save(newUser); updateUserCache(); + return newUser; } @@ -117,11 +162,19 @@ public SysUser updateUser(UserDto user) { if (null == oldUser) { throw new ServiceException(BizExceptionEnum.USER_NOT_EXIST); } - SysUser sysUser = UserFactory.editUser(user, oldUser); - //取对应的ZBX用户组ID - String usrZbxId = sysUserGroupService.getZabUsrGrpId(user.getUserGroupId()); - zbxUser.userUpdate(oldUser.getZbxId(), usrZbxId); + if (user.getUserId() == 1) { + throw new ServiceException(BizExceptionEnum.CANT_CHANGE_ADMIN); + } + //判断角色是否存在 + checkByRole(user.getRoleId()); + SysUser sysUser = UserFactory.editUser(user, oldUser); + //取对应的ZBX用户组ID 修改自己的信息 不更新zbx + Long id = LoginContextHolder.getContext().getUser().getId(); + if (!user.getUserId().equals(id)) { + String usrZbxId = sysUserGroupService.getZabUsrGrpId(user.getUserGroupId()); + zbxUser.userUpdate(oldUser.getZbxId(), usrZbxId, ConstantsContext.getConstntsMap().get(GLOBAL_ADMIN_ROLE_CODE).toString()); + } DB.save(sysUser); updateUserCache(); return sysUser; @@ -134,13 +187,22 @@ public SysUser updateUser(UserDto user) { * @return */ public void deleteUser(UserParam user) { + if (user.getUserIds().contains(1)) { + throw new ServiceException(BizExceptionEnum.CANT_DELETE_ADMIN); + } List list = new QSysUser().userId.in(user.getUserIds()).findList(); if (ToolUtil.isEmpty(list)) { throw new ServiceException(BizExceptionEnum.USER_NOT_EXIST); } List zbxIds = list.parallelStream().map(SysUser::getZbxId).collect(Collectors.toList()); - zbxUser.userDelete(zbxIds); + //删除 zbx 用户数据 + if (ToolUtil.isNotEmpty(zbxIds)) { + List zbxUserList = JSONObject.parseArray(zbxUser.getUser(zbxIds.toString()), ZbxUserInfo.class); + if (ToolUtil.isNotEmpty(zbxUserList)) { + zbxUser.userDelete(zbxUserList.parallelStream().map(ZbxUserInfo::getUserid).collect(Collectors.toList())); + } + } new QSysUser().userId.in(user.getUserIds()).delete(); updateUserCache(); } @@ -157,11 +219,23 @@ private void checkByAccount(String account) { } } + /** + * 检查所选角色是否存在 + * + * @param roleId 角色ID + */ + private void checkByRole(Long roleId) { + int count = new QSysRole().roleId.eq(roleId).findCount(); + if (count <= 0) { + throw new ServiceException(BizExceptionEnum.ROLE_NOT_EXIST); + } + } + /** * 修改密码 * - * @param oldPassword - * @param newPassword + * @param oldPassword String + * @param newPassword String */ public void changePwd(String oldPassword, String newPassword) { LoginUser loginUser = LoginContextHolder.getContext().getUser(); @@ -169,11 +243,15 @@ public void changePwd(String oldPassword, String newPassword) { if (null == loginUser) { throw new ServiceException(AuthExceptionEnum.NOT_LOGIN_ERROR); } + if (loginUser.getId() == 1) { + throw new ServiceException(BizExceptionEnum.CANT_CHANGE_ADMIN_PWD); + } SysUser user = new QSysUser().userId.eq(loginUser.getId()).findOne(); - + String rawNewPasswd = ""; try { - oldPassword = RsaUtil.decryptPwd(oldPassword); - newPassword = RsaUtil.decryptPwd(newPassword); + oldPassword = new String(Hex.decodeHex(oldPassword)); + newPassword = new String(Hex.decodeHex(newPassword)); + rawNewPasswd = newPassword; } catch (Exception e) { throw new ServiceException(BizExceptionEnum.PWD_DECRYPT_ERR); } @@ -184,6 +262,8 @@ public void changePwd(String oldPassword, String newPassword) { newPassword = SaltUtil.md5Encrypt(newPassword, user.getSalt()); user.setPassword(newPassword); DB.update(user); + + zbxUser.updatePwd(user.getZbxId(), rawNewPasswd); } else { throw new ServiceException(BizExceptionEnum.OLD_PWD_NOT_RIGHT); } @@ -197,4 +277,14 @@ public void updateUserCache() { public void run(String... args) throws Exception { updateUserCache(); } + + + public void reset(Long userId) { + SysUser user = new QSysUser().userId.eq(userId).findOne(); + user.setSalt(SaltUtil.getRandomSalt()); + user.setPassword(SaltUtil.md5Encrypt(ConstantsContext.getDefaultPassword(), user.getSalt())); + DB.update(user); + + zbxUser.updatePwd(user.getZbxId(), ConstantsContext.getDefaultPassword()); + } } diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/Tenantervice.java b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/Tenantervice.java new file mode 100644 index 00000000..fe4e8ef8 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/sys/service/Tenantervice.java @@ -0,0 +1,208 @@ +package com.zmops.iot.web.sys.service; + +import com.zmops.iot.constant.ConstantsContext; +import com.zmops.iot.domain.device.DeviceGroup; +import com.zmops.iot.domain.device.query.QDeviceGroup; +import com.zmops.iot.domain.product.query.QProductType; +import com.zmops.iot.domain.sys.SysUser; +import com.zmops.iot.domain.sys.SysUserGroup; +import com.zmops.iot.domain.sys.query.QSysUser; +import com.zmops.iot.domain.sys.query.QSysUserGroup; +import com.zmops.iot.domain.tenant.TenantInfo; +import com.zmops.iot.domain.tenant.query.QTenantInfo; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.util.DefinitionsUtil; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.device.dto.param.DeviceGroupParam; +import com.zmops.iot.web.device.service.DeviceGroupService; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.product.dto.param.ProductTypeParam; +import com.zmops.iot.web.product.service.ProductTypeService; +import com.zmops.iot.web.sys.dto.TenantInfoDto; +import com.zmops.iot.web.sys.dto.UserDto; +import com.zmops.iot.web.sys.dto.UserGroupDto; +import com.zmops.iot.web.sys.dto.param.TenantInfoParam; +import io.ebean.DB; +import io.ebean.annotation.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + + +/** + * @author yefei + **/ +@Service +public class Tenantervice implements CommandLineRunner { + + private static final String ZEUS_TENANT_ROLE_ID = "ZEUS_TENANT_ROLE_ID"; + + @Autowired + SysUserGroupService sysUserGroupService; + + @Autowired + DeviceGroupService deviceGroupService; + + @Autowired + SysUserService sysUserService; + + @Autowired + ProductTypeService productTypeService; + + public Pager getTenantByPage(TenantInfoParam tenantInfoParam) { + QTenantInfo qTenantInfo = new QTenantInfo(); + if (ToolUtil.isNotEmpty(tenantInfoParam.getName())) { + qTenantInfo.name.contains(tenantInfoParam.getName()); + } + List list = qTenantInfo.orderBy().createTime.desc().asDto(TenantInfoDto.class).setFirstRow((tenantInfoParam.getPage() - 1) * tenantInfoParam.getMaxRow()) + .setMaxRows(tenantInfoParam.getMaxRow()).findList(); + list.forEach(tenantInfoDto -> { + int count = new QSysUser().tenantId.eq(tenantInfoDto.getTenantId()).findCount(); + tenantInfoDto.setUserNum(count); + }); + return new Pager<>(list, qTenantInfo.findCount()); + } + + @Transactional + public Object createTenant(TenantInfoParam tenantInfoParam) { + //step 1:新增租户 + TenantInfo tenantInfo = new TenantInfo(); + ToolUtil.copyProperties(tenantInfoParam, tenantInfo); + tenantInfo.setStatus(CommonStatus.ENABLE.getCode()); + DB.save(tenantInfo); + + //step 2: 新增默认产品分类 + addProductType(tenantInfo.getTenantId(), tenantInfoParam.getName()); + //step 3:新增默认设备组 + addDeviceGrp(tenantInfo.getTenantId(), tenantInfoParam.getName()); + //step 4:新增租户管理员账号 + long userGrpId = addSysUserGrp(tenantInfo.getTenantId(), tenantInfoParam.getName()); + addSysUser(tenantInfoParam, userGrpId, tenantInfo.getTenantId()); + //step 5:新增租户告警通知方式设置 + addMediaTypeSetting(tenantInfo.getTenantId()); + //更新租户名称缓存 + updateTenantName(); + return tenantInfo; + } + + private void addMediaTypeSetting(Long tenantId) { + DB.sqlUpdate("insert into media_type_setting (type,template,webhooks,tenant_id) SELECT type,template,webhooks,:tenantId from media_type_setting where tenant_id is null") + .setParameter("tenantId", tenantId).execute(); + + DB.sqlUpdate("insert into mail_setting (host, port, account, password, sender, ssl, tls, severity, silent, tenant_id) SELECT host, port, account, password, sender, ssl, tls, severity, silent,:tenantId from mail_setting where tenant_id is null") + .setParameter("tenantId", tenantId).execute(); + } + + private void addProductType(Long tenantId, String tenantName) { + ProductTypeParam productTypeParam = new ProductTypeParam(); + productTypeParam.setName("默认产品分组-" + tenantName); + productTypeParam.setTenantId(tenantId); + productTypeService.create(productTypeParam); + } + + private long addDeviceGrp(Long tenantId, String tenantName) { + DeviceGroupParam deviceGroupDto = new DeviceGroupParam(); + deviceGroupDto.setName("默认设备组-" + tenantName); + deviceGroupDto.setTenantId(tenantId); + DeviceGroup deviceGroup = deviceGroupService.createDeviceGroup(deviceGroupDto); + return deviceGroup.getDeviceGroupId(); + } + + private long addSysUserGrp(Long tenantId, String tenantName) { + UserGroupDto userGroupDto = new UserGroupDto(); + userGroupDto.setGroupName("管理员组-" + tenantName); + userGroupDto.setRemark("默认管理员组,不要绑定设备组"); + userGroupDto.setTenantId(tenantId); + SysUserGroup userGroup = sysUserGroupService.createUserGroup(userGroupDto); + return userGroup.getUserGroupId(); + } + + private void addSysUser(TenantInfoParam tenantInfoParam, Long userGrpId, Long tenantId) { + UserDto userDto = new UserDto(); + userDto.setAccount(tenantInfoParam.getAccount()); + userDto.setPassword(tenantInfoParam.getPassword()); + userDto.setRoleId(Long.parseLong(ConstantsContext.getConstntsMap().getOrDefault(ZEUS_TENANT_ROLE_ID, "1").toString())); + userDto.setUserGroupId(userGrpId); + String userName = tenantInfoParam.getContact(); + if (ToolUtil.isEmpty(userName)) { + userName = tenantInfoParam.getName() + "管理员"; + } + userDto.setName(userName); + userDto.setPhone(tenantInfoParam.getPhone()); + userDto.setTenantId(tenantId); + sysUserService.createUser(userDto); + } + + @Transactional + public Object updateTenant(TenantInfoParam tenantInfoParam) { + TenantInfo tenantInfo = new QTenantInfo().tenantId.eq(tenantInfoParam.getTenantId()).findOne(); + if (null == tenantInfo) { + throw new ServiceException(BizExceptionEnum.TENANT_NOT_EXISTS); + } + tenantInfo.setName(tenantInfoParam.getName()); + tenantInfo.setRemark(tenantInfoParam.getRemark()); + tenantInfo.setContact(tenantInfoParam.getContact()); + tenantInfo.setPhone(tenantInfoParam.getPhone()); + DB.update(tenantInfo); + updateTenantName(); + return tenantInfo; + } + + public void deleteTenant(TenantInfoParam tenantInfoParam) { + if (isRelationInfo(tenantInfoParam.getTenantId())) { + throw new ServiceException(BizExceptionEnum.TENANT_HAS_RELATION_INFO); + } + new QTenantInfo().tenantId.eq(tenantInfoParam.getTenantId()).delete(); + updateTenantName(); + } + + private boolean isRelationInfo(Long tenantId) { + + int count = new QSysUserGroup().tenantId.eq(tenantId).findCount(); + if (count > 0) { + return true; + } + count = new QDeviceGroup().tenantId.eq(tenantId).findCount(); + if (count > 0) { + return true; + } + count = new QProductType().tenantId.eq(tenantId).findCount(); + if (count > 0) { + return true; + } + + return false; + } + + /** + * 启用 禁用租户 + * + * @param tenantId + * @param status + */ + @Transactional(rollbackFor = Exception.class) + public void status(Long tenantId, String status) { + DB.update(SysUser.class).where().eq("tenantId", tenantId).asUpdate().set("status", status).update(); + DB.update(TenantInfo.class).where().eq("tenantId", tenantId).asUpdate().set("status", status).update(); + } + + private void updateTenantName() { + List list = new QTenantInfo().findList(); + if (ToolUtil.isEmpty(list)) { + return; + } + DefinitionsUtil.updateTenantName(list.parallelStream().collect(Collectors.toMap(TenantInfo::getTenantId, TenantInfo::getName, (a, b) -> a))); + } + + @Override + public void run(String... args) throws Exception { + updateTenantName(); + } + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/task/controller/taskController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/task/controller/taskController.java new file mode 100644 index 00000000..3528e1c5 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/task/controller/taskController.java @@ -0,0 +1,95 @@ +package com.zmops.iot.web.task.controller; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.device.dto.DeviceGroupDto; +import com.zmops.iot.web.task.dto.TaskDto; +import com.zmops.iot.web.task.param.TaskParam; +import com.zmops.iot.web.task.service.TaskService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author yefei + *

+ * 任务管理 + **/ +@RestController +@RequestMapping("/task") +public class taskController { + + @Autowired + TaskService taskService; + +// /** +// * 任务分页列表 +// * +// * @return +// */ +// @PostMapping("/getTaskByPage") +// public Pager getTaskByPage(@RequestBody TaskParam taskParam) { +// return taskService.getTaskByPage(taskParam); +// } +// +// /** +// * 设任务列表 +// * +// * @return +// */ +// @PostMapping("/list") +// public ResponseData list(@RequestBody TaskParam taskParam) { +// return ResponseData.success(taskService.list(taskParam)); +// } + + /** + * 创建任务 + * + * @return + */ + @PostMapping("/create") +// @BussinessLog(value = "创建任务") + public ResponseData createTask(@Validated(BaseEntity.Create.class) @RequestBody TaskDto taskDto) { + return ResponseData.success(taskService.createTask(taskDto)); + } + + + /** + * 更新任务 + * + * @return + */ + @PostMapping("/update") +// @BussinessLog(value = "更新任务") + public ResponseData updateTask(@Validated(BaseEntity.Update.class) @RequestBody TaskDto taskDto) { + return ResponseData.success(taskService.updateTask(taskDto)); + } + + /** + * 删除任务 + * + * @return + */ + @PostMapping("/delete") +// @BussinessLog(value = "删除任务") + public ResponseData deleteTask(@Validated(BaseEntity.Delete.class) @RequestBody TaskDto taskParam) { + taskService.deleteTask(taskParam); + return ResponseData.success(); + } + + /** + * 启动 停止任务 + * + * @return + */ + @PostMapping("/status") +// @BussinessLog(value = "启动 停止任务") + public ResponseData status(@Validated(BaseEntity.Delete.class) @RequestBody TaskDto taskDto) { + taskService.status(taskDto); + return ResponseData.success(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java new file mode 100644 index 00000000..e95953cb --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/task/dto/TaskDto.java @@ -0,0 +1,50 @@ +package com.zmops.iot.web.task.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValue; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import com.zmops.iot.model.cache.filter.DicType; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class TaskDto { + + private Integer id; + + private String scheduleType = "CRON"; + + private String scheduleConf; + + private String misfireStrategy = "DO_NOTHING"; + + private Integer taskTimeout = 0; + + private Integer taskFailRetryCount = 0; + + @CachedValue(value = "STATUS", fieldName = "triggerStatusName") + private String triggerStatus = "ENABLE"; + + private Long triggerLastTime = 0L; + + private Long triggerNextTime = 0L; + + private String remark; + + private String executorParam; + + LocalDateTime createTime; + + LocalDateTime updateTime; + + @CachedValue(type = DicType.SysUserName, fieldName = "createUserName") + private Long createUser; + + @CachedValue(type = DicType.SysUserName, fieldName = "updateUserName") + private Long updateUser; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/task/param/TaskParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/task/param/TaskParam.java new file mode 100644 index 00000000..ce17e0a3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/task/param/TaskParam.java @@ -0,0 +1,14 @@ +package com.zmops.iot.web.task.param; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class TaskParam { + + private Integer id; + + private String triggerStatus; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java new file mode 100644 index 00000000..2a3066b3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/task/service/TaskService.java @@ -0,0 +1,82 @@ +package com.zmops.iot.web.task.service; + +import cn.hutool.core.bean.BeanUtil; +import com.zmops.iot.domain.schedule.Task; +import com.zmops.iot.domain.schedule.query.QTask; +import com.zmops.iot.enums.CommonStatus; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.task.dto.TaskDto; +import io.ebean.DB; +import org.springframework.stereotype.Service; + +/** + * @author yefei + **/ +@Service +public class TaskService { + + /** + * 创建任务 + * + * @param taskDto + * @return + */ + public Integer createTask(TaskDto taskDto) { + Task task = new Task(); + BeanUtil.copyProperties(taskDto, task); + DB.insert(task); + return task.getId(); + } + + /** + * 修改任务 + * + * @param taskDto + * @return + */ + public TaskDto updateTask(TaskDto taskDto) { + Task task = new QTask().id.eq(taskDto.getId()).findOne(); + if (task == null) { + task = new Task(); + BeanUtil.copyProperties(taskDto, task); + DB.insert(task); + } else { + task.setExecutorParam(taskDto.getExecutorParam()); + task.setScheduleConf(taskDto.getScheduleConf()); + task.setTriggerNextTime(0L); + task.setRemark(taskDto.getRemark()); + DB.update(task); + } + + return taskDto; + } + + /** + * 删除任务 + * + * @param taskParam + */ + public void deleteTask(TaskDto taskParam) { + if (taskParam.getId() == null) { + return; + } + new QTask().id.eq(taskParam.getId()).delete(); + } + + /** + * 启用 禁用任务 + * 默认启用 + * + * @param taskParam + */ + public void status(TaskDto taskParam) { + if (taskParam.getId() == null) { + return; + } + String triggerStatus = taskParam.getTriggerStatus(); + if (ToolUtil.isEmpty(triggerStatus)) { + triggerStatus = CommonStatus.DISABLE.getCode(); + } + DB.update(Task.class).where().eq("id", taskParam.getId()).asUpdate().set("trigger_status", triggerStatus).update(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/controller/TransferController.java b/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/controller/TransferController.java new file mode 100644 index 00000000..e13844a9 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/controller/TransferController.java @@ -0,0 +1,78 @@ +package com.zmops.iot.web.transfer.controller; + +import com.zmops.iot.domain.BaseEntity; +import com.zmops.iot.domain.proxy.query.QProxy; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.model.page.Pager; +import com.zmops.iot.model.response.ResponseData; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.transfer.dto.TransferDto; +import com.zmops.iot.web.transfer.dto.param.TransferParam; +import com.zmops.iot.web.transfer.service.TransferService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * @author yefei + *

+ * 数据转换服务 + */ + +@RestController +@RequestMapping("/transfer") +public class TransferController { + + @Autowired + TransferService proxyService; + + /** + * 数据转换分页列表 + */ + @GetMapping("/list") + public ResponseData list() { + return ResponseData.success(proxyService.list()); + } + + + /** + * 数据转换创建 + */ + @RequestMapping("/create") + public ResponseData create() { + proxyService.create(); + return ResponseData.success(); + } + + /** + * 数据转换删除 + */ + @RequestMapping("/delete") + public ResponseData delete(@Validated(BaseEntity.Delete.class) @RequestBody TransferParam transferParam) { + proxyService.delete(transferParam.getNames()); + return ResponseData.success(); + } + + /** + * 数据转换启动 + */ + @RequestMapping("/run") + public ResponseData run(@Validated @RequestBody TransferParam transferParam) { + proxyService.run(transferParam); + return ResponseData.success(); + } + + /** + * 数据转换停止 + */ + @RequestMapping("/stop") + public ResponseData stop(@Validated @RequestBody TransferParam transferParam) { + proxyService.stop(transferParam); + return ResponseData.success(); + } +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/ConfigDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/ConfigDto.java new file mode 100644 index 00000000..6e649e0e --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/ConfigDto.java @@ -0,0 +1,17 @@ +package com.zmops.iot.web.transfer.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class ConfigDto { + + private String name; + private String batchSize; + private String batchInterval; + private String createtime; + + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/StatusDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/StatusDto.java new file mode 100644 index 00000000..873a4953 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/StatusDto.java @@ -0,0 +1,74 @@ +package com.zmops.iot.web.transfer.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.zmops.iot.model.cache.filter.CachedValueFilter; +import lombok.Data; + +/** + * @author yefei + **/ +@Data +@JsonSerialize(using = CachedValueFilter.class) +public class StatusDto { + + private String name; + + private String logpath; + + private String readDataSize; + + private String readDataCount; + + private String elaspedtime; + + private Lag lag; + + private ReaderStats readerStats; + + private ParserStats parserStats; + + private String readspeedKb; + + private String readspeed; + + private String runningStatus; + + private String senderStats; + + @Data + public static class Lag { + private String total; + private String size; + private String ftlags; + private String sizeunit; + + } + + @Data + public static class ReaderStats { + private String errors; + private String success; + private String speed; + private String trend; + private String last_error; + } + + @Data + public static class ParserStats { + private String errors; + private String success; + private String speed; + private String trend; + private String last_error; + } + + @Data + public static class SenderStatsObj { + private String errors; + private String success; + private String speed; + private String trend; + private String last_error; + } + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/TransferDto.java b/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/TransferDto.java new file mode 100644 index 00000000..ef47bbb3 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/TransferDto.java @@ -0,0 +1,45 @@ +package com.zmops.iot.web.transfer.dto; + +import lombok.Data; + +/** + * @author yefei + **/ +@Data +public class TransferDto { + + private String name; + + private String createtime; + + private String logpath; + + private String readDataCount; + + private String lagSize; + + + private String parseSuccess; + private String parseError; + + private String parseTotal; + + private String sendSuccess; + private String sendError; + private String sendTotal; + + private String readspeedKb; + + private String readspeed; + + private String sendspeed; + + private String runningStatus; + + private String readLastError; + + private String parseLastError; + + private String sendLastError; + +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/param/TransferParam.java b/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/param/TransferParam.java new file mode 100644 index 00000000..22e13e36 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/dto/param/TransferParam.java @@ -0,0 +1,20 @@ +package com.zmops.iot.web.transfer.dto.param; + +import com.zmops.iot.web.sys.dto.param.BaseQueryParam; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author yefei + **/ +@Data +public class TransferParam extends BaseQueryParam { + + @NotNull + private List names; + + private String run; +} diff --git a/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/service/TransferService.java b/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/service/TransferService.java new file mode 100644 index 00000000..17f8b245 --- /dev/null +++ b/zeus-webapp/src/main/java/com/zmops/iot/web/transfer/service/TransferService.java @@ -0,0 +1,155 @@ +package com.zmops.iot.web.transfer.service; + +import com.alibaba.fastjson.JSONObject; +import com.zmops.iot.model.exception.ServiceException; +import com.zmops.iot.util.LocalDateTimeUtils; +import com.zmops.iot.util.ParseUtil; +import com.zmops.iot.util.ToolUtil; +import com.zmops.iot.web.exception.enums.BizExceptionEnum; +import com.zmops.iot.web.transfer.dto.ConfigDto; +import com.zmops.iot.web.transfer.dto.StatusDto; +import com.zmops.iot.web.transfer.dto.TransferDto; +import com.zmops.iot.web.transfer.dto.param.TransferParam; +import com.zmops.zeus.driver.service.TransferKit; +import com.zmops.zeus.driver.service.ZbxConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.*; + +/** + * @author yefei + *

+ * 数据转换 服务 + **/ +@Service +public class TransferService { + + @Autowired + TransferKit transferKit; + + @Autowired + ZbxConfig zbxConfig; + + /** + * 转换服务列表 + * + * @return + */ + public List list() { + String configs = transferKit.getConfigs(); + if (ToolUtil.isEmpty(configs)) { + return Collections.emptyList(); + } + JSONObject jsonObject = JSONObject.parseObject(configs); + List transferDtoList = new ArrayList<>(); + HashMap hashMap = JSONObject.parseObject(jsonObject.getString("data"), HashMap.class); + for (Map.Entry s : hashMap.entrySet()) { + ConfigDto configDto = JSONObject.parseObject(JSONObject.toJSONString(s.getValue()), ConfigDto.class); + transferDtoList.add(BuildTransferDto(configDto)); + } + + String status = transferKit.getStatus(); + if (ToolUtil.isEmpty(status)) { + return transferDtoList; + } + JSONObject statusObject = JSONObject.parseObject(status); + HashMap statusMap = JSONObject.parseObject(statusObject.getString("data"), HashMap.class); + transferDtoList.forEach(transferDto -> { + if (null != statusMap.get(transferDto.getName())) { + StatusDto statusDto = JSONObject.parseObject(JSONObject.toJSONString(statusMap.get(transferDto.getName())), StatusDto.class); + transferDto.setLogpath(statusDto.getLogpath()); + + transferDto.setReadDataCount(ParseUtil.getCommaFormat(statusDto.getReadDataCount())); + transferDto.setReadLastError(statusDto.getReaderStats().getLast_error()); + transferDto.setLagSize(ParseUtil.formatLagSize(statusDto.getLag().getSize())); + transferDto.setParseError(ToolUtil.isEmpty(statusDto.getParserStats().getErrors()) ? "0" : statusDto.getParserStats().getErrors()); + transferDto.setParseSuccess(ToolUtil.isEmpty(statusDto.getParserStats().getSuccess()) ? "0" : statusDto.getParserStats().getSuccess()); + transferDto.setParseTotal(transferDto.getParseSuccess() + transferDto.getParseError()); + transferDto.setParseLastError(statusDto.getParserStats().getLast_error()); + + HashMap sendStatusMap = JSONObject.parseObject(statusDto.getSenderStats(), HashMap.class); + for (Map.Entry map : sendStatusMap.entrySet()) { + StatusDto.SenderStatsObj senderStatsObj = JSONObject.parseObject(JSONObject.toJSONString(map.getValue()), StatusDto.SenderStatsObj.class); + transferDto.setSendSuccess(ToolUtil.isEmpty(senderStatsObj.getSuccess()) ? "0" : senderStatsObj.getSuccess()); + transferDto.setSendError(ToolUtil.isEmpty(senderStatsObj.getErrors()) ? "0" : senderStatsObj.getErrors()); + transferDto.setSendTotal(transferDto.getSendSuccess() + transferDto.getSendError()); + transferDto.setSendspeed(ToolUtil.isEmpty(senderStatsObj.getSpeed()) ? "0" : senderStatsObj.getSpeed()); + transferDto.setSendLastError(senderStatsObj.getLast_error()); + } + + transferDto.setReadspeed(statusDto.getReadspeed()); + transferDto.setReadspeedKb(statusDto.getReadspeedKb()); + transferDto.setRunningStatus(statusDto.getRunningStatus().equalsIgnoreCase("running") ? "ENABLE" : "DISABLE"); + } + }); + + return transferDtoList; + } + + private TransferDto BuildTransferDto(ConfigDto configDto) { + TransferDto transferDto = new TransferDto(); + transferDto.setName(configDto.getName()); + transferDto.setCreatetime(configDto.getCreatetime()); + return transferDto; + } + + /** + * 转换服务创建 + * + * @return + */ + public void create() { + String config = zbxConfig.getConfig(); + if (ToolUtil.isEmpty(config)) { + throw new ServiceException(BizExceptionEnum.ZBX_SERBER_NOT_CONFIG); + } + Map map = JSONObject.parseObject(config, Map.class); + String exportPath = map.get("ExportDir"); + String StartDBSyncers = map.get("StartDBSyncers"); + if (null == exportPath || "".equals(exportPath) || null == StartDBSyncers || "".equals(StartDBSyncers)) { + throw new ServiceException(BizExceptionEnum.ZBX_SERBER_EXPORT_PATH_NOT_CONFIG); + } + int dbSyncers = Integer.parseInt(StartDBSyncers); + for (int i = 1; i <= dbSyncers; i++) { + String logPath = exportPath + "/history-history-syncer-" + i + ".ndjson"; + String name = "runner:" + LocalDateTimeUtils.getMilliByTime(LocalDateTime.now()); + transferKit.createRunner(name, name, logPath, 20, 2097152); + } + } + + + /** + * 转换服务删除 + * + * @param names + * @return + */ + public void delete(List names) { + names.forEach(name -> { + transferKit.deleteRunner(name); + }); + } + + /** + * 数据转换启动 + */ + public void run(TransferParam transferParam) { + if (ToolUtil.isEmpty(transferParam.getRun()) || !"true".equals(transferParam.getRun())) { + stop(transferParam); + } + transferParam.getNames().forEach(name -> { + transferKit.startRunner(name); + }); + } + + /** + * 数据转换停止 + */ + public void stop(TransferParam transferParam) { + transferParam.getNames().forEach(name -> { + transferKit.stopRunner(name); + }); + } +} diff --git a/zeus-webapp/src/main/resources/nodata.jpg b/zeus-webapp/src/main/resources/nodata.jpg new file mode 100644 index 00000000..b8e6e87e Binary files /dev/null and b/zeus-webapp/src/main/resources/nodata.jpg differ