From 3e6c3aaf4cc76f41ff01010b4818e7c49ebeb565 Mon Sep 17 00:00:00 2001 From: "CHINAMI-TV221UM\\Administrator" Date: Tue, 9 Jul 2024 09:49:42 +0800 Subject: [PATCH] no message --- .cproject | 68 +- .idea/.gitignore | 8 + .idea/deployment.xml | 36 + .idea/misc.xml | 18 + .idea/other.xml | 10 + .idea/vcs.xml | 6 + .metadata/.lock | 0 .metadata/.log | 1292 +++++++ .../.root/.indexes/properties.version | 1 + .../org.eclipse.core.resources.prefs | 3 + .settings/language.settings.xml | 6 +- .vscode/settings.json | 73 + API_log/SH_log.cpp | 23 +- Cidn-SH | Bin 0 -> 1679480 bytes MD5/md5.cpp | 304 ++ MD5/md5.h | 16 + Makefile | 30 +- calculation/Calculation.cpp | 135 +- calculation/Calculation.hpp | 15 +- common/Mutex.h | 20 + common/SH_CommonFunc.cpp | 1762 ++++++++- common/SH_CommonFunc.hpp | 194 +- common/SH_global.h | 30 +- datatransfer/SH_Datatrans.cpp | 68 + datatransfer/SH_Datatrans.hpp | 2 +- dbaccess/SH_SqlDB.cpp | 669 +++- dbaccess/SH_SqlDB.hpp | 62 +- dial5G/Dial.cpp | 296 ++ dial5G/Dial.h | 70 + jsonparse/SH_JsonCmd.cpp | 1611 +++++++-- jsonparse/SH_JsonCmd.hpp | 20 +- localserver/SH_LocalServer.cpp | 228 +- main.cpp | 73 +- mqttclient/SH_MqttClient.cpp | 61 +- mqttclient/SH_MqttClient.h | 1 + platform/SH_PlatformInit.cpp | 156 +- platform/SH_PlatformInit.hpp | 4 +- searchdev/SH_SearchDev.cpp | 4 +- serial/serial.c | 503 +++ serial/serial.h | 193 + tcpcgi/TcpCgi.cpp | 2 +- threadfunc/SH_ThreadFunc.cpp | 666 +++- threadfunc/SH_ThreadFunc.hpp | 6 + uart/SH_Uart.cpp | 3134 +++++++++++++---- uart/SH_Uart.hpp | 64 +- udpqt/SH_UdpQt.cpp | 4 +- wifi/wpa_client.cpp | 555 +++ wifi/wpa_client.h | 90 + 48 files changed, 11315 insertions(+), 1277 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/deployment.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/other.xml create mode 100644 .idea/vcs.xml create mode 100644 .metadata/.lock create mode 100644 .metadata/.log create mode 100644 .metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version create mode 100644 .metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs create mode 100644 .vscode/settings.json create mode 100644 Cidn-SH create mode 100644 MD5/md5.cpp create mode 100644 MD5/md5.h create mode 100644 common/Mutex.h create mode 100644 dial5G/Dial.cpp create mode 100644 dial5G/Dial.h create mode 100644 serial/serial.c create mode 100644 serial/serial.h create mode 100644 wifi/wpa_client.cpp create mode 100644 wifi/wpa_client.h diff --git a/.cproject b/.cproject index 55e6828..32dc3ef 100644 --- a/.cproject +++ b/.cproject @@ -14,27 +14,28 @@ - + + + + + @@ -91,41 +96,42 @@ - + + + + + diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/deployment.xml b/.idea/deployment.xml new file mode 100644 index 0000000..a5120ee --- /dev/null +++ b/.idea/deployment.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..53624c9 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,18 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/other.xml b/.idea/other.xml new file mode 100644 index 0000000..8fe5a6c --- /dev/null +++ b/.idea/other.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.metadata/.lock b/.metadata/.lock new file mode 100644 index 0000000..e69de29 diff --git a/.metadata/.log b/.metadata/.log new file mode 100644 index 0000000..91e2b0a --- /dev/null +++ b/.metadata/.log @@ -0,0 +1,1292 @@ +!SESSION 2024-04-25 11:26:26.165 ----------------------------------------------- +eclipse.buildId=4.24.0.I20220607-0700 +java.version=17.0.3 +java.vendor=Eclipse Adoptium +BootLoader constants: OS=linux, ARCH=x86_64, WS=gtk, NL=zh_CN +Framework arguments: -product org.eclipse.epp.package.cpp.product +Command-line arguments: -os linux -ws gtk -arch x86_64 -product org.eclipse.epp.package.cpp.product + +!ENTRY org.eclipse.linuxtools.docker.editor.ls 4 0 2024-04-25 11:26:26.982 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.linuxtools.docker.editor.ls [823] + Unresolved requirement: Require-Bundle: org.eclipse.lsp4e; bundle-version="0.11.0" + -> Bundle-SymbolicName: org.eclipse.lsp4e; bundle-version="0.15.0.202211292024"; singleton:="true" + org.eclipse.lsp4e [843] + Unresolved requirement: Require-Bundle: org.eclipse.lsp4j; bundle-version="[0.19.0,0.20.0)" + -> Bundle-SymbolicName: org.eclipse.lsp4j; bundle-version="0.19.0.v20221118-0359" + org.eclipse.lsp4j [846] + Unresolved requirement: Import-Package: com.google.gson; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + com.google.gson [620] + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.messages; version="[0.19.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.messages; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc.validation" + org.eclipse.lsp4j.jsonrpc [848] + Unresolved requirement: Import-Package: com.google.gson.internal; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.internal; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; x-internal:="true"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc + -> Export-Package: org.eclipse.lsp4j.jsonrpc; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + org.eclipse.lsp4j.jsonrpc [847] + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.messages + -> Export-Package: org.eclipse.lsp4j.jsonrpc.messages; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc.validation" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json.adapters + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + org.eclipse.lsp4j.jsonrpc [849] + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json.adapters + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.services + -> Export-Package: org.eclipse.lsp4j.jsonrpc.services; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.json" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc + -> Export-Package: org.eclipse.lsp4j.jsonrpc; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.messages + -> Export-Package: org.eclipse.lsp4j.jsonrpc.messages; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc.validation" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.validation + -> Export-Package: org.eclipse.lsp4j.jsonrpc.validation; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.services + -> Export-Package: org.eclipse.lsp4j.jsonrpc.services; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.json" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.validation + -> Export-Package: org.eclipse.lsp4j.jsonrpc.validation; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.validation; version="[0.19.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.validation; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; version="[0.19.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.common.base; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + com.google.guava [1027] + Unresolved requirement: Import-Package: com.google.errorprone.annotations; version="[3.0.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Import-Package: com.google.errorprone.annotations.concurrent; version="[3.0.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Import-Package: javax.crypto; version="[3.0.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Import-Package: javax.crypto.spec; version="[3.0.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Import-Package: org.checkerframework.checker.nullness.qual; version="[3.5.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Import-Package: org.eclipse.lsp4j + -> Export-Package: org.eclipse.lsp4j; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.14.0.v20220526-1518"; version="0.14.0.v20220526-1518"; uses:="com.google.gson.annotations,org.eclipse.lsp4j.adapters,org.eclipse.lsp4j.jsonrpc.messages,org.eclipse.lsp4j.jsonrpc.validation,org.eclipse.xtext.xbase.lib" + org.eclipse.lsp4j [1069] + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.8.9,2.9.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.8.9.v20220111-1409"; version="2.8.9" + com.google.gson [1026] + Unresolved requirement: Import-Package: com.google.gson.internal.sql; version="[2.8.0,3.0.0)" + -> Export-Package: com.google.gson.internal.sql; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; x-internal:="true"; uses:="com.google.gson,com.google.gson.internal.bind" + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.8.0,3.0.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.8.0,3.0.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: com.google.gson.internal.reflect; version="[2.8.0,3.0.0)" + -> Export-Package: com.google.gson.internal.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; x-internal:="true"; uses:="com.google.gson" + Unresolved requirement: Import-Package: com.google.gson.internal.bind.util; version="[2.8.0,3.0.0)" + -> Export-Package: com.google.gson.internal.bind.util; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; x-internal:="true" + Unresolved requirement: Import-Package: com.google.gson.internal; version="[2.8.0,3.0.0)" + -> Export-Package: com.google.gson.internal; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; x-internal:="true"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.8.9,2.9.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.8.9.v20220111-1409"; version="2.8.9" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.messages; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.messages; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc.validation" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.validation; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.validation; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.services; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.services; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="org.eclipse.lsp4j,org.eclipse.lsp4j.adapters,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages,org.eclipse.lsp4j.jsonrpc.services" + org.eclipse.lsp4j [844] + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.util + -> Export-Package: org.eclipse.lsp4j.util; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j" + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.validation; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.validation; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j + -> Export-Package: org.eclipse.lsp4j; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.14.0.v20220526-1518"; version="0.14.0.v20220526-1518"; uses:="com.google.gson.annotations,org.eclipse.lsp4j.adapters,org.eclipse.lsp4j.jsonrpc.messages,org.eclipse.lsp4j.jsonrpc.validation,org.eclipse.xtext.xbase.lib" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.adapters + -> Export-Package: org.eclipse.lsp4j.adapters; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j,org.eclipse.lsp4j.jsonrpc.messages" + org.eclipse.lsp4j [845] + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j + -> Export-Package: org.eclipse.lsp4j; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.14.0.v20220526-1518"; version="0.14.0.v20220526-1518"; uses:="com.google.gson.annotations,org.eclipse.lsp4j.adapters,org.eclipse.lsp4j.jsonrpc.messages,org.eclipse.lsp4j.jsonrpc.validation,org.eclipse.xtext.xbase.lib" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.services + -> Export-Package: org.eclipse.lsp4j.services; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="org.eclipse.lsp4j,org.eclipse.lsp4j.adapters,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages,org.eclipse.lsp4j.jsonrpc.services" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.validation; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.validation; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.messages; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.messages; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc.validation" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.util + -> Export-Package: org.eclipse.lsp4j.util; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.services; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.services; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.json" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.messages; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.messages; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc.validation" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.services; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.services; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.json" + Unresolved requirement: Import-Package: com.google.gson; version="[2.8.9,2.9.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.8.9.v20220111-1409"; version="2.8.9"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: com.google.common.base; version="[14.0.0,31.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.util; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.util; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j" + Unresolved requirement: Import-Package: org.eclipse.xtext.xbase.lib.util; version="[2.24.0,3.0.0)" + -> Export-Package: org.eclipse.xtext.xbase.lib.util; bundle-symbolic-name="org.eclipse.xtext.xbase.lib"; bundle-version="2.29.0.v20221121-0915"; version="2.29.0" + org.eclipse.xtext.xbase.lib [943] + Unresolved requirement: Require-Bundle: com.google.guava; bundle-version="[30.1.0,31.0.0)"; visibility:="reexport" + -> Bundle-SymbolicName: com.google.guava; bundle-version="30.1.0.v20210127-2300" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.services; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.services; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.json" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.adapters; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.adapters; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.8.9,2.9.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.8.9.v20220111-1409"; version="2.8.9" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.xtext.xbase.lib; version="[2.24.0,3.0.0)" + -> Export-Package: org.eclipse.xtext.xbase.lib; bundle-symbolic-name="org.eclipse.xtext.xbase.lib"; bundle-version="2.29.0.v20221121-0915"; version="2.29.0" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc; version="[0.19.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.services; version="[0.19.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.services; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.json" + Unresolved requirement: Import-Package: org.eclipse.xtext.xbase.lib.util; version="[2.28.0,3.0.0)" + -> Export-Package: org.eclipse.xtext.xbase.lib.util; bundle-symbolic-name="org.eclipse.xtext.xbase.lib"; bundle-version="2.29.0.v20221121-0915"; version="2.29.0" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.adapters + -> Export-Package: org.eclipse.lsp4j.adapters; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.services + -> Export-Package: org.eclipse.lsp4j.services; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="org.eclipse.lsp4j,org.eclipse.lsp4j.adapters,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages,org.eclipse.lsp4j.jsonrpc.services" + Unresolved requirement: Import-Package: org.eclipse.xtext.xbase.lib; version="[2.28.0,3.0.0)" + -> Export-Package: org.eclipse.xtext.xbase.lib; bundle-symbolic-name="org.eclipse.xtext.xbase.lib"; bundle-version="2.29.0.v20221121-0915"; version="2.29.0" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json; version="[0.19.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Require-Bundle: org.eclipse.mylyn.wikitext; bundle-version="3.0.40" + -> Bundle-SymbolicName: org.eclipse.mylyn.wikitext; bundle-version="3.0.42.20220107230029" + org.eclipse.mylyn.wikitext [361] + Unresolved requirement: Import-Package: org.jsoup; version="[1.14.0,2.0.0)" + -> Export-Package: org.jsoup; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="javax.annotation,javax.net.ssl,org.jsoup.nodes,org.jsoup.parser,org.jsoup.safety" + org.jsoup [1113] + Unresolved requirement: Import-Package: javax.annotation.meta; resolution:="optional" + Unresolved requirement: Import-Package: com.google.common.collect; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.collect; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.common.base,com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.builder + -> Export-Package: org.eclipse.mylyn.wikitext.parser.builder; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.builder.event,org.eclipse.mylyn.wikitext.parser.outline,org.eclipse.mylyn.wikitext.util" + org.eclipse.mylyn.wikitext [851] + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.builder.event + -> Export-Package: org.eclipse.mylyn.wikitext.parser.builder.event; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser" + Unresolved requirement: Import-Package: com.google.common.base; version="[31.1.0,32.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="31.1.0.jre"; version="31.1.0"; uses:="javax.annotation" + com.google.guava [623] + Unresolved requirement: Import-Package: javax.annotation; version="[3.0.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Import-Package: com.google.common.xml; version="[31.1.0,32.0.0)" + -> Export-Package: com.google.common.xml; bundle-symbolic-name="com.google.guava"; bundle-version="31.1.0.jre"; version="31.1.0"; uses:="com.google.common.escape" + Unresolved requirement: Import-Package: org.jsoup; version="[1.15.0,2.0.0)" + -> Export-Package: org.jsoup; bundle-symbolic-name="org.jsoup"; bundle-version="1.15.3"; version="1.15.3"; uses:="javax.annotation,javax.net.ssl,org.jsoup.nodes,org.jsoup.parser,org.jsoup.safety" + org.jsoup [978] + Unresolved requirement: Import-Package: javax.annotation.meta; resolution:="optional" + Unresolved requirement: Import-Package: org.jsoup.internal + -> Export-Package: org.jsoup.internal; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; x-internal:="true"; uses:="javax.annotation,javax.annotation.meta" + Unresolved requirement: Import-Package: org.jsoup + -> Export-Package: org.jsoup; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="javax.annotation,javax.net.ssl,org.jsoup.nodes,org.jsoup.parser,org.jsoup.safety" + Unresolved requirement: Import-Package: org.jsoup.parser + -> Export-Package: org.jsoup.parser; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="javax.annotation,org.jsoup.nodes" + Unresolved requirement: Import-Package: org.jsoup.helper + -> Export-Package: org.jsoup.helper; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="javax.annotation,javax.net.ssl,javax.xml.parsers,org.jsoup,org.jsoup.nodes,org.jsoup.parser,org.jsoup.select,org.w3c.dom" + Unresolved requirement: Import-Package: org.jsoup.safety + -> Export-Package: org.jsoup.safety; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="org.jsoup.nodes" + Unresolved requirement: Import-Package: org.jsoup.select + -> Export-Package: org.jsoup.select; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="javax.annotation,org.jsoup.nodes" + Unresolved requirement: Import-Package: org.jsoup.select; version="[1.15.0,2.0.0)" + -> Export-Package: org.jsoup.select; bundle-symbolic-name="org.jsoup"; bundle-version="1.15.3"; version="1.15.3"; uses:="javax.annotation,org.jsoup.nodes" + Unresolved requirement: Import-Package: com.google.common.collect; version="[31.1.0,32.0.0)" + -> Export-Package: com.google.common.collect; bundle-symbolic-name="com.google.guava"; bundle-version="31.1.0.jre"; version="31.1.0"; uses:="com.google.common.base,javax.annotation" + Unresolved requirement: Import-Package: com.google.common.escape; version="[31.1.0,32.0.0)" + -> Export-Package: com.google.common.escape; bundle-symbolic-name="com.google.guava"; bundle-version="31.1.0.jre"; version="31.1.0"; uses:="com.google.common.base,javax.annotation" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.outline + -> Export-Package: org.eclipse.mylyn.wikitext.parser.outline; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.block + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.block; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser.markup,org.eclipse.mylyn.wikitext.parser.outline" + Unresolved requirement: Import-Package: org.jsoup.nodes; version="[1.15.0,2.0.0)" + -> Export-Package: org.jsoup.nodes; bundle-symbolic-name="org.jsoup"; bundle-version="1.15.3"; version="1.15.3"; uses:="javax.annotation,org.jsoup,org.jsoup.helper,org.jsoup.parser,org.jsoup.select" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.internal.parser.html + -> Export-Package: org.eclipse.mylyn.wikitext.internal.parser.html; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser,org.jsoup.nodes,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.util" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.token + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.token; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.jsoup.internal; version="[1.15.0,2.0.0)" + -> Export-Package: org.jsoup.internal; bundle-symbolic-name="org.jsoup"; bundle-version="1.15.3"; version="1.15.3"; uses:="javax.annotation,javax.annotation.meta" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.util + -> Export-Package: org.eclipse.mylyn.wikitext.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="javax.xml.stream,org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.css + -> Export-Package: org.eclipse.mylyn.wikitext.parser.css; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.internal.util + -> Export-Package: org.eclipse.mylyn.wikitext.internal.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; x-internal:="true" + Unresolved requirement: Import-Package: org.jsoup.internal; version="[1.14.0,2.0.0)" + -> Export-Package: org.jsoup.internal; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; x-internal:="true"; uses:="javax.annotation,javax.annotation.meta" + Unresolved requirement: Import-Package: org.jsoup.nodes; version="[1.14.0,2.0.0)" + -> Export-Package: org.jsoup.nodes; bundle-symbolic-name="org.jsoup"; bundle-version="1.15.3"; version="1.15.3"; uses:="javax.annotation,org.jsoup,org.jsoup.helper,org.jsoup.parser,org.jsoup.select" + Unresolved requirement: Import-Package: com.google.common.base; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + Unresolved requirement: Import-Package: com.google.common.xml; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.xml; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.common.escape" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.util + -> Export-Package: org.eclipse.mylyn.wikitext.parser.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup,org.eclipse.mylyn.wikitext.parser.outline,org.eclipse.mylyn.wikitext.util" + Unresolved requirement: Import-Package: org.jsoup.select; version="[1.14.0,2.0.0)" + -> Export-Package: org.jsoup.select; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="javax.annotation,org.jsoup.nodes" + Unresolved requirement: Import-Package: com.google.common.escape; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.escape; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.common.base,com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser + -> Export-Package: org.eclipse.mylyn.wikitext.parser; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: com.google.common.base + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="32.1.2.jre"; version="32.1.2"; uses:="javax.annotation" + com.google.guava [622] + Unresolved requirement: Import-Package: javax.annotation; version="[3.0.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Require-Bundle: com.google.guava; bundle-version="30.1.0" + -> Bundle-SymbolicName: com.google.guava; bundle-version="32.1.2.jre" + Unresolved requirement: Require-Bundle: org.eclipse.mylyn.wikitext.markdown; bundle-version="3.0.40" + -> Bundle-SymbolicName: org.eclipse.mylyn.wikitext.markdown; bundle-version="3.0.42.20220107230029" + org.eclipse.mylyn.wikitext.markdown [369] + Unresolved requirement: Import-Package: com.google.common.collect; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.collect; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.common.base,com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.phrase; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.phrase; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.util; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="javax.xml.stream,org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: com.google.common.base; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown + -> Export-Package: org.eclipse.mylyn.wikitext.markdown; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.48.202308291007"; version="3.0.48"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup" + org.eclipse.mylyn.wikitext.markdown [860] + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.util; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="javax.xml.stream,org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.builder; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.builder; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.builder.event,org.eclipse.mylyn.wikitext.parser.outline,org.eclipse.mylyn.wikitext.util" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.util" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.builder,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.token + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.token; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.validation; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.validation; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: com.google.common.base; version="[31.1.0,33.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="32.1.2.jre"; version="32.1.2"; uses:="javax.annotation" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.phrase; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.phrase; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.token; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.token; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.util + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.markdown.internal.block,org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.phrase + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.phrase; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup,org.eclipse.mylyn.wikitext.parser.markup.token" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.block + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.block; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.46.202301111837"; version="3.0.46"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.markdown.internal.util,org.eclipse.mylyn.wikitext.parser.markup" + org.eclipse.mylyn.wikitext.markdown [861] + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.builder,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.token + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.token; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.phrase + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.phrase; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup,org.eclipse.mylyn.wikitext.parser.markup.token" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.util; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="javax.xml.stream,org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.util + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.markdown.internal.block,org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown + -> Export-Package: org.eclipse.mylyn.wikitext.markdown; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.48.202308291007"; version="3.0.48"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: com.google.common.base; version="[31.1.0,32.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="31.1.0.jre"; version="31.1.0"; uses:="javax.annotation" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.builder; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.builder; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.builder.event,org.eclipse.mylyn.wikitext.parser.outline,org.eclipse.mylyn.wikitext.util" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.token; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.token; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.validation; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.validation; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.phrase; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.phrase; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.util" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.block + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.block; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.46.202301111837"; version="3.0.46"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.markdown.internal.util,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.util" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.token; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.token; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.validation; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.validation; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.builder; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.builder; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.builder.event,org.eclipse.mylyn.wikitext.parser.outline,org.eclipse.mylyn.wikitext.util" + Unresolved requirement: Import-Package: com.google.gson; version="2.7.0" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.8.9.v20220111-1409"; version="2.8.9"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Require-Bundle: org.eclipse.lsp4j.jsonrpc; bundle-version="[0.19.0,0.20.0)" + -> Bundle-SymbolicName: org.eclipse.lsp4j.jsonrpc; bundle-version="0.19.0.v20221118-0359" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.lsp4e 4 0 2024-04-25 11:26:26.988 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.lsp4e [843] + Unresolved requirement: Require-Bundle: org.eclipse.lsp4j; bundle-version="[0.19.0,0.20.0)" + -> Bundle-SymbolicName: org.eclipse.lsp4j; bundle-version="0.19.0.v20221118-0359" + org.eclipse.lsp4j [846] + Unresolved requirement: Import-Package: com.google.gson; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + com.google.gson [620] + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.messages; version="[0.19.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.messages; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc.validation" + org.eclipse.lsp4j.jsonrpc [848] + Unresolved requirement: Import-Package: com.google.gson.internal; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.internal; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; x-internal:="true"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc + -> Export-Package: org.eclipse.lsp4j.jsonrpc; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + org.eclipse.lsp4j.jsonrpc [847] + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.messages + -> Export-Package: org.eclipse.lsp4j.jsonrpc.messages; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc.validation" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json.adapters + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + org.eclipse.lsp4j.jsonrpc [849] + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json.adapters + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.services + -> Export-Package: org.eclipse.lsp4j.jsonrpc.services; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.json" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc + -> Export-Package: org.eclipse.lsp4j.jsonrpc; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.messages + -> Export-Package: org.eclipse.lsp4j.jsonrpc.messages; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc.validation" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.validation + -> Export-Package: org.eclipse.lsp4j.jsonrpc.validation; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.services + -> Export-Package: org.eclipse.lsp4j.jsonrpc.services; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.json" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.validation + -> Export-Package: org.eclipse.lsp4j.jsonrpc.validation; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.validation; version="[0.19.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.validation; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; version="[0.19.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.common.base; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + com.google.guava [1027] + Unresolved requirement: Import-Package: com.google.errorprone.annotations; version="[3.0.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Import-Package: com.google.errorprone.annotations.concurrent; version="[3.0.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Import-Package: javax.crypto; version="[3.0.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Import-Package: javax.crypto.spec; version="[3.0.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Import-Package: org.checkerframework.checker.nullness.qual; version="[3.5.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Import-Package: org.eclipse.lsp4j + -> Export-Package: org.eclipse.lsp4j; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.14.0.v20220526-1518"; version="0.14.0.v20220526-1518"; uses:="com.google.gson.annotations,org.eclipse.lsp4j.adapters,org.eclipse.lsp4j.jsonrpc.messages,org.eclipse.lsp4j.jsonrpc.validation,org.eclipse.xtext.xbase.lib" + org.eclipse.lsp4j [1069] + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.8.9,2.9.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.8.9.v20220111-1409"; version="2.8.9" + com.google.gson [1026] + Unresolved requirement: Import-Package: com.google.gson.internal.sql; version="[2.8.0,3.0.0)" + -> Export-Package: com.google.gson.internal.sql; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; x-internal:="true"; uses:="com.google.gson,com.google.gson.internal.bind" + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.8.0,3.0.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.8.0,3.0.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: com.google.gson.internal.reflect; version="[2.8.0,3.0.0)" + -> Export-Package: com.google.gson.internal.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; x-internal:="true"; uses:="com.google.gson" + Unresolved requirement: Import-Package: com.google.gson.internal.bind.util; version="[2.8.0,3.0.0)" + -> Export-Package: com.google.gson.internal.bind.util; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; x-internal:="true" + Unresolved requirement: Import-Package: com.google.gson.internal; version="[2.8.0,3.0.0)" + -> Export-Package: com.google.gson.internal; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; x-internal:="true"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.8.9,2.9.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.8.9.v20220111-1409"; version="2.8.9" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.messages; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.messages; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc.validation" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.validation; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.validation; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.services; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.services; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="org.eclipse.lsp4j,org.eclipse.lsp4j.adapters,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages,org.eclipse.lsp4j.jsonrpc.services" + org.eclipse.lsp4j [844] + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.util + -> Export-Package: org.eclipse.lsp4j.util; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j" + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.validation; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.validation; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j + -> Export-Package: org.eclipse.lsp4j; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.14.0.v20220526-1518"; version="0.14.0.v20220526-1518"; uses:="com.google.gson.annotations,org.eclipse.lsp4j.adapters,org.eclipse.lsp4j.jsonrpc.messages,org.eclipse.lsp4j.jsonrpc.validation,org.eclipse.xtext.xbase.lib" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.adapters + -> Export-Package: org.eclipse.lsp4j.adapters; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j,org.eclipse.lsp4j.jsonrpc.messages" + org.eclipse.lsp4j [845] + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.9.1,2.11.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j + -> Export-Package: org.eclipse.lsp4j; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.14.0.v20220526-1518"; version="0.14.0.v20220526-1518"; uses:="com.google.gson.annotations,org.eclipse.lsp4j.adapters,org.eclipse.lsp4j.jsonrpc.messages,org.eclipse.lsp4j.jsonrpc.validation,org.eclipse.xtext.xbase.lib" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.services + -> Export-Package: org.eclipse.lsp4j.services; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="org.eclipse.lsp4j,org.eclipse.lsp4j.adapters,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages,org.eclipse.lsp4j.jsonrpc.services" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.validation; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.validation; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.messages; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.messages; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc.validation" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.util + -> Export-Package: org.eclipse.lsp4j.util; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.services; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.services; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.json" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.messages; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.messages; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc.validation" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.services; version="[0.21.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.services; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.json" + Unresolved requirement: Import-Package: com.google.gson; version="[2.8.9,2.9.0)" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.8.9.v20220111-1409"; version="2.8.9"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Import-Package: com.google.common.base; version="[14.0.0,31.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.util; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.util; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="org.eclipse.lsp4j" + Unresolved requirement: Import-Package: org.eclipse.xtext.xbase.lib.util; version="[2.24.0,3.0.0)" + -> Export-Package: org.eclipse.xtext.xbase.lib.util; bundle-symbolic-name="org.eclipse.xtext.xbase.lib"; bundle-version="2.29.0.v20221121-0915"; version="2.29.0" + org.eclipse.xtext.xbase.lib [943] + Unresolved requirement: Require-Bundle: com.google.guava; bundle-version="[30.1.0,31.0.0)"; visibility:="reexport" + -> Bundle-SymbolicName: com.google.guava; bundle-version="30.1.0.v20210127-2300" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.services; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.services; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.json" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.adapters; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.adapters; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.8.9,2.9.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.8.9.v20220111-1409"; version="2.8.9" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; version="[0.14.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json.adapters; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.xtext.xbase.lib; version="[2.24.0,3.0.0)" + -> Export-Package: org.eclipse.xtext.xbase.lib; bundle-symbolic-name="org.eclipse.xtext.xbase.lib"; bundle-version="2.29.0.v20221121-0915"; version="2.29.0" + Unresolved requirement: Import-Package: com.google.gson.reflect; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson.reflect; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc; version="[0.19.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: com.google.gson.annotations; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson.annotations; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.services; version="[0.19.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.services; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.json" + Unresolved requirement: Import-Package: org.eclipse.xtext.xbase.lib.util; version="[2.28.0,3.0.0)" + -> Export-Package: org.eclipse.xtext.xbase.lib.util; bundle-symbolic-name="org.eclipse.xtext.xbase.lib"; bundle-version="2.29.0.v20221121-0915"; version="2.29.0" + Unresolved requirement: Import-Package: com.google.gson.stream; version="[2.9.1,2.10.0)" + -> Export-Package: com.google.gson.stream; bundle-symbolic-name="com.google.gson"; bundle-version="2.9.1.v20220915-1632"; version="2.9.1" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.adapters + -> Export-Package: org.eclipse.lsp4j.adapters; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.21.0.v20230517-2120"; version="0.21.0"; uses:="com.google.gson,com.google.gson.reflect,com.google.gson.stream,org.eclipse.lsp4j,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.services + -> Export-Package: org.eclipse.lsp4j.services; bundle-symbolic-name="org.eclipse.lsp4j"; bundle-version="0.21.1.v20230829-0012"; version="0.21.1"; uses:="org.eclipse.lsp4j,org.eclipse.lsp4j.adapters,org.eclipse.lsp4j.jsonrpc.json,org.eclipse.lsp4j.jsonrpc.messages,org.eclipse.lsp4j.jsonrpc.services" + Unresolved requirement: Import-Package: org.eclipse.xtext.xbase.lib; version="[2.28.0,3.0.0)" + -> Export-Package: org.eclipse.xtext.xbase.lib; bundle-symbolic-name="org.eclipse.xtext.xbase.lib"; bundle-version="2.29.0.v20221121-0915"; version="2.29.0" + Unresolved requirement: Import-Package: org.eclipse.lsp4j.jsonrpc.json; version="[0.19.0,1.0.0)" + -> Export-Package: org.eclipse.lsp4j.jsonrpc.json; bundle-symbolic-name="org.eclipse.lsp4j.jsonrpc"; bundle-version="0.19.0.v20221118-0359"; version="0.19.0"; uses:="com.google.gson,org.eclipse.lsp4j.jsonrpc,org.eclipse.lsp4j.jsonrpc.messages" + Unresolved requirement: Require-Bundle: org.eclipse.mylyn.wikitext; bundle-version="3.0.40" + -> Bundle-SymbolicName: org.eclipse.mylyn.wikitext; bundle-version="3.0.42.20220107230029" + org.eclipse.mylyn.wikitext [361] + Unresolved requirement: Import-Package: org.jsoup; version="[1.14.0,2.0.0)" + -> Export-Package: org.jsoup; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="javax.annotation,javax.net.ssl,org.jsoup.nodes,org.jsoup.parser,org.jsoup.safety" + org.jsoup [1113] + Unresolved requirement: Import-Package: javax.annotation.meta; resolution:="optional" + Unresolved requirement: Import-Package: com.google.common.collect; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.collect; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.common.base,com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.builder + -> Export-Package: org.eclipse.mylyn.wikitext.parser.builder; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.builder.event,org.eclipse.mylyn.wikitext.parser.outline,org.eclipse.mylyn.wikitext.util" + org.eclipse.mylyn.wikitext [851] + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.builder.event + -> Export-Package: org.eclipse.mylyn.wikitext.parser.builder.event; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser" + Unresolved requirement: Import-Package: com.google.common.base; version="[31.1.0,32.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="31.1.0.jre"; version="31.1.0"; uses:="javax.annotation" + com.google.guava [623] + Unresolved requirement: Import-Package: javax.annotation; version="[3.0.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Import-Package: com.google.common.xml; version="[31.1.0,32.0.0)" + -> Export-Package: com.google.common.xml; bundle-symbolic-name="com.google.guava"; bundle-version="31.1.0.jre"; version="31.1.0"; uses:="com.google.common.escape" + Unresolved requirement: Import-Package: org.jsoup; version="[1.15.0,2.0.0)" + -> Export-Package: org.jsoup; bundle-symbolic-name="org.jsoup"; bundle-version="1.15.3"; version="1.15.3"; uses:="javax.annotation,javax.net.ssl,org.jsoup.nodes,org.jsoup.parser,org.jsoup.safety" + org.jsoup [978] + Unresolved requirement: Import-Package: javax.annotation.meta; resolution:="optional" + Unresolved requirement: Import-Package: org.jsoup.internal + -> Export-Package: org.jsoup.internal; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; x-internal:="true"; uses:="javax.annotation,javax.annotation.meta" + Unresolved requirement: Import-Package: org.jsoup + -> Export-Package: org.jsoup; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="javax.annotation,javax.net.ssl,org.jsoup.nodes,org.jsoup.parser,org.jsoup.safety" + Unresolved requirement: Import-Package: org.jsoup.parser + -> Export-Package: org.jsoup.parser; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="javax.annotation,org.jsoup.nodes" + Unresolved requirement: Import-Package: org.jsoup.helper + -> Export-Package: org.jsoup.helper; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="javax.annotation,javax.net.ssl,javax.xml.parsers,org.jsoup,org.jsoup.nodes,org.jsoup.parser,org.jsoup.select,org.w3c.dom" + Unresolved requirement: Import-Package: org.jsoup.safety + -> Export-Package: org.jsoup.safety; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="org.jsoup.nodes" + Unresolved requirement: Import-Package: org.jsoup.select + -> Export-Package: org.jsoup.select; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="javax.annotation,org.jsoup.nodes" + Unresolved requirement: Import-Package: org.jsoup.select; version="[1.15.0,2.0.0)" + -> Export-Package: org.jsoup.select; bundle-symbolic-name="org.jsoup"; bundle-version="1.15.3"; version="1.15.3"; uses:="javax.annotation,org.jsoup.nodes" + Unresolved requirement: Import-Package: com.google.common.collect; version="[31.1.0,32.0.0)" + -> Export-Package: com.google.common.collect; bundle-symbolic-name="com.google.guava"; bundle-version="31.1.0.jre"; version="31.1.0"; uses:="com.google.common.base,javax.annotation" + Unresolved requirement: Import-Package: com.google.common.escape; version="[31.1.0,32.0.0)" + -> Export-Package: com.google.common.escape; bundle-symbolic-name="com.google.guava"; bundle-version="31.1.0.jre"; version="31.1.0"; uses:="com.google.common.base,javax.annotation" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.outline + -> Export-Package: org.eclipse.mylyn.wikitext.parser.outline; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.block + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.block; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser.markup,org.eclipse.mylyn.wikitext.parser.outline" + Unresolved requirement: Import-Package: org.jsoup.nodes; version="[1.15.0,2.0.0)" + -> Export-Package: org.jsoup.nodes; bundle-symbolic-name="org.jsoup"; bundle-version="1.15.3"; version="1.15.3"; uses:="javax.annotation,org.jsoup,org.jsoup.helper,org.jsoup.parser,org.jsoup.select" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.internal.parser.html + -> Export-Package: org.eclipse.mylyn.wikitext.internal.parser.html; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser,org.jsoup.nodes,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.util" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.token + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.token; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.jsoup.internal; version="[1.15.0,2.0.0)" + -> Export-Package: org.jsoup.internal; bundle-symbolic-name="org.jsoup"; bundle-version="1.15.3"; version="1.15.3"; uses:="javax.annotation,javax.annotation.meta" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.util + -> Export-Package: org.eclipse.mylyn.wikitext.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="javax.xml.stream,org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.css + -> Export-Package: org.eclipse.mylyn.wikitext.parser.css; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.internal.util + -> Export-Package: org.eclipse.mylyn.wikitext.internal.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; x-internal:="true" + Unresolved requirement: Import-Package: org.jsoup.internal; version="[1.14.0,2.0.0)" + -> Export-Package: org.jsoup.internal; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; x-internal:="true"; uses:="javax.annotation,javax.annotation.meta" + Unresolved requirement: Import-Package: org.jsoup.nodes; version="[1.14.0,2.0.0)" + -> Export-Package: org.jsoup.nodes; bundle-symbolic-name="org.jsoup"; bundle-version="1.15.3"; version="1.15.3"; uses:="javax.annotation,org.jsoup,org.jsoup.helper,org.jsoup.parser,org.jsoup.select" + Unresolved requirement: Import-Package: com.google.common.base; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + Unresolved requirement: Import-Package: com.google.common.xml; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.xml; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.common.escape" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.util + -> Export-Package: org.eclipse.mylyn.wikitext.parser.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup,org.eclipse.mylyn.wikitext.parser.outline,org.eclipse.mylyn.wikitext.util" + Unresolved requirement: Import-Package: org.jsoup.select; version="[1.14.0,2.0.0)" + -> Export-Package: org.jsoup.select; bundle-symbolic-name="org.jsoup"; bundle-version="1.14.3.v20211012-1727"; version="1.14.3"; uses:="javax.annotation,org.jsoup.nodes" + Unresolved requirement: Import-Package: com.google.common.escape; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.escape; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.common.base,com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser + -> Export-Package: org.eclipse.mylyn.wikitext.parser; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: com.google.common.base + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="32.1.2.jre"; version="32.1.2"; uses:="javax.annotation" + com.google.guava [622] + Unresolved requirement: Import-Package: javax.annotation; version="[3.0.0,4.0.0)"; resolution:="optional" + Unresolved requirement: Require-Bundle: com.google.guava; bundle-version="30.1.0" + -> Bundle-SymbolicName: com.google.guava; bundle-version="32.1.2.jre" + Unresolved requirement: Require-Bundle: org.eclipse.mylyn.wikitext.markdown; bundle-version="3.0.40" + -> Bundle-SymbolicName: org.eclipse.mylyn.wikitext.markdown; bundle-version="3.0.42.20220107230029" + org.eclipse.mylyn.wikitext.markdown [369] + Unresolved requirement: Import-Package: com.google.common.collect; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.collect; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.common.base,com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.phrase; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.phrase; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.util; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="javax.xml.stream,org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: com.google.common.base; version="[30.1.0,31.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="30.1.0.v20210127-2300"; version="30.1.0"; uses:="com.google.errorprone.annotations,org.checkerframework.checker.nullness.qual" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown + -> Export-Package: org.eclipse.mylyn.wikitext.markdown; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.48.202308291007"; version="3.0.48"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup" + org.eclipse.mylyn.wikitext.markdown [860] + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.util; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="javax.xml.stream,org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.builder; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.builder; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.builder.event,org.eclipse.mylyn.wikitext.parser.outline,org.eclipse.mylyn.wikitext.util" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.util" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.builder,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.token + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.token; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.validation; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.validation; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: com.google.common.base; version="[31.1.0,33.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="32.1.2.jre"; version="32.1.2"; uses:="javax.annotation" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.phrase; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.phrase; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.token; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.token; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.util + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.markdown.internal.block,org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.phrase + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.phrase; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup,org.eclipse.mylyn.wikitext.parser.markup.token" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.block + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.block; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.46.202301111837"; version="3.0.46"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.markdown.internal.util,org.eclipse.mylyn.wikitext.parser.markup" + org.eclipse.mylyn.wikitext.markdown [861] + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.builder,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.token + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.token; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.phrase + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.phrase; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup,org.eclipse.mylyn.wikitext.parser.markup.token" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.util; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="javax.xml.stream,org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.util + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.util; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.markdown.internal.block,org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown + -> Export-Package: org.eclipse.mylyn.wikitext.markdown; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.48.202308291007"; version="3.0.48"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: com.google.common.base; version="[31.1.0,32.0.0)" + -> Export-Package: com.google.common.base; bundle-symbolic-name="com.google.guava"; bundle-version="31.1.0.jre"; version="31.1.0"; uses:="javax.annotation" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.builder; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.builder; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.builder.event,org.eclipse.mylyn.wikitext.parser.outline,org.eclipse.mylyn.wikitext.util" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.token; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.token; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.validation; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.validation; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.phrase; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.phrase; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.util" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.markdown.internal.block + -> Export-Package: org.eclipse.mylyn.wikitext.markdown.internal.block; bundle-symbolic-name="org.eclipse.mylyn.wikitext.markdown"; bundle-version="3.0.46.202301111837"; version="3.0.46"; x-internal:="true"; uses:="org.eclipse.mylyn.wikitext.markdown.internal.util,org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.util" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.markup.token; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.markup.token; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.42.20220107230029"; version="3.0.42"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.validation; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.validation; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser.markup,org.xml.sax" + Unresolved requirement: Import-Package: org.eclipse.mylyn.wikitext.parser.builder; version="[3.0.0,4.0.0)" + -> Export-Package: org.eclipse.mylyn.wikitext.parser.builder; bundle-symbolic-name="org.eclipse.mylyn.wikitext"; bundle-version="3.0.46.202301111837"; version="3.0.46"; uses:="org.eclipse.mylyn.wikitext.parser,org.eclipse.mylyn.wikitext.parser.builder.event,org.eclipse.mylyn.wikitext.parser.outline,org.eclipse.mylyn.wikitext.util" + Unresolved requirement: Import-Package: com.google.gson; version="2.7.0" + -> Export-Package: com.google.gson; bundle-symbolic-name="com.google.gson"; bundle-version="2.8.9.v20220111-1409"; version="2.8.9"; uses:="com.google.gson.internal,com.google.gson.reflect,com.google.gson.stream" + Unresolved requirement: Require-Bundle: org.eclipse.lsp4j.jsonrpc; bundle-version="[0.19.0,0.20.0)" + -> Bundle-SymbolicName: org.eclipse.lsp4j.jsonrpc; bundle-version="0.19.0.v20221118-0359" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.cdt.remote.core 4 0 2024-04-25 11:26:26.990 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.cdt.remote.core [1052] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="1.2.0.202211062329"; osgi.identity="org.eclipse.cdt.remote.core"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.ecf.provider.filetransfer 4 0 2024-04-25 11:26:26.991 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.ecf.provider.filetransfer [1054] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="3.3.0.v20230422-0242"; osgi.identity="org.eclipse.ecf.provider.filetransfer"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.ecf.provider.filetransfer.httpclient5 4 0 2024-04-25 11:26:26.991 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.ecf.provider.filetransfer.httpclient5 [1055] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="1.1.0.v20230423-0417"; osgi.identity="org.eclipse.ecf.provider.filetransfer.httpclient5"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.emf.common.ui 4 0 2024-04-25 11:26:26.992 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.emf.common.ui [1058] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="2.21.0.v20230211-1150"; osgi.identity="org.eclipse.emf.common.ui"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.equinox.p2.discovery.compatibility 4 0 2024-04-25 11:26:26.993 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.equinox.p2.discovery.compatibility [1060] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="1.3.0.v20230322-1009"; osgi.identity="org.eclipse.equinox.p2.discovery.compatibility"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.linuxtools.dataviewers 4 0 2024-04-25 11:26:26.993 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.linuxtools.dataviewers [1062] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="6.1.0.202309052024"; osgi.identity="org.eclipse.linuxtools.dataviewers"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.linuxtools.dataviewers.charts 4 0 2024-04-25 11:26:26.994 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.linuxtools.dataviewers.charts [1063] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="7.0.0.202309052024"; osgi.identity="org.eclipse.linuxtools.dataviewers.charts"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.linuxtools.docker.core 4 0 2024-04-25 11:26:26.995 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.linuxtools.docker.core [1065] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="5.9.0.202211291906"; osgi.identity="org.eclipse.linuxtools.docker.core"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.linuxtools.docker.editor.ls 4 0 2024-04-25 11:26:26.995 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.linuxtools.docker.editor.ls [1067] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="1.0.1.202211291906"; osgi.identity="org.eclipse.linuxtools.docker.editor.ls"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.linuxtools.docker.ui 4 0 2024-04-25 11:26:26.996 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.linuxtools.docker.ui [1068] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="5.9.0.202211291906"; osgi.identity="org.eclipse.linuxtools.docker.ui"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.remote.serial.core 4 0 2024-04-25 11:26:26.996 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.remote.serial.core [1072] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="1.2.0.202211062329"; osgi.identity="org.eclipse.remote.serial.core"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.remote.serial.ui 4 0 2024-04-25 11:26:26.997 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.remote.serial.ui [1073] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="1.1.0.202211062329"; osgi.identity="org.eclipse.remote.serial.ui"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.remote.telnet.core 4 0 2024-04-25 11:26:26.998 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.remote.telnet.core [1074] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="1.2.0.202211062329"; osgi.identity="org.eclipse.remote.telnet.core"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.swtchart.extensions 4 0 2024-04-25 11:26:26.998 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.swtchart.extensions [1076] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="0.13.0.202207230616"; osgi.identity="org.eclipse.swtchart.extensions"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.tm.terminal.connector.local 4 0 2024-04-25 11:26:26.999 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.tm.terminal.connector.local [1077] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="4.8.0.202211062329"; osgi.identity="org.eclipse.tm.terminal.connector.local"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.tm.terminal.connector.process 4 0 2024-04-25 11:26:26.999 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.tm.terminal.connector.process [1078] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="4.9.0.202211062329"; osgi.identity="org.eclipse.tm.terminal.connector.process"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.tm.terminal.connector.ssh 4 0 2024-04-25 11:26:27.000 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.tm.terminal.connector.ssh [1079] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="4.8.100.202303140100"; osgi.identity="org.eclipse.tm.terminal.connector.ssh"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.tm.terminal.connector.telnet 4 0 2024-04-25 11:26:27.001 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.tm.terminal.connector.telnet [1080] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="4.8.0.202211062329"; osgi.identity="org.eclipse.tm.terminal.connector.telnet"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.tm.terminal.control 4 0 2024-04-25 11:26:27.001 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.tm.terminal.control [1081] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="5.5.100.202311142253"; osgi.identity="org.eclipse.tm.terminal.control"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.tm.terminal.view.core 4 0 2024-04-25 11:26:27.002 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.tm.terminal.view.core [1082] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="4.10.100.202309151124"; osgi.identity="org.eclipse.tm.terminal.view.core"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.tm.terminal.view.ui 4 0 2024-04-25 11:26:27.002 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.tm.terminal.view.ui [1083] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="4.11.300.202311142324"; osgi.identity="org.eclipse.tm.terminal.view.ui"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.tm4e.registry 4 0 2024-04-25 11:26:27.003 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.tm4e.registry [1085] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="0.6.5.202308132047"; osgi.identity="org.eclipse.tm4e.registry"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.tm4e.ui 4 0 2024-04-25 11:26:27.003 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.tm4e.ui [1086] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="0.6.1.202211021121"; osgi.identity="org.eclipse.tm4e.ui"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.wst.common.frameworks.ui 4 0 2024-04-25 11:26:27.004 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.wst.common.frameworks.ui [1091] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="1.3.0.v202308161955"; osgi.identity="org.eclipse.wst.common.frameworks.ui"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.wst.common.uriresolver 4 0 2024-04-25 11:26:27.005 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.wst.common.uriresolver [1092] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="1.4.0.v202308161955"; osgi.identity="org.eclipse.wst.common.uriresolver"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.wst.sse.core 4 0 2024-04-25 11:26:27.005 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.wst.sse.core [1093] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="1.2.900.v202211200019"; osgi.identity="org.eclipse.wst.sse.core"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.wst.xml.core 4 0 2024-04-25 11:26:27.006 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.wst.xml.core [1094] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="1.2.700.v202305221615"; osgi.identity="org.eclipse.wst.xml.core"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.xsd 4 0 2024-04-25 11:26:27.006 +!MESSAGE FrameworkEvent ERROR +!STACK 0 +org.osgi.framework.BundleException: Could not resolve module: org.eclipse.xsd [1095] + Another singleton bundle selected: osgi.identity; type="osgi.bundle"; version:Version="2.19.0.v20230614-0642"; osgi.identity="org.eclipse.xsd"; singleton:="true" + + at org.eclipse.osgi.container.Module.start(Module.java:463) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel$2.run(ModuleContainer.java:1847) + at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor$1$1.execute(EquinoxContainerAdaptor.java:136) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1840) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1781) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1745) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1667) + at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1) + at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:234) + at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:345) + +!ENTRY org.eclipse.equinox.app 0 0 2024-04-25 11:26:27.065 +!MESSAGE Product org.eclipse.epp.package.cpp.product could not be found. + +!ENTRY org.eclipse.osgi 4 0 2024-04-25 11:26:38.863 +!MESSAGE Application error +!STACK 1 +java.lang.LinkageError: loader constraint violation: loader org.eclipse.osgi.internal.loader.EquinoxClassLoader @602c167e wants to load abstract class org.eclipse.e4.core.contexts.ContextFunction. A different abstract class with the same name was previously loaded by org.eclipse.osgi.internal.loader.EquinoxClassLoader @194ec3c8. (org.eclipse.e4.core.contexts.ContextFunction is in unnamed module of loader org.eclipse.osgi.internal.loader.EquinoxClassLoader @194ec3c8, parent loader 'platform') + at org.eclipse.e4.core.commands.internal.HandlerServiceImpl.getHandler(HandlerServiceImpl.java:65) + at org.eclipse.ui.internal.commands.CommandPersistence.readCommandsFromRegistry(CommandPersistence.java:196) + at org.eclipse.ui.internal.commands.CommandPersistence.reRead(CommandPersistence.java:461) + at org.eclipse.ui.internal.CommandToModelProcessor.process(CommandToModelProcessor.java:71) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:568) + at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:58) + at org.eclipse.e4.core.internal.di.InjectorImpl.invokeUsingClass(InjectorImpl.java:300) + at org.eclipse.e4.core.internal.di.InjectorImpl.invoke(InjectorImpl.java:234) + at org.eclipse.e4.core.contexts.ContextInjectionFactory.invoke(ContextInjectionFactory.java:173) + at org.eclipse.e4.ui.internal.workbench.ModelAssembler.runProcessor(ModelAssembler.java:715) + at org.eclipse.e4.ui.internal.workbench.ModelAssembler.runProcessors(ModelAssembler.java:649) + at org.eclipse.e4.ui.internal.workbench.ModelAssembler.processModel(ModelAssembler.java:322) + at org.eclipse.e4.ui.internal.workbench.ResourceHandler.loadMostRecentModel(ResourceHandler.java:199) + at org.eclipse.e4.ui.internal.workbench.swt.E4Application.loadApplicationModel(E4Application.java:371) + at org.eclipse.e4.ui.internal.workbench.swt.E4Application.createE4Workbench(E4Application.java:247) + at org.eclipse.ui.internal.Workbench.lambda$3(Workbench.java:573) + at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:342) + at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:551) + at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:156) + at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:152) + at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:203) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:136) + at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:402) + at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:255) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) + at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) + at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) + at java.base/java.lang.reflect.Method.invoke(Method.java:568) + at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:659) + at org.eclipse.equinox.launcher.Main.basicRun(Main.java:596) + at org.eclipse.equinox.launcher.Main.run(Main.java:1467) + at org.eclipse.equinox.launcher.Main.main(Main.java:1440) diff --git a/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version b/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version new file mode 100644 index 0000000..6b2aaa7 --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..30841eb --- /dev/null +++ b/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +encoding=UTF-8 +version=1 diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml index 1a5207d..3023585 100644 --- a/.settings/language.settings.xml +++ b/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -16,10 +16,10 @@ - + - + \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..455a709 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,73 @@ +{ + "files.associations": { + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp", + "csignal": "cpp", + "ctime": "cpp", + "strstream": "cpp", + "bitset": "cpp", + "chrono": "cpp", + "codecvt": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "ratio": "cpp", + "future": "cpp", + "iomanip": "cpp", + "mutex": "cpp", + "semaphore": "cpp", + "stop_token": "cpp", + "thread": "cpp", + "cfenv": "cpp", + "typeindex": "cpp" + } +} \ No newline at end of file diff --git a/API_log/SH_log.cpp b/API_log/SH_log.cpp index 61d06f7..05bb876 100644 --- a/API_log/SH_log.cpp +++ b/API_log/SH_log.cpp @@ -7,7 +7,8 @@ #include #include #include - +#include "../common/SH_global.h" +#include "../common/SH_CommonFunc.hpp" struct _LogParam { pthread_mutex_t *m_mutex; @@ -33,7 +34,8 @@ int log_init(const char* file_name, int log_buf_size, int limit_size) struct timeval now = {0,0}; gettimeofday(&now, NULL); - time_t t = now.tv_sec; + time_t t ; + t = now.tv_sec; struct tm* sys_tm = localtime(&t); char fileTime[20]={0x00}; char fileName[100]={0x00}; @@ -46,6 +48,16 @@ int log_init(const char* file_name, int log_buf_size, int limit_size) void log_write(const char *level, const char* format, ...) { + struct timeval now = {0,0}; + gettimeofday(&now, NULL); + time_t t; + t = now.tv_sec; + struct tm* sys_tm = localtime(&t); + char fileTime[20]={0x00}; + char fileName[100]={0x00}; + int n = snprintf(fileTime, 64, "%d-%02d-%02d.log", sys_tm->tm_year+1900, sys_tm->tm_mon+1, sys_tm->tm_mday); + sprintf(fileName,"%s%s",SOFTWARE_RUN_LOG,fileTime); + strcpy(gLogParam.m_log_full_name, fileName); FILE *fp = fopen(gLogParam.m_log_full_name, "a"); if(fp == NULL) { return; @@ -53,15 +65,10 @@ void log_write(const char *level, const char* format, ...) memset(gLogParam.m_buf, 0, sizeof(char)*gLogParam.m_log_buf_size); - struct timeval now = {0,0}; - gettimeofday(&now, NULL); - time_t t = now.tv_sec; - struct tm* sys_tm = localtime(&t); - pthread_mutex_lock(gLogParam.m_mutex); - int n = snprintf(gLogParam.m_buf, 64, "%d-%02d-%02d %02d:%02d:%02d %s: ", sys_tm->tm_year+1900, sys_tm->tm_mon+1, sys_tm->tm_mday, + n = snprintf(gLogParam.m_buf, 64, "%d-%02d-%02d %02d:%02d:%02d %s: ", sys_tm->tm_year+1900, sys_tm->tm_mon+1, sys_tm->tm_mday, sys_tm->tm_hour, sys_tm->tm_min, sys_tm->tm_sec, level); diff --git a/Cidn-SH b/Cidn-SH new file mode 100644 index 0000000000000000000000000000000000000000..d5a893727f8e4a3a8ab9835f908df8f212d1b627 GIT binary patch literal 1679480 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�X;A(33Rp(0&3C|>fTbJ$b7+i)#pFb`} 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 z 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

UIlr!vs&b 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 literal 0 HcmV?d00001 diff --git a/MD5/md5.cpp b/MD5/md5.cpp new file mode 100644 index 0000000..6c9cd15 --- /dev/null +++ b/MD5/md5.cpp @@ -0,0 +1,304 @@ +#include "md5.h" + +#ifndef HAVE_OPENSSL + + #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) + #define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) + #define H(x, y, z) ((x) ^ (y) ^ (z)) + #define I(x, y, z) ((y) ^ ((x) | ~(z))) + #define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + + #if defined(__i386__) || defined(__x86_64__) || defined(__vax__) + #define SET(n) \ + (*(MD5_u32 *)&ptr[(n) * 4]) + #define GET(n) \ + SET(n) + #else + #define SET(n) \ + (ctx->block[(n)] = \ + (MD5_u32)ptr[(n) * 4] | \ + ((MD5_u32)ptr[(n) * 4 + 1] << 8) | \ + ((MD5_u32)ptr[(n) * 4 + 2] << 16) | \ + ((MD5_u32)ptr[(n) * 4 + 3] << 24)) + #define GET(n) \ + (ctx->block[(n)]) + #endif + + typedef unsigned int MD5_u32; + + typedef struct { + MD5_u32 lo, hi; + MD5_u32 a, b, c, d; + unsigned char buffer[64]; + MD5_u32 block[16]; + } MD5_CTX; + + static void MD5_Init(MD5_CTX *ctx); + static void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); + static void MD5_Final(unsigned char *result, MD5_CTX *ctx); + + static const void *body(MD5_CTX *ctx, const void *data, unsigned long size){ + const unsigned char *ptr; + MD5_u32 a, b, c, d; + MD5_u32 saved_a, saved_b, saved_c, saved_d; + + ptr = (const unsigned char*)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23) + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while (size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; + } + + void MD5_Init(MD5_CTX *ctx){ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; + } + + void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size){ + MD5_u32 saved_lo; + unsigned long used, free; + + saved_lo = ctx->lo; + if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->hi++; + ctx->hi += size >> 29; + used = saved_lo & 0x3f; + + if (used){ + free = 64 - used; + if (size < free) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + memcpy(&ctx->buffer[used], data, free); + data = (unsigned char *)data + free; + size -= free; + body(ctx, ctx->buffer, 64); + } + + if (size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); + } + + void MD5_Final(unsigned char *result, MD5_CTX *ctx){ + unsigned long used, free; + used = ctx->lo & 0x3f; + ctx->buffer[used++] = 0x80; + free = 64 - used; + + if (free < 8) { + memset(&ctx->buffer[used], 0, free); + body(ctx, ctx->buffer, 64); + used = 0; + free = 64; + } + + memset(&ctx->buffer[used], 0, free - 8); + + ctx->lo <<= 3; + ctx->buffer[56] = ctx->lo; + ctx->buffer[57] = ctx->lo >> 8; + ctx->buffer[58] = ctx->lo >> 16; + ctx->buffer[59] = ctx->lo >> 24; + ctx->buffer[60] = ctx->hi; + ctx->buffer[61] = ctx->hi >> 8; + ctx->buffer[62] = ctx->hi >> 16; + ctx->buffer[63] = ctx->hi >> 24; + body(ctx, ctx->buffer, 64); + result[0] = ctx->a; + result[1] = ctx->a >> 8; + result[2] = ctx->a >> 16; + result[3] = ctx->a >> 24; + result[4] = ctx->b; + result[5] = ctx->b >> 8; + result[6] = ctx->b >> 16; + result[7] = ctx->b >> 24; + result[8] = ctx->c; + result[9] = ctx->c >> 8; + result[10] = ctx->c >> 16; + result[11] = ctx->c >> 24; + result[12] = ctx->d; + result[13] = ctx->d >> 8; + result[14] = ctx->d >> 16; + result[15] = ctx->d >> 24; + memset(ctx, 0, sizeof(*ctx)); + } +#else + #include +#endif + + +using namespace std; + +/* Return Calculated raw result(always little-endian), the size is always 16 */ +void md5bin(const void* dat, size_t len, unsigned char out[16]) { + MD5_CTX c; + MD5_Init(&c); + MD5_Update(&c, dat, len); + MD5_Final(out, &c); +} + +static char hb2hex(unsigned char hb) { + hb = hb & 0xF; + return hb < 10 ? '0' + hb : hb - 10 + 'a'; +} + +string md5file(const char* filename){ + printf("file = %s\n",filename); + FILE* file = fopen(filename, "rb"); + string res = md5file(file); + fclose(file); + return res; +} + +string md5file(FILE* file){ + + MD5_CTX c; + MD5_Init(&c); + + char buff[BUFSIZ]; + unsigned char out[16]; + size_t len = 0; + while( ( len = fread(buff ,sizeof(char), BUFSIZ, file) ) > 0) { + MD5_Update(&c, buff, len); + } + MD5_Final(out, &c); + + string res; + for(size_t i = 0; i < 16; ++ i) { + res.push_back(hb2hex(out[i] >> 4)); + res.push_back(hb2hex(out[i])); + } + return res; +} + +string md5(const void* dat, size_t len) { + string res; + unsigned char out[16]; + md5bin(dat, len, out); + for(size_t i = 0; i < 16; ++ i) { + res.push_back(hb2hex(out[i] >> 4)); + res.push_back(hb2hex(out[i])); + } + return res; +} + +std::string md5(std::string dat){ + return md5(dat.c_str(), dat.length()); +} + +/* Generate shorter md5sum by something like base62 instead of base16 or base10. 0~61 are represented by 0-9a-zA-Z */ +string md5sum6(const void* dat, size_t len){ + static const char* tbl = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + string res; + unsigned char out[16]; + md5bin(dat, len, out); + for(size_t i = 0; i < 6; ++i) { + res.push_back(tbl[out[i] % 62]); + } + return res; +} + +std::string md5sum6(std::string dat){ + return md5sum6(dat.c_str(), dat.length() ); +} diff --git a/MD5/md5.h b/MD5/md5.h new file mode 100644 index 0000000..f63ab34 --- /dev/null +++ b/MD5/md5.h @@ -0,0 +1,16 @@ +#ifndef MD5_H +#define MD5_H + +#define _CRT_SECURE_NO_WARNINGS +#include +#include +#include + +std::string md5(std::string dat); +std::string md5(const void* dat, size_t len); +extern std::string md5file(const char* filename); +std::string md5file(FILE* file); +std::string md5sum6(std::string dat); +std::string md5sum6(const void* dat, size_t len); + +#endif // end of MD5_H diff --git a/Makefile b/Makefile index 481d64f..54d941c 100644 --- a/Makefile +++ b/Makefile @@ -2,22 +2,24 @@ TARGET = Cidn-SH OBJ_PATH = $(shell pwd)/debug PREFIX_BIN = -CC = arm-linux-gnueabihf-g++ -STRIP = arm-linux-gnueabihf-strip -INCLUDES = -I../third_party/boost/include \ - -I../third_party/fftw/include \ - -I../third_party/jsoncpp/include \ - -I../third_party/sqlite/include/ +CC = ${CXX} +STRIP = aarch64-poky-linux-strip +INCLUDES = -I../Tools/GatewayThirdParty/boost/include \ + -I../Tools/GatewayThirdParty/fftw/include \ + -I../Tools/GatewayThirdParty/jsoncpp/include \ + -I../Tools/GatewayThirdParty/sqlite/include/ \ + -I../Tools/GatewayThirdParty/curl/include/ \ + -I ./ \ -LIBS = -L../third_party/boost/lib \ - -L../third_party/fftw/lib \ - -L../third_party/ssl/lib \ - -L../third_party/jsoncpp \ - -L../third_party/mqtt1410/lib \ - -L../third_party/sqlite/lib \ - -lsqlite3 -lboost_system -lpthread -lboost_thread -lboost_date_time -lfftw3 -lssl -lcrypto -ljson -lmosquitto +LIBS = -L../Tools/renesas_thirdparty/lib \ + -L../Tools/renesas_thirdparty/lib \ + -L../Tools/renesas_thirdparty/lib \ + -L../Tools/renesas_thirdparty/lib \ + -L../Tools/renesas_thirdparty/lib \ + -L../Tools/renesas_thirdparty/lib \ + -lsqlite3 -lboost_system -lpthread -lboost_thread -lboost_date_time -lfftw3 -ljsoncpp -lmosquitto -lcurl -CFLAGS = -O2 #-Wall -Werror +CFLAGS = -O0 -fpermissive #-Wall -Werror LINKFLAGS = AllDirs :=$(shell ls -R | grep '^\./.*:' | awk '{if( \ diff --git a/calculation/Calculation.cpp b/calculation/Calculation.cpp index 38f9aa5..7893857 100644 --- a/calculation/Calculation.cpp +++ b/calculation/Calculation.cpp @@ -60,7 +60,46 @@ void Calculation::iFFT(int n, fftw_complex* in, fftw_complex* out) fftw_destroy_plan(p); fftw_cleanup(); } +void Calculation::_iFFT( std::vector & vecrealData,std::vector & vecimageData,std::vector & veciFFTData) +{ + fftw_complex *inFFt, *outFFt; + int N = vecrealData.size(); + inFFt = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * N); + outFFt = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * N); + for (int j = 0; j < N; j++) { + inFFt[j][0] = (double)vecrealData[j]; + inFFt[j][1] = (double)vecimageData[j]; + } + iFFT(N,inFFt, outFFt); + for (int i = 0; i < N; i++) { + outFFt[i][0] *= 1./N; + outFFt[i][1] *= 1./N; + veciFFTData.push_back(outFFt[i][0]); + } + fftw_free(inFFt); + fftw_free(outFFt); +} +void Calculation::_FFT(std::vector & vecData, std::vector & vecFFTrealData,std::vector & vecFFTimageData) +{ + fftw_complex *inHilFFt, *outHilFFt; + inHilFFt = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * vecData.size()); + outHilFFt = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * vecData.size()); + + for (int j = 0; j < vecData.size(); j++) { + inHilFFt[j][0] = (double)vecData[j]; + inHilFFt[j][1] = 0; + } + + FFT(vecData.size(), inHilFFt, outHilFFt); + fftShift(outHilFFt, vecData.size()); + for (int i = 0; i < vecData.size(); i++) { + vecFFTrealData.push_back(outHilFFt[i][0]); + vecFFTimageData.push_back(outHilFFt[i][1]); + } + fftw_free(inHilFFt); + fftw_free(outHilFFt); +} //************************************ // Method: caculateAmp_Pha // FullName: Calculation::caculateAmp_Pha @@ -155,6 +194,22 @@ float Calculation::rms(std::vector & vecData) } + +float Calculation::getSample_variance(std::vector a) +{ + float ss = 0; + float s = 0; + float mx = mean(a); + int len = a.size(); + for (int i = 0; i < len; i++) { + s = a[i] - mx; + ss += pow(s, 2); + } + return ss / (len - 1); +} + + + float Calculation::variance(std::vector & vecDropMeanData) { double varianceTemp = 0; @@ -187,7 +242,43 @@ float Calculation::kurtosis(std::vector & vecDropMeanData, float fVarianc tempkurtosis = tempkurtosis / pow(fVariance, 2); return tempkurtosis; } +void Calculation::Hanning(std::vector & vecData,std::vector & vecHanningData) +{ + int N = vecData.size(); + float* w = NULL; + w = (float*)calloc(N, sizeof(float)); + int half, i, idx; + if (N % 2 == 0) + { + half = N / 2; + for (i = 0; i < half; i++) //CALC_HANNING Calculates Hanning window samples. + w[i] = 0.5 * (1 - cos(2 * pi * (i + 1) / (N + 1))); + + + idx = half - 1; + for (i = half; i < N; i++) { + w[i] = w[idx]; + idx--; + } + } + else + { + half = (N + 1) / 2; + for (i = 0; i < half; i++) //CALC_HANNING Calculates Hanning window samples. + w[i] = 0.5 * (1 - cos(2 * pi * (i + 1) / (N + 1))); + + idx = half - 2; + for (i = half; i < N; i++) { + w[i] = w[idx]; + idx--; + } + } + for(int j = 0; j < N;j++){ + vecHanningData.push_back(w[j]); + } + free(w); +} void Calculation::hilbert(std::vector & vecData, std::vector & vecHilbertData, int N) { @@ -253,6 +344,7 @@ void Calculation::hilbert(std::vector & vecData, std::vector & vec vecHilbertData.push_back(amp); // printf("%d %f\n",n,vecHilbertData[n]); } + fftw_free(out); } @@ -289,9 +381,9 @@ void Calculation::FFTSpec(std::vector & vecData, std::vector & vec } -void Calculation::envSpec(std::vector & vecData, std::vector & vecEnvSpecData) +void Calculation::envSpec(std::vector & vecData, std::vector & vecEnvSpecData,int StartFrequency,int EndFrequency) { - std::vector vecDropMeanData; + /*std::vector vecDropMeanData; drop_mean(vecDropMeanData, vecData); std::vector vecHilbertData; @@ -313,5 +405,42 @@ void Calculation::envSpec(std::vector & vecData, std::vector & vec for (int i = vecHilbertData.size() / 2 + 1; i < vecHilbertData.size(); i++) { float ftemp = 2 * sqrt(outHilFFt[i][0] * outHilFFt[i][0] + outHilFFt[i][1] * outHilFFt[i][1]) / vecHilbertData.size(); vecEnvSpecData.push_back(ftemp); - } + }*/ + std::vector vecFFTrealData,vecFFTimageData; + std::vector vecRealData,vecImageData; + std::vector veciFFtData; + std::vector veciFFtData2; + std::vector vecHilbertData; + _FFT(vecData,vecFFTrealData,vecFFTimageData); + for(int i = 0; i < vecFFTrealData.size();i++){ + if(i > StartFrequency && i < EndFrequency){ + vecRealData.push_back(vecFFTrealData.at(i)); + vecImageData.push_back(vecFFTimageData.at(i)); + }else{ + vecRealData.push_back(0); + vecImageData.push_back(0); + } + } + _iFFT(vecRealData,vecImageData,veciFFtData); + for(int j = 0; j < veciFFtData.size();j++){ + veciFFtData2.push_back(veciFFtData[j]*2); + } + hilbert(veciFFtData2,vecHilbertData,veciFFtData2.size()); + FFTSpec(vecHilbertData, vecEnvSpecData); +} + + +void Calculation::GenerateSin(std::vector & vecData) +{ + int i; + int ft = 1; /* 周期 hz */ + int fs = 12800; /* 采样频率*/ + + /* generate data */ + int data_len = (8*1024); + + for (i = 0; i < data_len; i++) { + vecData.push_back(sin(1000 * 2 *3.1415926*ft*i/fs)); + } + } diff --git a/calculation/Calculation.hpp b/calculation/Calculation.hpp index 3e26611..6d888be 100644 --- a/calculation/Calculation.hpp +++ b/calculation/Calculation.hpp @@ -75,7 +75,8 @@ public: float rms(std::vector & vecData); - + //获取样本方差 + float getSample_variance(std::vector a); //去数据的直流分量 @@ -105,7 +106,8 @@ public: float kurtosis(std::vector & vecDropMeanData, float fVariance); - + //hanning 窗 + void Hanning(std::vector & vecData,std::vector & vecHanningData); //快速傅里叶变换函数 @@ -122,8 +124,8 @@ public: //快速傅里叶逆变换 void iFFT(int n, fftw_complex* in, fftw_complex* out); - - + void _iFFT(std::vector & vecData, std::vector & vecFFTSpecData,std::vector & veciFFTData); + void _FFT(std::vector & vecData, std::vector & vecFFTrealData,std::vector & vecFFTimageData); //通道幅值和相位提取 @@ -139,7 +141,8 @@ public: - + //生成正弦信号 + void GenerateSin(std::vector & vecData); //FFT shift @@ -147,7 +150,7 @@ public: //频谱图数据 void FFTSpec(std::vector & vecData, std::vector & vecFFTSpecData); //包络图谱数据 - void envSpec(std::vector & vecData, std::vector & vecEnvSpecData); + void envSpec(std::vector & vecData, std::vector & vecEnvSpecData,int StartFrequency,int EndFrequency); }; diff --git a/common/Mutex.h b/common/Mutex.h new file mode 100644 index 0000000..ece4f02 --- /dev/null +++ b/common/Mutex.h @@ -0,0 +1,20 @@ +#ifndef _MY_COMM_H_ +#define _MY_COMM_H_ +#include + +class Mutex { +private: + pthread_mutex_t mutex; +public: + Mutex() { mutex = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_init(&mutex,NULL); /*printf("\n pthread_mutex_init \n");*/} + virtual ~Mutex() {pthread_mutex_destroy(&mutex); /*printf("\n pthread_mutex_destroy \n");*/} + void Lock() {pthread_mutex_lock(&mutex); /*printf("\n mutex lock \n");*/} + void UnLock() {pthread_mutex_unlock(&mutex); /*printf("\n mutex unlock \n");*/} +}; +//Mutex g_Mutex; + + + + + +#endif //_MY_COMM_H_ diff --git a/common/SH_CommonFunc.cpp b/common/SH_CommonFunc.cpp index 016dd81..ab7e782 100644 --- a/common/SH_CommonFunc.cpp +++ b/common/SH_CommonFunc.cpp @@ -3,9 +3,353 @@ #include "SH_global.h" #include "SH_CommonFunc.hpp" #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../dbaccess/SH_SqlDB.hpp" +#define ETHTOOL_GLINK 0x0000000a /* Get link status (ethtool_value) */ +#define MAX_WAIT_TIME 1 +#define MAX_NO_PACKETS 1 +#define ICMP_HEADSIZE 8 +#define PACKET_SIZE 4096 +struct timeval tvsend,tvrecv; +struct sockaddr_in dest_addr,recv_addr; +int sockfd; +pid_t pid; +char sendpacket[PACKET_SIZE]; +char recvpacket[PACKET_SIZE]; static boost::mutex s_config_mu; +Mutex g_tDbMutex; +string GetLocalTimeWithMs(void) +{ + string defaultTime = "19700101000000000"; + try + { + struct timeval curTime; + gettimeofday(&curTime, NULL); + int milli = curTime.tv_usec / 1000; + + char buffer[80] = {0}; + struct tm nowTime; + localtime_r(&curTime.tv_sec, &nowTime);//把得到的值存入临时分配的内存中,线程安全 + strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S", &nowTime); + + char currentTime[84] = {0}; + snprintf(currentTime, sizeof(currentTime), "%s%03d", buffer, milli); + + return currentTime; + } + catch(const std::exception& e) + { + return defaultTime; + } + catch (...) + { + return defaultTime; + } +} +int code_convert(const char *from_charset, const char *to_charset, char *inbuf, size_t inlen, + char *outbuf, size_t outlen) { + iconv_t cd; + char **pin = &inbuf; + char **pout = &outbuf; + + cd = iconv_open(to_charset, from_charset); + if (cd == 0) + return -1; + + memset(outbuf, 0, outlen); + + if ((int)iconv(cd, pin, &inlen, pout, &outlen) == -1) + { + iconv_close(cd); + return -1; + } + iconv_close(cd); + *pout = '\0'; + + return 0; +} + +int u2g(char *inbuf, size_t inlen, char *outbuf, size_t outlen) { + return code_convert("utf-8", "gb2312", inbuf, inlen, outbuf, outlen); +} + +int g2u(char *inbuf, size_t inlen, char *outbuf, size_t outlen) { + return code_convert("gb2312", "utf-8", inbuf, inlen, outbuf, outlen); +} + +std::string GBKToUTF8(const std::string& strGBK) +{ + int length = strGBK.size()*2+1; + + char *temp = (char*)malloc(sizeof(char)*length); + + if(g2u((char*)strGBK.c_str(),strGBK.size(),temp,length) >= 0) + { + std::string str_result; + str_result.append(temp); + free(temp); + return str_result; + }else + { + free(temp); + return ""; + } +} + +std::string UTFtoGBK(const char* utf8) +{ + int length = strlen(utf8); + + char *temp = (char*)malloc(sizeof(char)*length); + + if(u2g((char*)utf8,length,temp,length) >= 0) + { + std::string str_result; + str_result.append(temp); + free(temp); + + return str_result; + }else + { + free(temp); + return ""; + } +} + + +void InitGpio(unsigned int gpioN,unsigned int inout) +{ + int fd = 0; + char tmp[100] = {0}; + //打开gpio设备文件 + fd = open("/sys/class/gpio/export", O_WRONLY); + if(-1 == fd) + { + printf("[%s]:[%d] open gpio export file error\r\n", __FUNCTION__, __LINE__); + } + //申请gpio + sprintf(tmp,"%d",gpioN); + if(write(fd, tmp, strlen(tmp)) < 0) + { + printf("write file operation error %s\r\n",tmp); + + } + close(fd); + sleep(1); + //配置gpio方向 +#ifdef G2UL_GATEWAY + char tmp2[100] = {0}; + if(gpioN == 507) + memcpy(tmp2,"P18_3",5); + else if(gpioN == 499) + memcpy(tmp2,"P17_3",5); + else if(gpioN == 496) + memcpy(tmp2,"P17_0",5); + else if(gpioN == 130) + memcpy(tmp2,"P9_0",4); + else if(gpioN == 408) + memcpy(tmp2,"P6_0",4); + else if(gpioN == 363) + memcpy(tmp2,"P0_3",4); + else if(gpioN == 498) + memcpy(tmp2,"P17_2",5); + else if(gpioN == 466) + memcpy(tmp2,"P13_2",5); + else if(gpioN == 488) + memcpy(tmp2,"P16_0",5); + else if(gpioN == 474) + memcpy(tmp2,"P14_2",5); + else if(gpioN == 497) + memcpy(tmp2,"P17_1",5); + else if(gpioN == 409) + memcpy(tmp2,"P6_1",4); + else if(gpioN == 410) + memcpy(tmp2,"P6_2",4); + else if(gpioN == 449) + memcpy(tmp2,"P11_1",5); + else if(gpioN == 489) + memcpy(tmp2,"P16_1",5); + sprintf(tmp,"/sys/class/gpio/%s/direction",tmp2); +#else if IMX6UL_GATEWAY + sprintf(tmp,"/sys/class/gpio/gpio%d/direction",gpioN); +#endif + + print_info("open GPIO = %s\n",tmp); + fd = open(tmp, O_WRONLY); + if(-1 == fd) + { + printf("[%s]:[%d] open gpio direction file error\r\n", __FUNCTION__, __LINE__); + } + + if(inout == 0) + { + print_info("=====InitGpio=====in\n"); + if(-1 == write(fd, "in", sizeof("in"))) + { + print_info("[%s]:[%d] [%d]write operation direction error\r\n", __FUNCTION__, __LINE__,gpioN); + close(fd); + } + } + else if( inout == 1) + { + print_info("=====InitGpio=====out\n"); + if(-1 == write(fd, "out", sizeof("out"))) + { + print_info("[%s]:[%d] [%d]write operation direction error\r\n", __FUNCTION__, __LINE__,gpioN); + close(fd); + } + } + close(fd); +// printf("gpio%d init %d\r\n",gpioN,inout); +} +int gpio_set(unsigned int gpioN,char x) +{ + int fd = 0; + char tmp[100] = {0}; +#ifdef G2UL_GATEWAY + char tmp2[100] = {0}; + if(gpioN == 507) + memcpy(tmp2,"P18_3",5); + else if(gpioN == 499) + memcpy(tmp2,"P17_3",5); + else if(gpioN == 496) + memcpy(tmp2,"P17_0",5); + else if(gpioN == 130) + memcpy(tmp2,"P9_0",4); + else if(gpioN == 408) + memcpy(tmp2,"P6_0",4); + else if(gpioN == 363) + memcpy(tmp2,"P0_3",4); + else if(gpioN == 498) + memcpy(tmp2,"P17_2",5); + else if(gpioN == 466) + memcpy(tmp2,"P13_2",5); + else if(gpioN == 488) + memcpy(tmp2,"P16_0",5); + else if(gpioN == 474) + memcpy(tmp2,"P14_2",5); + else if(gpioN == 497) + memcpy(tmp2,"P17_1",5); + else if(gpioN == 409) + memcpy(tmp2,"P6_1",4); + else if(gpioN == 410) + memcpy(tmp2,"P6_2",4); + else if(gpioN == 449) + memcpy(tmp2,"P11_1",5); + else if(gpioN == 489) + memcpy(tmp2,"P16_1",5); + sprintf(tmp,"/sys/class/gpio/%s/value",tmp2); +#else if IMX6UL_GATEWAY + sprintf(tmp,"/sys/class/gpio/gpio%d/value",gpioN); +#endif +// printf("%s\r\n",tmp); + //print_info("set GPIO = %s\n",tmp); + //打开gpio value文件 + fd = open(tmp, O_WRONLY); + if(-1 == fd) + { + print_red("[%s]:[%d] open gpio export file error\r\n", __FUNCTION__, __LINE__); + return (-1);//exit(1); + } + //设置电平 + if(x) + { + if(-1 == write(fd, "1", sizeof("1"))) + { + print_red("[%s]:[%d] %d write operation value error\r\n", __FUNCTION__, __LINE__,gpioN); + close(fd); + return (-1);//exit(1); + } + } + else + { + if(-1 == write(fd, "0", sizeof("0"))) + { + print_red("[%s]:[%d] %d write operation value error\r\n", __FUNCTION__, __LINE__,gpioN); + close(fd); + return (-1);//exit(1); + } + } +// printf("gpio%d set %d ok\r\n",gpioN,x); + close(fd); + return 0; +} +int gpio_read(unsigned int gpioN) +{ + int fd = 0; + char value; + + char tmp[100] = {0}; + +#ifdef G2UL_GATEWAY + char tmp2[100] = {0}; + if(gpioN == 507) + memcpy(tmp2,"P18_3",5); + else if(gpioN == 499) + memcpy(tmp2,"P17_3",5); + else if(gpioN == 496) + memcpy(tmp2,"P17_0",5); + else if(gpioN == 130) + memcpy(tmp2,"P9_0",4); + else if(gpioN == 408) + memcpy(tmp2,"P6_0",4); + else if(gpioN == 363) + memcpy(tmp2,"P0_3",4); + else if(gpioN == 498) + memcpy(tmp2,"P17_2",5); + else if(gpioN == 466) + memcpy(tmp2,"P13_2",5); + else if(gpioN == 488) + memcpy(tmp2,"P16_0",5); + else if(gpioN == 474) + memcpy(tmp2,"P14_2",5); + else if(gpioN == 497) + memcpy(tmp2,"P17_1",5); + else if(gpioN == 409) + memcpy(tmp2,"P6_1",4); + else if(gpioN == 410) + memcpy(tmp2,"P6_2",4); + else if(gpioN == 449) + memcpy(tmp2,"P11_1",5); + else if(gpioN == 489) + memcpy(tmp2,"P16_1",5); + sprintf(tmp,"/sys/class/gpio/%s/value",tmp2); +#else if IMX6UL_GATEWAY + sprintf(tmp,"/sys/class/gpio/gpio%d/value",gpioN); +#endif + //打开gpio value文件 + fd = open(tmp, O_RDONLY); + if(-1 == fd) + { + print_red("[%s]:[%d] %d open gpio export file error\r\n", __FUNCTION__, __LINE__,gpioN); + return (-1);//exit(1); + } + //读取 value文件 + if(-1 == read(fd, &value, sizeof(value))) + { + print_red("[%s]:[%d] %d read gpiovalue is fail\r\n", __FUNCTION__, __LINE__,gpioN); + close(fd); + return (-1);//exit(1); + } + close(fd); + //printf("gpio%d get %d\r\n",gpioN,value); + return value; +} int CheckFileVersion(int argc, char** argv) { @@ -36,8 +380,81 @@ int CheckFileVersion(int argc, char** argv) } return 0; } +int config_uart(const char* Port,speed_t speed) +{ + int iFd = open(Port,O_RDWR | O_NOCTTY); + if(iFd < 0) { + return -1; + } + struct termios opt; + tcgetattr(iFd, &opt); + cfsetispeed(&opt, speed); + cfsetospeed(&opt, speed); + if (tcgetattr(iFd, &opt)<0) { + return -1; + } + opt.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + opt.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + opt.c_oflag &= ~(OPOST); + opt.c_cflag &= ~(CSIZE | PARENB | CBAUD); + opt.c_cflag |= (CS8 | speed); + opt.c_cc[VMIN] = 255; + opt.c_cc[VTIME] = 5; + if (tcsetattr(iFd, TCSANOW, &opt)<0) { + return -1; + } + tcflush(iFd,TCIOFLUSH); + return iFd; +} +int write_data(int fd, char *buff, int len) +{ + int ret; + char buf[100]; + ret = write(fd, buff, len); + if (ret < 0) { + return -1; + } + return ret; +} +int read_data(int fd, char *buff, int len, int timeout) +{ + int ret; + struct timeval to; + fd_set rdfds; + + to.tv_sec = 0; + to.tv_usec = timeout; + + FD_ZERO(&rdfds); + FD_SET(fd, &rdfds); + + if (timeout > 0) { + ret = select(fd+1, &rdfds, NULL, NULL, &to); + if (ret <= 0) { + // printf("zigbee doesn't respond!\n"); + return ret; + } + } + + ret = read(fd,buff,len); + if(ret < 0) { + perror("read_data"); + return -1; + } + buff[ret] = '\0'; + return ret; +} +int ModifyMac(char* buff) +{ + FILE *fp = fopen("/opt/system/mac", "w"); + fprintf(fp, buff); + fprintf(fp, "\n"); + fclose(fp); + system("cp /opt/system/mac /opt/system/macbak"); + system("/opt/Cidn/init.sh"); +} std::string GetCurrentTime() { struct tm nowtime; @@ -114,7 +531,50 @@ void GetTimeNet(char* timebuf,int type) } } +// 获取RTC时间 +std::string GetRTC(char* timestamp,int& millisecond) +{ + time_t rtc_timestamp; + struct tm tm; + struct timespec ts; + char rtcTime[100]={0x00}; + int fd = open("/dev/rtc0", O_RDONLY); + if (fd < 0) { + perror("open /dev/rtc0"); + } else { + struct rtc_time rtc_tm; + if (ioctl(fd, RTC_RD_TIME, &rtc_tm) < 0) { + perror("ioctl RTC_RD_TIME"); + } else { + clock_gettime(CLOCK_REALTIME, &ts); + millisecond = (int)(ts.tv_nsec / 1000000); + printf("RTC date/time is %d-%d-%d, %02d:%02d:%02d\n", + rtc_tm.tm_year + 1900, rtc_tm.tm_mon + 1, rtc_tm.tm_mday, + rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); + sprintf(rtcTime,"%d-%d-%d, %02d:%02d:%02d",rtc_tm.tm_year + 1900, rtc_tm.tm_mon + 1, rtc_tm.tm_mday, + rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); + // 将rtc_time结构体转换为time_t时间戳 + tm.tm_year = rtc_tm.tm_year; + tm.tm_mon = rtc_tm.tm_mon; + tm.tm_mday = rtc_tm.tm_mday; + tm.tm_hour = rtc_tm.tm_hour; + tm.tm_min = rtc_tm.tm_min; + tm.tm_sec = rtc_tm.tm_sec; + tm.tm_isdst = -1; // 不使用夏令时 + + rtc_timestamp = mktime(&tm); + + if (rtc_timestamp == -1) { + perror("mktime"); + } + printf("RTC timestamp is %ld,millisecond = %d\n", rtc_timestamp,millisecond); + sprintf(timestamp,"%ld",rtc_timestamp); + } + } + close(fd); + return std::string(rtcTime); +} void GetTime_(char time_buff[],TIME_SIZE len) { int i = sizeof(time_buff); @@ -142,24 +602,218 @@ std::string ReadStrByOpt(std::string filename, std::string config, std::string o is.close(); return value; } -std::vector ReadStrByOpt(std::string filename,std::string& strUpdataFileName) +std::vector ReadStrUpdate(std::string filename) { boost::mutex::scoped_lock lock(s_config_mu); Json::Value root,hwVersion; Json::Reader reader; std::vector value; + std::vector vecDataNodeUpdate; + DataNodeUpdate datanodeUpdate; std::fstream is; is.open(filename.c_str(), std::ios::in); if (reader.parse(is, root)) { - hwVersion = root["hw_vesion"]; - strUpdataFileName = root["fw_name"].asString(); - } - for(int i = 0; i < hwVersion.size();i++){ - value.push_back(hwVersion[i].asString()); - } + print_info("root = %d\n",root.size()); + for(int i = 0; i < root.size();i++){ + hwVersion = root[i]["hw_vesion"]; + for(int i = 0; i < hwVersion.size();i++){ + datanodeUpdate.hwVersion.push_back(hwVersion[i].asString()); + } + datanodeUpdate.strUpdataFileName = root[i]["fw_name"].asString(); + datanodeUpdate.strSoftVersion = root[i]["sf_vesion"].asString(); + print_info("strUpdataFileName = %s,strSoftVersion = %s\n",datanodeUpdate.strUpdataFileName.c_str(),\ + datanodeUpdate.strSoftVersion.c_str()); + vecDataNodeUpdate.push_back(datanodeUpdate); + } + } is.close(); - return value; + + return vecDataNodeUpdate; +} +void ReadStrConfig(std::string filename) +{ + Json::Value root,gateWay,dataNode; + std::fstream is; + Json::Reader reader; + is.open(filename.c_str(), std::ios::in); + string zigbeeChannel; + if (reader.parse(is, root)) { + gateWay = root["gateWay"]; + dataNode = root["dataNodeArray"]; + print_info("dataNode = %d\n",dataNode.size()); + for(int i = 0; i < dataNode.size();i++){ + string softVersion = dataNode[i]["softVersion"].asString(); + string bpNo = dataNode[i]["bpNo"].asString(); + print_info("bpNo = %s\n",bpNo.c_str()); + string wakeupTime = dataNode[i]["wakeupTime"].asString(); + int viff = dataNode[i]["viff"].asInt(); + string StaticTime = dataNode[i]["StaticTime"].asString(); + int configFlag = dataNode[i]["configFlag"].asInt(); + int rangeValue = dataNode[i]["range"].asInt(); + int updateValue = dataNode[i]["update"].asInt(); + string zigbeeLongAddr = dataNode[i]["zigbeeLongAddr"].asString(); + int accFlag = dataNode[i]["accFlag"].asInt(); + print_info("accFlag = %d\n",accFlag); + int temTopFlag = dataNode[i]["temTopFlag"].asInt(); + string startBrands = dataNode[i]["startBrands"].asString(); + int waveInterVal = dataNode[i]["waveInterVal"].asInt(); + string zigbeePanId = dataNode[i]["zigbeePanId"].asString(); + int waveTime = dataNode[i]["waveTime"].asInt(); + int zigbeePower = dataNode[i]["zigbeePower"].asInt(); + int zigbeeRetry = dataNode[i]["zigbeeRetry"].asInt(); + string stopBrands = dataNode[i]["stopBrands"].asString(); + int featureInterVal = dataNode[i]["featureInterVal"].asInt(); + int zigbeeFlag = dataNode[i]["zigbeeFlag"].asInt(); + string zigbeeDesAddr = dataNode[i]["zigbeeDesAddr"].asString(); + print_info("zigbeeDesAddr = %s\n",zigbeeDesAddr.c_str()); + int ZigbeeRetryGap = dataNode[i]["zigbeeRetryGap"].asInt(); + string dataNodeNo = dataNode[i]["dataNodeNo"].asString(); + int initFlag = dataNode[i]["initFlag"].asInt(); + string faultFrequency = dataNode[i]["faultFrequency"].asString(); + int temBotFlag = dataNode[i]["temBotFlag"].asInt(); + string bateryV = dataNode[i]["bateryV"].asString(); + int ACCSampleTime = dataNode[i]["ACCSampleTime"].asInt(); + print_info("ACCSampleTime = %d\n",ACCSampleTime); + string firstPowerTime = dataNode[i]["firstPowerTime"].asString(); + string serialNo = dataNode[i]["serialNo"].asString(); + string zigbeeAddr = dataNode[i]["zigbeeAddr"].asString(); + string productNo = dataNode[i]["productNo"].asString(); + string timeStamp = dataNode[i]["timeStamp"].asString(); + zigbeeChannel = dataNode[i]["zigbeeChannel"].asString(); + int RSSI = dataNode[i]["RSSI"].asInt(); + print_info("RSSI = %d\n",RSSI); + string hardVersion = dataNode[i]["hardVersion"].asString(); + string envelopeBandPass = dataNode[i]["envelopeBandPass"].asString(); + int samplingRate = dataNode[i]["samplingRate"].asInt(); + string dataNodeName = dataNode[i]["dataNodeName"].asString(); + int status = dataNode[i]["status"].asInt(); + int EquipSta = dataNode[i]["equipSta"].asInt(); + char insertSql[1024] = { 0 }; + char whereCon[100]={0x00}; + sprintf(whereCon,"dataNodeNo = '%s'",dataNodeNo.c_str()); + int rows = sql_ctl->GetTableRows(T_SENSOR_INFO(TNAME), whereCon); + if(rows > 0) + continue; + sprintf(insertSql, "'%s','%s','%d','%d','%d','%d','%d','%d',\ + '%s','%s','%s','%s','%s','%d',\ + '%d','%d','%d','%s','%d','%s',\ + '%s','%d','%d','%d','%s','%d','%s','%s',\ + '%s','%d','%s','%s','%s',\ + '%d','%d','%d','%d','%d','%s','%d','%d','%d','0','0,0'", + dataNodeNo.c_str(), dataNodeName.c_str(), initFlag, accFlag, zigbeeFlag, temTopFlag, temBotFlag,EquipSta,\ + hardVersion.c_str(), softVersion.c_str(), bpNo.c_str(), serialNo.c_str(), firstPowerTime.c_str(), atoi(wakeupTime.c_str()),\ + atoi(StaticTime.c_str()),waveTime,atoi(bateryV.c_str()),productNo.c_str(),configFlag, startBrands.c_str(), \ + stopBrands.c_str(), featureInterVal, waveInterVal, samplingRate,"",rangeValue, envelopeBandPass.c_str(), faultFrequency.c_str(),\ + zigbeePanId.c_str(), atoi(zigbeeChannel.c_str()), zigbeeAddr.c_str(), zigbeeLongAddr.c_str(), zigbeeDesAddr.c_str(), \ + zigbeePower,zigbeeRetry,ZigbeeRetryGap,ACCSampleTime,status, timeStamp.c_str(),viff,RSSI,updateValue); + sql_ctl->InsertData(T_SENSOR_INFO(TNAME), insertSql); + } + + /*WriteStr2Config(SERVERCONFIG, "Server", "localServerIpAddress", gateWay["Server"]["localServerIpAddress"].asString()); + WriteStr2Config(SERVERCONFIG, "Server", "localServerPort", gateWay["Server"]["localServerPort"].asString()); + WriteStr2Config(SERVERCONFIG, "Server", "CommMode", gateWay["Server"]["CommMode"].asString()); + WriteStr2Config(SERVERCONFIG, "Server", "UserName", gateWay["Server"]["UserName"].asString()); + WriteStr2Config(SERVERCONFIG, "Server", "Password", gateWay["Server"]["Password"].asString()); + + WriteStr2Config(NETWORKCONFIG, "Net", "dnsName", gateWay["Net"]["dnsName"].asString()); + WriteStr2Config(NETWORKCONFIG, "Net", "networkPortStatus", gateWay["Net"]["networkPortStatus"].asString()); + WriteStr2Config(NETWORKCONFIG, "Net", "gateway", gateWay["Net"]["gateway"].asString()); + WriteStr2Config(NETWORKCONFIG, "Net", "subnetMask", gateWay["Net"]["subnetMask"].asString()); + WriteStr2Config(NETWORKCONFIG, "Net", "ipAddress", gateWay["Net"]["ipAddress"].asString()); + WriteStr2Config(NETWORKCONFIG, "Net", "hostName", gateWay["Net"]["hostName"].asString()); + + WriteStr2Config(ZIGBEECONFIG, "Zigbee", "channel", zigbeeChannel);*/ + }else{ + print_info("parse error\n"); + } + is.close(); +} +int UpdataDataNodeConfig(std::string filename) +{ + vector vecDataNode; //声明一个字符串向量 + //以读入方式打开文件 + ifstream csv_data(filename, ios::in); + int iRet = 0; + if (!csv_data.is_open()) + { + cout << "Error: opening file fail" << endl; + return -1; + } + else { + string line; + + vector words; //声明一个字符串向量 + string word; + + DataNodeInfo dataNode; + // ------------读取数据----------------- + // 读取标题行 + getline(csv_data, line); + + + istringstream sin; + // 按行读取数据 + while (getline(csv_data, line)) + { + words.clear(); + sin.clear(); + sin.str(line); + while (getline(sin, word, ',')) + { + cout << word << endl; + words.push_back(word); + + } + string mac = words[1]; + if(mac != GlobalConfig::MacAddr_G){ + iRet = -2; + break; + } + dataNode.ZigbeeLongAddr = words[7]; + dataNode.FeatureInterVal = atoi(words[14].c_str()); + dataNode.WaveInterVal = atoi(words[15].c_str()); + dataNode.SamplingRate = atoi(words[16].c_str()); + print_info("words[17] = %s\n",words[17].c_str()); + + if(words[17].find("8g") != string::npos){ + dataNode.Range = 0; + }else if(words[17].find("16g") != string::npos){ + dataNode.Range = 1; + }else if(words[17].find("32g") != string::npos){ + dataNode.Range = 2; + }else if(words[17].find("64g") != string::npos){ + dataNode.Range = 3; + }else if(words[17].find("50g") != string::npos){ + dataNode.Range = 0; + } + + dataNode.ACCSampleTime = atoi(words[18].c_str()); + int update = atoi(words[20].c_str()); + if(update == 1) + vecDataNode.push_back(dataNode); + } + csv_data.close(); + } + + char whereCon[1024] = {0}; + char updateSql[1024] = { 0 }; + if(vecDataNode.size() > 0){ + for(int i = 0; i < vecDataNode.size();i++){ + sprintf(updateSql, "featureInterVal='%d',waveInterVal='%d',range='%d',samplingRate='%d',AccSampleTime = '%d',UpdateFlag = 0", + vecDataNode[i].FeatureInterVal, vecDataNode[i].WaveInterVal,vecDataNode[i].Range,\ + vecDataNode[i].SamplingRate,vecDataNode[i].ACCSampleTime); + sprintf(whereCon, "dataNodeNo='%s'", vecDataNode[i].ZigbeeLongAddr.c_str()); + + int iRet = sql_ctl->UpdateTableData(T_SENSOR_INFO(TNAME), updateSql, whereCon); + memset(whereCon,0x00,sizeof(whereCon)); + memset(updateSql,0x00,sizeof(updateSql)); + } + iRet = vecDataNode.size() ; + }else{ + iRet = -3; + } + return iRet; } int WriteStr2Config(std::string filename, std::string config, std::string option, std::string value, bool listable) { @@ -197,7 +851,7 @@ int WriteStr2Config(std::string filename, std::string config, std::string option } -std::string GetLocalMac() +std::string GetLocalMac(const char* net) { int sock_mac; struct ifreq ifr_mac; @@ -208,7 +862,7 @@ std::string GetLocalMac() return ""; } memset(&ifr_mac,0,sizeof(ifr_mac)); - strncpy(ifr_mac.ifr_name, "eth0", sizeof(ifr_mac.ifr_name)-1); + strncpy(ifr_mac.ifr_name, net, sizeof(ifr_mac.ifr_name)-1); if( (ioctl( sock_mac, SIOCGIFHWADDR, &ifr_mac)) < 0) { printf("mac ioctl error/n"); return ""; @@ -219,9 +873,10 @@ std::string GetLocalMac() (unsigned char)ifr_mac.ifr_hwaddr.sa_data[2], (unsigned char)ifr_mac.ifr_hwaddr.sa_data[3], (unsigned char)ifr_mac.ifr_hwaddr.sa_data[4], - (unsigned char)ifr_mac.ifr_hwaddr.sa_data[5]); + (unsigned char)ifr_mac.ifr_hwaddr.sa_data[5]); printf("local mac:%s /n",mac_addr); close( sock_mac ); + LOG_INFO("net : %s,mac:%s\n",net,mac_addr); return std::string( mac_addr ); } @@ -238,7 +893,7 @@ std::string GetGwIp_(const char *eth_name) bzero(&req, sizeof(struct ifreq)); strcpy(req.ifr_name, eth_name); - print_info("eth_name = %s\n",eth_name); + //print_info("eth_name = %s\n",eth_name); ioctl(sockfd, SIOCGIFADDR, &req); host = (struct sockaddr_in*) &req.ifr_addr; close(sockfd); @@ -250,14 +905,43 @@ std::string GetGwIp_(const char *eth_name) std::string IpAddrInit() { + const char *WLAN2 = "wlan2"; const char *WLAN0 = "wlan0"; const char *ETH0 = "eth0"; - std::string strip; - strip = GetGwIp_(ETH0); - if (strip.compare("0.0.0.0") == 0) { - strip = GetGwIp_(WLAN0); + const char *USB0 = "usb0"; + const char *WWAN0 = "wwan0"; + const char *ETH1 = "eth1"; + const char *ETH2 = "eth2"; + std::string strip = ""; + strip = GetGwIp_(WLAN0); + if (strip.compare("0.0.0.0") != 0) { + return strip; } - return strip; + strip = GetGwIp_(WLAN2); + if (strip.compare("0.0.0.0") != 0) { + return strip; + } + strip = GetGwIp_(ETH1); + if (strip.compare("0.0.0.0") != 0) { + return strip; + } + strip = GetGwIp_(ETH2); + if (strip.compare("0.0.0.0") != 0) { + return strip; + } + strip = GetGwIp_(ETH0); + if (strip.compare("0.0.0.0") != 0) { + return strip; + } + strip = GetGwIp_(USB0); + if (strip.compare("0.0.0.0") != 0) { + return strip; + } + strip = GetGwIp_(WWAN0); + if (strip.compare("0.0.0.0") != 0) { + return strip; + } + //return strip; } std::string GetWorkNic() @@ -308,8 +992,8 @@ std::string GetSysInfo() system_custom(getMemFree, chRes); std::string MemFree = std::string(chRes); - float a = boost::lexical_cast(MemFree); - float b = boost::lexical_cast(MemTotal); + float a = atof(MemFree.c_str()); + float b = atof(MemTotal.c_str()); float c = (1 - a/b)*100; const char * getEmmcInfo = "df -h | grep /dev/root"; @@ -323,7 +1007,7 @@ std::string GetSysInfo() Emmcinfo = ClearAllSpace(Emmcinfo); char sysinfo[128] = {0}; - sprintf(sysinfo, "%-13s%-13s%-13s%-13s ", boost::lexical_cast(c).substr(0,4).c_str(), CpuSys.c_str(), CpuUse.c_str(), Emmcinfo.c_str()); + sprintf(sysinfo, "%-13s%-13s%-13s%-13s ", to_string(c).substr(0,4).c_str(), CpuSys.c_str(), CpuUse.c_str(), Emmcinfo.c_str()); return std::string(sysinfo); } @@ -443,10 +1127,8 @@ std::string GetFileContent(std::string filename, int line) //BOOST用正则表达式验证ip地址合法 bool CheckIP(const char *ip) { - using namespace boost::xpressive; - /* 定义正则表达式 */ - cregex reg_ip = cregex::compile("(25[0-5]|2[0-5][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])[.](25[0-5]|2[0-5][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])[.](25[0-5]|2[0-5][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])[.](25[0-5]|2[0-5][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])"); - return regex_match(ip, reg_ip); + boost::xpressive::cregex reg_ip = boost::xpressive::cregex::compile("(25[0-4]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])[.](25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])[.](25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])[.](25[0-4]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])"); + return boost::xpressive::regex_match(ip, reg_ip); } bool IsValidMask(std::string mask) { @@ -542,13 +1224,13 @@ bool IsValidMask(std::string mask) { // jsData["memoryTotal"] = (int)mem_total; // jsData["memoryFree"] = (int)mem_free; // jsData["memoryUse"] = fMemRate * 100; -// jsData["hardDiskTotal"] = boost::lexical_cast(strhardTotal.substr(0,strhardTotal.length() - 1)); -// jsData["hardDiskFree"] = boost::lexical_cast(strhardFree.substr(0,strhardFree.length() - 1)); +// jsData["hardDiskTotal"] = atof(strhardTotal.substr(0,strhardTotal.length() - 1)); +// jsData["hardDiskFree"] = atof(strhardFree.substr(0,strhardFree.length() - 1)); -// double total = boost::lexical_cast(strhardTotal.substr(0,strhardTotal.length() - 1)); -// double free = boost::lexical_cast(strhardFree.substr(0,strhardFree.length() - 1)); +// double total = atof(strhardTotal.substr(0,strhardTotal.length() - 1)); +// double free = atof(strhardFree.substr(0,strhardFree.length() - 1)); // double use = ((total - free) / free) * 100; -// // jsData["hardDiskUse"] = boost::lexical_cast(strrateHardUse.substr(0,strrateHardUse.length() - 1)); +// // jsData["hardDiskUse"] = atof(strrateHardUse.substr(0,strrateHardUse.length() - 1)); // jsData["hardDiskUse"] = use; // jsData["cpuSystemUse"] = rateSys; // jsData["temperature"] = temperature; @@ -566,7 +1248,40 @@ bool IsValidMask(std::string mask) { // return 0; // } +double GetHardDiskFree() +{ + char hardName[32]; + char hardTotal[32]; + char hardUse[32]; + char hardFree[32]; + char rateHardUse[32]; + const char * getEmmcInfo = "df -h | grep /opt"; + char chRes[100]; + memset(chRes, 0, 100); + system_custom(getEmmcInfo, chRes); + sscanf(chRes,"%s%s%s%s%s",hardName, hardTotal, hardUse, hardFree, rateHardUse); + std::string strhardTotal(hardTotal); + std::string strhardFree(hardFree); + std::string strrateHardUse(rateHardUse); + double freeDisk = atof(strhardFree.substr(0,strhardFree.length() - 1).c_str()); + return freeDisk; +} +int getSysIntValue(char *key) +{ + FILE *fp = NULL; + int value = 0; + if(key == NULL)return 0; + fp = fopen(key, "r"); + if (fp == NULL) { + printf("Error: could not open %s file\n",key); + return 1; + } + + fscanf(fp, "%d", &value); + fclose(fp);fp = NULL; + return value; +} std::string GetSysStatus() { long mem_used = -1; @@ -618,13 +1333,24 @@ std::string GetSysStatus() const char * getEmmcInfo = "df -h | grep /opt"; char chRes[100]; memset(chRes, 0, 100); +#ifdef IMX6UL_GATEWAY system_custom(getEmmcInfo, chRes); sscanf(chRes,"%s%s%s%s%s",hardName, hardTotal, hardUse, hardFree, rateHardUse); +#endif +#ifdef G2UL_GATEWAY + getDiskInfo(hardTotal,hardFree); +#endif + std::string strhardTotal(hardTotal); std::string strhardFree(hardFree); std::string strrateHardUse(rateHardUse); - + char key[128] = {0}; + memset(key,0,sizeof(key)); + sprintf(key,"/sys/class/thermal/thermal_zone0/temp"); + int temp = getSysIntValue(key); + + print_info("rateUser = %f,mem_total = %d,mem_free = %d,fMemRate = %f\n",rateUser,mem_total,mem_free,fMemRate); Json::Value jsData; Json::FastWriter fw; jsData["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; @@ -632,13 +1358,15 @@ std::string GetSysStatus() jsData["memoryTotal"] = (int)mem_total; jsData["memoryFree"] = (int)mem_free; jsData["memoryUse"] = fMemRate * 100; - jsData["hardDiskTotal"] = boost::lexical_cast(strhardTotal.substr(0,strhardTotal.length() - 1)); - jsData["hardDiskFree"] = boost::lexical_cast(strhardFree.substr(0,strhardFree.length() - 1)); + jsData["hardDiskTotal"] = atof(strhardTotal.substr(0,strhardTotal.length() - 1).c_str()); + jsData["hardDiskFree"] = atof(strhardFree.substr(0,strhardFree.length() - 1).c_str()); + jsData["temperature"] = temp/1000.0; + jsData["temperatureNR5G"] = atoi(GlobalConfig::NR5GTemp.c_str()); - double total = boost::lexical_cast(strhardTotal.substr(0,strhardTotal.length() - 1)); - double free = boost::lexical_cast(strhardFree.substr(0,strhardFree.length() - 1)); + double total = atof(strhardTotal.substr(0,strhardTotal.length() - 1).c_str()); + double free = atof(strhardFree.substr(0,strhardFree.length() - 1).c_str()); double use = ((total - free) / total) * 100; - // jsData["hardDiskUse"] = boost::lexical_cast(strrateHardUse.substr(0,strrateHardUse.length() - 1)); + // jsData["hardDiskUse"] = atof(strrateHardUse.substr(0,strrateHardUse.length() - 1)); jsData["hardDiskUse"] = use; jsData["cpuSystemUse"] = rateSys; @@ -650,6 +1378,48 @@ std::string GetSysStatus() return strJson; } + +unsigned char ch2hex(char ch) +{ + static const char *hex="0123456789ABCDEF"; + for(unsigned char i=0;i!=16;++i) + if(ch==hex[i]) + return i; + return 0; +} +string tohex(const string& str) +{ + string ret; + static const char *hex="0123456789ABCDEF"; + for(int i=0;i!=str.size();++i) + { + ret.push_back(hex[(str[i]>>4)&0xf]); + ret.push_back( hex[str[i]&0xf]); + } + return ret; +} +char* solve(char *dest,const char *src) +{ + int i=0; + int cnt=0; + unsigned char*d=(unsigned char*)dest; + while(*src) + { + if(i&1) + { + d[cnt++]|=ch2hex(*src); + } + else + { + d[cnt]=ch2hex(*src)<<4; + } + src++; + i++; + } + return dest; +} + + void swap(char *data) { int tmp; @@ -657,6 +1427,928 @@ void swap(char *data) data[1] = data[0]; data[0] = tmp; } +int OpenWatchDog() +{ + int fd = -1; + InitGpio(GlobalConfig::GPIO_G.hardWatchDog,1); + gpio_set(GlobalConfig::GPIO_G.hardWatchDog,1);//高电平有效 + if(0 >(fd = open("/dev/watchdog",O_WRONLY))){ + print_info("Failed:Open /dev/watchdog"); + } + return fd; + +} +int WriteWatchDog(int fd) +{ + if(1 != write(fd,"0",1)){ + print_info("Failed:feeding watchdog"); + } +} +int CloseWatchDog(int fd) +{ + close(fd); +} +string TrimStringLeft(const char* szData, const char* szTargets) +{ + string strData = szData; + int nPos = 0; + nPos = strData.find(szTargets); + while (nPos == 0) + { + strData.erase(nPos, 1); + nPos = strData.find(szTargets); + } + return strData; +} + +string TrimStringRight(const char* szData, const char* szTargets) +{ + string strData = szData; + int nPos = 0; + nPos = strData.rfind(szTargets); + while ((nPos == (int)(strData.size() - 1)) && (nPos >= 0)) + { + strData.erase(nPos, 1); + nPos = strData.rfind(szTargets); + } + return strData; +} +string GetOneContent(const char* szData, int nRow, const char* szSeparate) +{ + string strParam = ""; + string strTemp = szData; + int nFirstPos = -1; + for (int i = 0; i < nRow; i++) + { + nFirstPos = strTemp.find(szSeparate, nFirstPos + 1); + if (nFirstPos < 0) + return strParam.c_str(); + } + + int nSecondPos = strTemp.find(szSeparate, nFirstPos + 1); + if (nSecondPos < 0) + { + strParam = strTemp.substr(nFirstPos + 1); + } + else + { + strParam = strTemp.substr(nFirstPos + 1, nSecondPos - nFirstPos - 1); + } + + { + strParam = TrimStringRight(strParam.c_str(), " "); + strParam = TrimStringLeft(strParam.c_str(), " "); + } + return strParam.c_str(); +} +int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop) +{ + struct termios newtio,oldtio; + if ( tcgetattr( fd,&oldtio) != 0) { //检测串口是否可用 + perror("SetupSerial 1"); + return -1; + } + bzero( &newtio, sizeof( newtio ) ); + newtio.c_cflag |= CLOCAL | CREAD; + newtio.c_cflag &= ~CSIZE; + + switch( nBits ) //设置数据位 + { + case 7: + newtio.c_cflag |= CS7; + break; + case 8: + newtio.c_cflag |= CS8; + break; + } + + switch( nEvent )//设置检验位 + { + case 'O': + newtio.c_cflag |= PARENB; + newtio.c_cflag |= PARODD; + newtio.c_iflag |= (INPCK | ISTRIP); + break; + case 'E': + newtio.c_iflag |= (INPCK | ISTRIP); + newtio.c_cflag |= PARENB; + newtio.c_cflag &= ~PARODD; + break; + case 'N': + newtio.c_cflag &= ~PARENB; + break; + } + + switch( nSpeed ) //设置波特率 + { + case 2400: + cfsetispeed(&newtio, B2400); + cfsetospeed(&newtio, B2400); + break; + case 4800: + cfsetispeed(&newtio, B4800); + cfsetospeed(&newtio, B4800); + break; + case 9600: + cfsetispeed(&newtio, B9600); + cfsetospeed(&newtio, B9600); + break; + case 115200: + cfsetispeed(&newtio, B115200); + cfsetospeed(&newtio, B115200); + break; + case 460800: + cfsetispeed(&newtio, B460800); + cfsetospeed(&newtio, B460800); + break; + default: + cfsetispeed(&newtio, B9600); + cfsetospeed(&newtio, B9600); + break; + } + if( nStop == 1 )//设置停止位 + newtio.c_cflag &= ~CSTOPB; + else if ( nStop == 2 ) + newtio.c_cflag |= CSTOPB; + newtio.c_cc[VTIME] = 0; + newtio.c_cc[VMIN] = 0; + tcflush(fd,TCIFLUSH); + if((tcsetattr(fd,TCSANOW,&newtio))!=0) //设置串口参数 + { + perror("com set error"); + return -1; + } + return 0; +} + +int getcsq() +{ + /*int fd = config_uart("/dev/ttyUSB2",115200); + print_info("fd = %d\n",fd); + if(fd < 0){ + printf("config_uart error\n"); + } + int len = write_data(fd,"AT+QENG=\"servingcell\"\r\n",27); + + sleep(1); + unsigned char rbuf[128]={0x00}; + len = read_data(fd,(char*)rbuf,100,10); + if(len < 0) { + print_info("Can't get /dev/ttyUSBx Serial Port data!\n"); + } + print_info("rbuf = %s\n",(char*)rbuf); + close(fd);*/ + + int ret = 0; + char csq[128] = {0}; + + int fd = 0, sig = 0; + + if((fd = open("/dev/ttyUSB2", O_RDWR | O_NOCTTY | O_NDELAY))<0){ + + //LOG_ERROR("open %s is FAILED\n\n","/dev/ttyUSB2"); + } + else{ + set_opt(fd, 9600, 8, 'N', 1); + } + set_opt(fd, 115200, 8, 'N', 1); + + //write(fd,"AT+QENG=\"servingcell\"\r\n",27);//开启定位 + write(fd,"AT+CSQ",6); + sleep(1); + unsigned char rbuf[128]={0x00}; + int len = read(fd, rbuf, sizeof(rbuf)); // 在串口读入字符串 + + print_info("rbuf = %s,len = %d\n",rbuf,len); + sleep(1); + if(len < 0) { + print_info("Can't get /dev/ttyUSBx Serial Port data!\n"); + } + + const char *str2 = "+QENG: "; + char *pdata = strstr((char*)rbuf, str2); + if(pdata) + strncpy(csq, pdata+7, sizeof(csq)); + else { + return -1; + } + //printf("SIM-CSQ: %s\n", csq); + GlobalConfig::NetStatus = GetOneContent(csq,1,","); + string signal = GetOneContent(csq,13,","); + GlobalConfig::NetSignal = atoi(signal.c_str()); + print_info("NetStatus = %s,NetSignal = %d\n",GlobalConfig::NetStatus.c_str(),GlobalConfig::NetSignal); + // ret = csq + close(fd); + /*if(csq[0] == ',') + ret = 0; + else if(csq[1] == ',') + ret = (int)csq[0] - '0'; + else if(csq[2] == ',') + ret = ((int)csq[0] - '0')*10 + (int)csq[1] - '0'; + + print_info("sig = %d\n", ret);*/ + return atoi(signal.c_str()); + +/* + int level; + char *str = NULL; + if (strstr(csq, "99,") || strstr(csq, "199,") ){ + printf("No signal ..\n"); + level = 0; + } + else { + char rssi_str[4]; + int rssi; + memset(rssi_str, 0, sizeof(rssi_str)); + if (*(csq+2) == ',') { + rssi_str[0] = *(csq+0+0); + rssi_str[1] = *(csq+0+1); + } + else if (isdigit(*(csq+2)) && isdigit(*(csq+3) == ',')) { + rssi_str[0] = *(csq+0+0); + rssi_str[1] = *(csq+0+1); + rssi_str[2] = *(csq+0+2); + } + rssi = atoi(rssi_str); + +printf("rssi = %d\n", rssi); + + int signal = -113 + (2 * rssi); + if(signal > -91) + level = 5; + else if (signal <= -91 && signal > -101) + level = 4; + else if(signal <= -101 && signal > -103) + level = 3; + else if(signal <= -103 && signal > -107) + level = 2; + else if(signal <= -107 && signal > -113) + level = 1; + else + level = 0; + printf("level = %d, signal: %d\n", rssi, signal); + } +*/ + +} +void IniReadValue(char* section, char* key, char* val, const char* file) +{ + FILE* fp; + int i = 0; + int lineContentLen = 0; + int position = 0; + char lineContent[LINE_CONTENT_MAX_LEN]; + bool bFoundSection = false; + bool bFoundKey = false; + fp = fopen(file, "r"); + if(fp == NULL) + { + printf("%s: Opent file %s failed.\n", __FILE__, file); + return; + } + while(feof(fp) == 0) + { + memset(lineContent, 0, LINE_CONTENT_MAX_LEN); + fgets(lineContent, LINE_CONTENT_MAX_LEN, fp); + if((lineContent[0] == ';') || (lineContent[0] == '\0') || (lineContent[0] == '\r') || (lineContent[0] == '\n')) + { + continue; + } + + //check section + if(strncmp(lineContent, section, strlen(section)) == 0) + { + bFoundSection = true; + //printf("Found section = %s\n", lineContent); + while(feof(fp) == 0) + { + memset(lineContent, 0, LINE_CONTENT_MAX_LEN); + fgets(lineContent, LINE_CONTENT_MAX_LEN, fp); + //check key + if(strncmp(lineContent, key, strlen(key)) == 0) + { + bFoundKey = true; + lineContentLen = strlen(lineContent); + //find value + for(i = strlen(key); i < lineContentLen; i++) + { + if(lineContent[i] == '=') + { + position = i + 1; + break; + } + } + if(i >= lineContentLen) break; + strncpy(val, lineContent + position, strlen(lineContent + position)); + lineContentLen = strlen(val); + for(i = 0; i < lineContentLen; i++) + { + if((lineContent[i] == '\0') || (lineContent[i] == '\r') || (lineContent[i] == '\n')) + { + val[i] = '\0'; + break; + } + } + } + else if(lineContent[0] == '[') + { + break; + } + } + break; + } + } + if(!bFoundSection){printf("No section = %s\n", section);} + else if(!bFoundKey){printf("No key = %s\n", key);} + fclose(fp); +} + +int readStringValue(const char* section, char* key, char* val, const char* file) +{ + char sect[SECTION_MAX_LEN]; + //printf("section = %s, key = %s, file = %s\n", section, key, file); + if (section == NULL || key == NULL || val == NULL || file == NULL) + { + printf("%s: input parameter(s) is NULL!\n", __func__); + return -1; + } + + memset(sect, 0, SECTION_MAX_LEN); + sprintf(sect, "[%s]", section); + //printf("reading value...\n"); + IniReadValue(sect, key, val, file); + + return 0; +} + +int readIntValue(const char* section, char* key, const char* file) +{ + char strValue[STRVALUE_MAX_LEN]; + memset(strValue, '\0', STRVALUE_MAX_LEN); + if(readStringValue(section, key, strValue, file) != 0) + { + printf("%s: error", __func__); + return 0; + } + return(atoi(strValue)); +} + +void IniWriteValue(const char* section, char* key, char* val, const char* file) +{ + FILE* fp; + int i = 0, n = 0, err = 0; + int lineContentLen = 0; + int position = 0; + char lineContent[LINE_CONTENT_MAX_LEN]; + char strWrite[LINE_CONTENT_MAX_LEN]; + bool bFoundSection = false; + bool bFoundKey = false; + + memset(lineContent, '\0', LINE_CONTENT_MAX_LEN); + memset(strWrite, '\0', LINE_CONTENT_MAX_LEN); + n = sprintf(strWrite, "%s=%s\n", key, val); + fp = fopen(file, "r+"); + if(fp == NULL) + { + printf("%s: Opent file %s failed.\n", __FILE__, file); + return; + } + while(feof(fp) == 0) + { + memset(lineContent, 0, LINE_CONTENT_MAX_LEN); + fgets(lineContent, LINE_CONTENT_MAX_LEN, fp); + if((lineContent[0] == ';') || (lineContent[0] == '\0') || (lineContent[0] == '\r') || (lineContent[0] == '\n')) + { + continue; + } + //check section + if(strncmp(lineContent, section, strlen(section)) == 0) + { + bFoundSection = true; + while(feof(fp) == 0) + { + memset(lineContent, 0, LINE_CONTENT_MAX_LEN); + fgets(lineContent, LINE_CONTENT_MAX_LEN, fp); + //check key + if(strncmp(lineContent, key, strlen(key)) == 0) + { + bFoundKey = true; + printf("%s: %s=%s\n", __func__, key, val); + fseek(fp, (0-strlen(lineContent)),SEEK_CUR); + err = fputs(strWrite, fp); + if(err < 0){printf("%s err.\n", __func__);} + break; + } + else if(lineContent[0] == '[') + { + break; + } + } + break; + } + } + if(!bFoundSection){printf("No section = %s\n", section);} + else if(!bFoundKey){printf("No key = %s\n", key);} + fclose(fp); +} + +int writeStringVlaue(const char* section, char* key, char* val, const char* file) +{ + char sect[SECTION_MAX_LEN]; + //printf("section = %s, key = %s, file = %s\n", section, key, file); + if (section == NULL || key == NULL || val == NULL || file == NULL) + { + printf("%s: input parameter(s) is NULL!\n", __func__); + return -1; + } + memset(sect, '\0', SECTION_MAX_LEN); + sprintf(sect, "[%s]", section); + IniWriteValue(sect, key, val, file); +} + +int writeIntValue(const char* section, char* key, int val, const char* file) +{ + char strValue[STRVALUE_MAX_LEN]; + memset(strValue, '\0', STRVALUE_MAX_LEN); + sprintf(strValue, "%-4d", val); + + writeStringVlaue(section, key, strValue, file); +} + +int getDiskInfo(char* diskTotal,char* diskFree) +{ + DISK diskInfo; +// pDISK pDiskInfo; +// char dpath[100]="/";//设置默认位置 +// int flag=0; +// if(NULL!=path) +// { +// strcpy(dpath,path); +// } +// if(-1==(flag=statfs("/tmp",pDiskInfo)))//获取包含磁盘空间信息的结构体 +// { +// perror("getDiskInfo statfs fail"); +// return 0; +// } +// unsigned long long total=0,avail=0,free=0,blockSize=0; +// +// blockSize=pDiskInfo->f_bsize;//每块包含字节大小 +// total=pDiskInfo->f_blocks*blockSize;//磁盘总空间 +// avail=pDiskInfo->f_bavail*blockSize;//非超级用户可用空间 +// free=pDiskInfo->f_bfree*blockSize;//磁盘所有剩余空间 +// //字符串转换 +// char diskTotal[30],diskAvail[30],diskFree[30]; +// flag=sprintf(diskTotal,"%llu",total>>20); +// flag=sprintf(diskAvail,"%llu",avail>>20); +// flag=sprintf(diskFree,"%llu",free>>20); +// print_info("diskTotal = %s,diskAvail = %s,diskFree = %s\n",diskTotal,diskAvail,diskFree); +// if(-1==flag) +// { +// return 0; +// } + /* 1.获取/home/下面的总容量 */ + statfs("/", &diskInfo); + unsigned long long blocksize = diskInfo.f_bsize; //每个block里包含的字节数 + unsigned long long totalsize = blocksize * diskInfo.f_blocks;//总的字节数,f_blocks为block的数目 + //printf("Total_size=%llu B =%llu KB =%llu MB = %llu GB\n",\ + totalsize,totalsize>>10,totalsize>>20, totalsize>>30); + + /* 2.获取一下剩余空间和可用空间的大小 */ + unsigned long long freeDisk = diskInfo.f_bfree * blocksize; //剩余空间的大小 + unsigned long long availableDisk = diskInfo.f_bavail * blocksize; //可用空间大小 + //printf("Disk_free=%llu MB =%llu GB Disk_available=%llu MB = %llu GB\n",\ + freeDisk>>20,freeDisk>>30,availableDisk>>20, availableDisk>>30); + sprintf(diskTotal,"%llu",totalsize>>20); + sprintf(diskFree,"%llu",freeDisk>>20); + return 1; +} +bool NetIsOk() +{ + + double rtt; + struct hostent *host; + struct protoent *protocol; + int i,recv_status; + +#ifdef _USE_DNS //如果定义该宏,则可以使用域名进行判断网络连接,例如www.baidu.com + /* 设置目的地址信息 */ + char hostname[32]; + sprintf(hostname,"%s","www.baidu.com") + bzero(&dest_addr, sizeof(dest_addr)); + dest_addr.sin_family = AF_INET; + + if((host=gethostbyname(hostname))==NULL) + { + LOG_ERROR("[NetStatus] error : Can't get serverhost info!\n"); + return false; + } + + bcopy((char*)host->h_addr,(char*)&dest_addr.sin_addr,host->h_length); +#else //如果不使用域名,则只能用ip地址直接发送icmp包, + dest_addr.sin_addr.s_addr = inet_addr(GlobalConfig::ServerIP.c_str()); +#endif + + + if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) + { /* 创建原始ICMP套接字 */ + LOG_ERROR("[NetStatus] error : socket %d\n",sockfd); + return false; + } + + int iFlag; + if(iFlag = fcntl(sockfd,F_GETFL,0)<0) + { + LOG_ERROR("[NetStatus] error : fcntl(sockfd,F_GETFL,0)"); + _CloseSocket(); + return false; + } + iFlag |= O_NONBLOCK; + if(iFlag = fcntl(sockfd,F_SETFL,iFlag)<0) + { + LOG_ERROR("[NetStatus] error : fcntl(sockfd,F_SETFL,iFlag )"); + _CloseSocket(); + return false; + } + print_info("================NetIsOk check=============\n"); + pid=getpid(); + for(i=0;i0) + { + _CloseSocket(); + return true; + } + + } + _CloseSocket(); + return false; +} + + + +int send_packet(int pkt_no,char *sendpacket) +{ + int packetsize; + packetsize=pack(pkt_no,sendpacket); + gettimeofday(&tvsend,NULL); + print_info("================NetIsOk send_packet=============\n"); + if(sendto(sockfd,sendpacket,packetsize,0,(struct sockaddr *)&dest_addr,sizeof(dest_addr) )<0) + { + LOG_ERROR("[NetStatus] error : sendto error"); + return -1; + } + return 1; +} + + +int pack(int pkt_no,char*sendpacket) +{ + int i,packsize; + struct icmp *icmp; + struct timeval *tval; + icmp=(struct icmp*)sendpacket; + icmp->icmp_type=ICMP_ECHO; //设置类型为ICMP请求报文 + icmp->icmp_code=0; + icmp->icmp_cksum=0; + icmp->icmp_seq=pkt_no; + icmp->icmp_id=pid; //设置当前进程ID为ICMP标示符 + packsize=ICMP_HEADSIZE+sizeof(struct timeval); + tval= (struct timeval *)icmp->icmp_data; + gettimeofday(tval,NULL); + icmp->icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize); + return packsize; +} + + +unsigned short cal_chksum(unsigned short *addr,int len) +{ + int nleft=len; + int sum=0; + unsigned short *w=addr; + unsigned short answer=0; + while(nleft>1) //把ICMP报头二进制数据以2字节为单位累加起来 + { + sum+=*w++; + nleft-=2; + } + if( nleft==1) //若ICMP报头为奇数个字节,会剩下最后一字节.把最后一个字节视为一个2字节数据的高字节,这个2字节数据的低字节为0,继续累加 + { + *(unsigned char *)(&answer)=*(unsigned char *)w; + sum+=answer; + } + sum=(sum>>16)+(sum&0xffff); + sum+=(sum>>16); + answer=~sum; + return answer; +} + + +int recv_packet(int pkt_no,char *recvpacket) +{ + int n; + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(sockfd,&rfds); + signal(SIGALRM,timeout); + unsigned int fromlen=sizeof(recv_addr); + alarm(MAX_WAIT_TIME); + print_info("================NetIsOk recv_packet=============\n"); + while(1) + { + select(sockfd+1, &rfds, NULL, NULL, NULL); + if (FD_ISSET(sockfd,&rfds)) + { + if( (n=recvfrom(sockfd,recvpacket,PACKET_SIZE,0,(struct sockaddr *)&recv_addr,&fromlen)) <0) + { + print_info("================NetIsOk recvfrom=============errno = %d\n",errno); + if(errno==EINTR){ + return -1; + LOG_ERROR("recvfrom error"); + return -2; + } + } + } + gettimeofday(&tvrecv,NULL); + if(unpack(pkt_no,recvpacket,n)==-1) + continue; + return 1; + } +} + +int unpack(int cur_seq,char *buf,int len) +{ + int iphdrlen; + struct ip *ip; + struct icmp *icmp; + ip=(struct ip *)buf; + iphdrlen=ip->ip_hl<<2; //求ip报头长度,即ip报头的长度标志乘4 + icmp=(struct icmp *)(buf+iphdrlen); //越过ip报头,指向ICMP报头 + len-=iphdrlen; //ICMP报头及ICMP数据报的总长度 + if( len<8) + return -1; + if( (icmp->icmp_type==ICMP_ECHOREPLY) && (icmp->icmp_id==pid) && (icmp->icmp_seq==cur_seq)) + return 0; + else return -1; +} + + +void timeout(int signo) +{ + LOG_ERROR("Request Timed Out\n"); + _CloseSocket(); +} + +void tv_sub(struct timeval *out,struct timeval *in) +{ + if( (out->tv_usec-=in->tv_usec)<0) + { + --out->tv_sec; + out->tv_usec+=1000000; + } + out->tv_sec-=in->tv_sec; +} + +void _CloseSocket() +{ + close(sockfd); + sockfd = 0; +} + +int socketHeart(const char* pSendData) +{ + print_info("socketHeart\n"); + int sockfd; // Socket文件描述符 + struct sockaddr_in serverAddr{}; // Server地址结构体 + + // 创建Socket + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + std::cerr << "Failed to create socket." << std::endl; + return 1; + } + + // 设置Server地址信息 + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(18393); // TCP默认端口号为80 + inet_pton(AF_INET, /*GlobalConfig::ServerIP.c_str()*/"192.168.1.147", &serverAddr.sin_addr); + + // 连接到Server + if (connect(sockfd, reinterpret_cast(&serverAddr), sizeof(serverAddr)) == -1) { + std::cerr << "Failed to connect to the server." << std::endl; + close(sockfd); + return 1; + } + + // 发送心跳数据包 + const char heartbeat[] = "Heartbeat"; + ssize_t bytesSent = send(sockfd, pSendData, strlen(pSendData), MSG_NOSIGNAL); + if (bytesSent == -1) { + std::cerr << "Failed to send heartbeat packet." << std::endl; + close(sockfd); + return 1; + } else if (static_cast(bytesSent) != strlen(pSendData)) { + std::cerr << "Partially sent heartbeat packet." << std::endl; + close(sockfd); + return 1; + } + + // 关闭Socket连接 + close(sockfd); + + return 0; +} +//unsigned short cal_chksum(unsigned short *addr, int len) +//{ +// int nleft=len; +// int sum=0; +// unsigned short *w=addr; +// unsigned short answer=0; +// +// while(nleft > 1) +// { +// sum += *w++; +// nleft -= 2; +// } +// +// if( nleft == 1) +// { +// *(unsigned char *)(&answer) = *(unsigned char *)w; +// sum += answer; +// } +// +// sum = (sum >> 16) + (sum & 0xffff); +// sum += (sum >> 16); +// answer = ~sum; +// +// return answer; +//} + +// Ping函数,timeout为超时时间,单位是ms,10000 毫秒=10 秒 +//成功:返回0,失败:返回1或-1 +int Ping( const char *ips, int timeout) +{ + struct timeval *tval; + int maxfds = 0; + fd_set readfds; + + int iRet = 0; + struct sockaddr_in addr; + struct sockaddr_in from; + // 设定Ip信息 + bzero(&addr,sizeof(addr)); + addr.sin_family = AF_INET; + + addr.sin_addr.s_addr = inet_addr(ips); + + int sockfd; + // 取得socket 。 如果没加sudo 这里会报错 + sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (sockfd < 0) + { + print_error("ip:%s,socket error\n",ips); + return -1; + } + + struct timeval timeo; + // 设定TimeOut时间 + timeo.tv_sec = timeout / 1000; + timeo.tv_usec = timeout % 1000; + + if (setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeo, sizeof(timeo)) == -1) + { + print_error("ip:%s,setsockopt error\n",ips); + close(sockfd); + return -1; + } + + char sendpacket[2048]; + char recvpacket[2048]; + // 设定Ping包 + memset(sendpacket, 0, sizeof(sendpacket)); + + pid_t pid; + // 取得PID,作为Ping的Sequence ID + pid=getpid(); + + struct ip *iph; + struct icmp *icmp; + + + icmp=(struct icmp*)sendpacket; + icmp->icmp_type=ICMP_ECHO; //回显请求 + icmp->icmp_code=0; + icmp->icmp_cksum=0; + icmp->icmp_seq=0; + icmp->icmp_id=pid; + tval= (struct timeval *)icmp->icmp_data; + gettimeofday(tval,NULL); + icmp->icmp_cksum=cal_chksum((unsigned short *)icmp,sizeof(struct icmp)); //校验 + + int n = sendto(sockfd, (char *)&sendpacket, sizeof(struct icmp), 0, (struct sockaddr *)&addr, sizeof(addr)); + if (n < 1) + { + print_error("ip:%s,sendto error\n",ips); + close(sockfd); + return -1; + } + + // 接受 + // 由于可能接受到其他Ping的应答消息,所以这里要用循环 + int cnt=0; + while(1) + { + // 设定TimeOut时间,这次才是真正起作用的 + FD_ZERO(&readfds); + FD_SET(sockfd, &readfds); + maxfds = sockfd + 1; + n = select(maxfds, &readfds, NULL, NULL, &timeo); + if (n <= 0) + { + print_info("ip:%s,Time out error\n",ips); + close(sockfd); + iRet = -1; + break; + } + + // 接受 + memset(recvpacket, 0, sizeof(recvpacket)); + int fromlen = sizeof(from); + n = recvfrom(sockfd, recvpacket, sizeof(recvpacket), 0, (struct sockaddr *)&from, (socklen_t *)&fromlen); + print_info("recvfrom Len:%d\n",n); + if (n < 1) + { + close(sockfd); + iRet = 1; + break; + } + + char *from_ip = (char *)inet_ntoa(from.sin_addr); + // 判断是否是自己Ping的回复 + if (strcmp(from_ip,ips) != 0) + { + print_info("NowPingip:%s Fromip:%s NowPingip is not same to Fromip,so ping wrong!\n",ips,from_ip); + close(sockfd); + iRet = 1; + break; + + } + + iph = (struct ip *)recvpacket; + + icmp=(struct icmp *)(recvpacket + (iph->ip_hl<<2)); + + print_info("ip:%s,icmp->icmp_type:%d,icmp->icmp_id:%d\n",ips,icmp->icmp_type,icmp->icmp_id); + // 判断Ping回复包的状态 + if (icmp->icmp_type == ICMP_ECHOREPLY && icmp->icmp_id == pid) //ICMP_ECHOREPLY回显应答 + { + // 正常就退出循环 + print_info("icmp succecss ............. \n"); + break; + } + else if(cnt<3) + { + // 否则继续等 + cnt++; + continue; + } + else + { + close(sockfd); + iRet = -1; + break; + } + } + close(sockfd); + return iRet; +} +int get_netlink_status(const char *if_name) +{ + int skfd; + struct ifreq ifr; + struct ethtool_value edata; + edata.cmd = ETHTOOL_GLINK; + edata.data = 0; + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name) - 1); + ifr.ifr_data = (char *)&edata; + if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) == 0) + return -1; + if (ioctl(skfd, SIOCETHTOOL, &ifr) == -1) + { + close(skfd); + return -1; + } + close(skfd); + return edata.data; +} + static const char* JSON_FIELD_CMD = "cmd";//协议: 命令字段 static const char* JSON_FIELD_NAME = "dataWatchName";//协议: 终端名称 diff --git a/common/SH_CommonFunc.hpp b/common/SH_CommonFunc.hpp index 12bb465..b3bb258 100644 --- a/common/SH_CommonFunc.hpp +++ b/common/SH_CommonFunc.hpp @@ -26,10 +26,19 @@ #include //ipc #include #include "dirent.h" +#include +#include +#include +#include +#include +#include +#include "Mutex.h" +typedef struct statfs DISK,*pDISK; - - +#define SECTION_MAX_LEN 256 +#define STRVALUE_MAX_LEN 256 +#define LINE_CONTENT_MAX_LEN 256 //配置文件位置 #define NETWORK "/etc/network/interfaces" #define SYSTEMINFOFILE "/opt/configenv/SystemInfo.json" //系统信息 @@ -43,6 +52,7 @@ #define SN "/opt/system/sn" //设备序列号 #define SYSTEMSTART "/opt/system/start" //系统启动类型标志 0:正常启动 1:重启 2: #define BUILD_UINT16(x,y) (((x & 0x00FFu) << 8u) | (y & 0x00FFu)) +#define BUILD_UINT2(x,y) (((x) << 2u) | (y)) // 生成UINT32 数据 #define BUILD_UINT32(u,v,x,y) (((u & 0x00FFu) << 24u) | (v & 0x00FFu) << 16u) | (((x & 0x00FFu) << 8u) | (y & 0x00FFu)) // 获取UINT32的高低字节 @@ -50,16 +60,18 @@ #define UINT32_HIGH_2(x) ((x & 0x00FF0000u) >> 16u) #define UINT32_LOW_1(x) ((x & 0x0000FF00u) >> 8u) #define UINT32_LOW_2(x) ((x & 0x000000FFu)) - +#define GET_BIT(x, bit) ((x & (1 << bit)) >> bit) /* 获取第bit位 */ // 获取UINT32的高低字节 #define UINT16_HIGH(x) ((x & 0xFF00u) >> 8u) #define UINT16_LOW(x) ((x & 0x00FFu)) -#define onlineCheck 21600 #define GENERAL_BUF_SIZE 128*1024*10 using namespace std; + + + enum TIME_SIZE{ TIME_MINUTE=5, TIME_SECEOND=8 @@ -108,6 +120,8 @@ struct ZigbeeInfo { std::string PanID; std::string MyAddr; std::string DstAddr; + std::string RetryNum; + std::string TranTimeout; }; struct ZIGBEE { @@ -183,7 +197,9 @@ struct DataNodeInfo { std::string ConfigDate;//配置时间 int VIntegralFilterFrequency;//速度积分滤波频率 - + DataNodeInfo(){ + FeatureInterVal = 0;WaveInterVal = 0; + } }; @@ -205,6 +221,7 @@ struct DataRecvDym { float Amp3; float Amp4; float Amp5; + long Time; float Phase1; float Phase2; float Phase3; @@ -221,6 +238,7 @@ struct TopicList{ std::string mPubWaveSecondData; //原始数据发布主题 std::string mPubCmd; //命令控制发布主题 std::string mPubRep; + std::string mPubTiming; //校时 std::string mPubLocalWifi; std::string mPubLocalWaveServer; @@ -263,6 +281,25 @@ typedef struct { } WAVE_GENERAL; +typedef struct{ + int zigAckrep; + int zigAckreset; + int zigReset; + int zigDef; + int alarmLight; + int commPower;//4G,5G 电源开关 + int vol3_8;//5G 3.8v电源 + int commRest;//4G,5G复位 + int wifiPower;//WiFi 电源开关 + int wifiReset;//WiFi 复位 + int hardWatchDog; + int power; + int runLed; + int errorLed; + int netResetNet0; + int netResetNet1; +} GPIOInfo; + struct Param_01 { int mMode; //0:登陆 1:更改密码 std::string mUserName; @@ -302,7 +339,10 @@ struct Param_23 { std::string mServerIp; std::string mPort; std::string mCommMode; // 通信模式,有线通信模式 = 1;4G LTE 无线通信模式 = 2 - Param_23():mMode(0),mCmdSerial(""), mServerIp(""),mPort(""),mCommMode(""){}; + std::string mUserName; + std::string mPassword; + std::string mAPN; + Param_23():mMode(0),mCmdSerial(""), mServerIp(""),mPort(""),mCommMode(""),mUserName("chaos"),mPassword("HSD272*#xkd"),mAPN(""){}; }; @@ -317,6 +357,7 @@ struct Param_24 { struct Param_25 { int mMode; + std::string mNet; std::string mCmdSerial; std::string mDnsName; std::string mNetworkPortStatus; @@ -327,12 +368,29 @@ struct Param_25 { Param_25():mMode(0),mCmdSerial(""), mDnsName(""),mGateway(""),mSubnetMask(""),mIp(""),mHostName(""){}; }; - +struct Param_09 { + int mPackageFlag; + Param_09():mPackageFlag(0){}; +}; +struct Param_10 { + std::string strDataNode; + std::string strStatic; + std::string straxis; + std::string timeStart; + std::string timeEnd; + int mPackageFlag; + Param_10():strDataNode(""),strStatic(""),mPackageFlag(0){}; +}; +struct Param_11 { + std::string DataNodeNo; + Param_11():DataNodeNo(""){}; +}; struct Param_26 { int mMode; std::string mCmdSerial; std::string mDataNodeNo; - Param_26():mMode(0),mCmdSerial(""),mDataNodeNo(""){}; + int mPackageFlag; + Param_26():mMode(0),mCmdSerial(""),mDataNodeNo(""),mPackageFlag(0){}; }; @@ -368,6 +426,34 @@ struct Param_30 { int mPackageFlag; Param_30():mMode(0),mChannelId(""),mDataNodeNo(""),mPackageFlag(0){}; }; +struct Param_40 { + int mMode; + std::string mChannelId; + std::string mDataNodeNo; + int mPackageFlag; + int StartFrequency; + int EndFrequency; + Param_40():mMode(0),mChannelId(""),mDataNodeNo(""),mPackageFlag(0),StartFrequency(0),EndFrequency(0){}; +}; +struct Param_41 { + std::string mdataNodeNo; + int mfeatureInterVal; + int mwaveInterVal; + int msamplingRate; + int mrange; + int mAccSampleTime; + std::string mstartBrands; + std::string mstopBrands; + std::string menvelopeBandPass; + int mviff; + std::string mfaultFrequency; + Param_41():mdataNodeNo(""),mfeatureInterVal(0),mwaveInterVal(0),msamplingRate(0),mrange(0),mAccSampleTime(0),\ + mstartBrands(""),mstopBrands(""),menvelopeBandPass(""),mviff(0),mfaultFrequency(""){}; +}; +struct Param_42 { + string fileName; + Param_42():fileName(""){}; +}; struct Param_31 { int mMode; @@ -376,13 +462,13 @@ struct Param_31 { Param_31():mMode(0),mChannelId(""){}; }; + struct Param_32 { - int mMode; - std::string mChannelId; + int mMode; + std::string mChannelId; int mPackageFlag; Param_32():mMode(0),mChannelId(""),mPackageFlag(0){}; }; - struct Param_33 { int mMode; std::string mUnit; @@ -443,11 +529,53 @@ struct Param_47 { std::string mFileName; Param_47():mMode(0),mFileName(""){}; }; +struct Param_51 { + int mMode; + string strGateWayMAC; + string strGateWayLocation; + Param_51():mMode(-1),strGateWayLocation(""){}; +}; +struct Param_52 { + int mMode; + std::string mCmdSerial; + string mSsid; + string mPassWord; +}; +struct Param_53 { + int mMode; + string mdataNodeNo; + string mUpdateKey; + string mUpdateValue; + string mUpdateKey2; + string mUpdateValue2; + string mUpdateKey3; + string mUpdateValue3; + Param_53():mUpdateKey2(""),mUpdateValue2(""),mUpdateKey3(""),mUpdateValue3(""){}; +}; + +typedef struct DataNodeUpdate{ + std::string strUpdataFileName; + std::string strSoftVersion; + std::vector hwVersion; +}; +struct ethtool_value { + unsigned int cmd; + unsigned int data; +}; - - +extern std::string GBKToUTF8(const std::string& strGBK); +extern std::string UTFtoGBK(const char* utf8); +extern string GetLocalTimeWithMs(void); +extern void InitGpio(unsigned int gpioN,unsigned int inout); +extern int gpio_set(unsigned int gpioN,char x); +extern int gpio_read(unsigned int gpioN); +extern int config_uart(const char* Port,speed_t speed); +extern int write_data(int fd, char *buff, int len); +extern int read_data(int fd, char *buff, int len, int timeout); +extern int ModifyMac(char* buff); +//extern int str_recv(int fd, char srcshow,char* buffer); /** * @brief 系统运行时输入入参进行系统软件版本查询 * @param argv 输入参数 -vV版本查询 --debugmode日志调试模式 @@ -477,7 +605,6 @@ extern int system_custom(const char *cmd, char *buf); */ extern void WriteMemoryInfo(); - /** * @brief 获取当前日期 * @return 当前日期的string @@ -497,7 +624,7 @@ extern void GetTime_(char * time_buff,TIME_SIZE len) ; * @return void */ extern void GetTimeNet(char* timebuf, int type); - +extern std::string GetRTC(char* timebuf, int& millisecond); /** * @brief 从配置文件中读取数据 * @param filename 配置文件名 @@ -521,7 +648,7 @@ extern int WriteStr2Config(std::string filename, std::string config, std::string * @brief 获取设备的MAC地址做为设备的唯一标识 * @return std::string Mac地址 */ -extern std::string GetLocalMac(); +extern std::string GetLocalMac(const char* net); /** * @brief 获取设备IP @@ -597,14 +724,45 @@ extern void ZoneConfig(std::string zoneid); * @return std::string CPU MEM DISK info */ extern std::string GetSysStatus(); - +double GetHardDiskFree(); extern bool CheckIP(const char *ip); bool IsValidMask(std::string mask); //read update config file -extern std::vector ReadStrByOpt(std::string filename,std::string& strUpdataFileName); +extern std::vector ReadStrUpdate(std::string filename); +extern void ReadStrConfig(std::string filename); +extern int UpdataDataNodeConfig(std::string filename); +extern char* solve(char *dest,const char *src); extern void swap(char *data); +extern int OpenWatchDog(); +extern int WriteWatchDog(int fd); +extern int CloseWatchDog(int fd); +//获取4G信号强度 +extern int getcsq(); +extern std::string GetGwIp_(const char *eth_name); +extern string GetOneContent(const char* szData, int nRow, const char* szSeparate); +extern int readStringValue(const char* section, char* key, char* val, const char* file); +extern int writeStringVlaue(const char* section, char* key, char* val, const char* file); +extern int readIntValue(const char* section, char* key, const char* file); +extern int writeIntValue(const char* section, char* key, int val, const char* file); +int getDiskInfo(char* diskTotal,char* diskFree); + +void timeout(int signo); +unsigned short cal_chksum(unsigned short *addr,int len); +int pack(int pkt_no,char *sendpacket); +int send_packet(int pkt_no,char *sendpacket); +int recv_packet(int pkt_no,char *recvpacket); +int unpack(int cur_seq,char *buf,int len); +void tv_sub(struct timeval *out,struct timeval *in); +void _CloseSocket(); + +int socketHeart(const char* pSendData); + +extern bool NetIsOk(); +extern int Ping( const char *ips, int timeout); +extern int get_netlink_status(const char *if_name); +extern Mutex g_tDbMutex; #endif diff --git a/common/SH_global.h b/common/SH_global.h index c89673c..ed934cf 100644 --- a/common/SH_global.h +++ b/common/SH_global.h @@ -10,6 +10,8 @@ #include "SH_CommonFunc.hpp" #include "../mqttclient/SH_MqttClient.h" + +#define SECTION_MAX_LEN 1024 //******************** 全局变量********************** enum enumZigBeeTransmitStatus { NO_ENTER_TRANSMITTING_STATUS = 0, @@ -17,6 +19,13 @@ enum enumZigBeeTransmitStatus { }; +//#define NR5G_MODULE +//#define Q4G_MODULE +//#define WIFI_MODULE +//#define NR5G_MEIGE +#define G2UL_GATEWAY +//#define IMX6UL_GATEWAY + class GlobalConfig { public : @@ -24,17 +33,25 @@ public : static int QuitFlag_G; //程序退出标志 static int LinkStatus_G; //和服务器连接状态 static int LinkCount; + static int NetSignal; + static int serverStatus; + static int net0Status; + static std::string NR5GTemp; + static std::string NetStatus; + static std::string NetType; static std::string Version; //软件版本号 static std::string MacAddr_G; //设备MAC地址 + static std::string MacAddr_G2; //设备光纤MAC地址 static std::string IpAddr_G; //设备IP static std::string DbName_G; //数据库名字 + static std::string Config_G; //配置文件 static std::string ServerIP; //服务器地址 static int ServerPort; //服务器端口 static std::string UartName_G; static TopicList Topic_G; //发布的主题 static ZigbeeInfo ZigbeeInfo_G; //gateway zigbee info static ZIGBEE Zigbee_G; - + static GPIOInfo GPIO_G; static enumZigBeeTransmitStatus EnterZigBeeWaveTransmittingFlag_G; // 进入ZigBee网络原始数据传输状态标志 static int EnterZigBeeWaveTransmittingCnt_G; // 进入ZigBee网络原始数据传输状态计数器,以秒为单位进行计数 }; @@ -56,6 +73,17 @@ public : #define LIGHT_GRAY "\033[0;37m" #define WHITE "\033[1;37m" +#ifdef IMX6UL_GATEWAY +#define SAVE_COUNT 2058 //2058,4800 +#define OneWeek 259359//259359,604800 +#endif +#ifdef G2UL_GATEWAY +#define SAVE_COUNT 4800*4 +#define OneWeek 604800*7 +#endif + + + #define perror_info(info) { \ if (GlobalConfig::RUN_MODE) { \ perror(info); \ diff --git a/datatransfer/SH_Datatrans.cpp b/datatransfer/SH_Datatrans.cpp index c032ace..7c44c71 100644 --- a/datatransfer/SH_Datatrans.cpp +++ b/datatransfer/SH_Datatrans.cpp @@ -54,6 +54,7 @@ static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid) static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) { + printf("size = %d\n",size); struct DowloadFile *out=(struct DowloadFile *)stream; if(out && !out->stream) { out->stream=fopen(out->filename, "wb");//打开文件进行写入 @@ -116,6 +117,73 @@ int DataTrans::download(char* pFilename,string& strUrl,string& strResponse,bool curl_global_cleanup(); return 0; } +//下载文件数据接收函数 + +size_t writedata2file(void *ptr, size_t size, size_t nmemb, FILE *stream) { + size_t written = fwrite(ptr, size, nmemb, stream); + return written; +} +//http POST请求文件下载 +int DataTrans::dl_curl_post_req(const string &url, const string &postParams, string& filename) +{ + CURL *curl; + FILE *fp; + CURLcode res; + /* 调用curl_global_init()初始化libcurl */ + res = curl_global_init(CURL_GLOBAL_ALL); + if (CURLE_OK != res) + { + printf("init libcurl failed."); + curl_global_cleanup(); + return -1; + } + /* 调用curl_easy_init()函数得到 easy interface型指针 */ + curl = curl_easy_init(); + if (curl) { + fp = fopen(filename.c_str(),"wb"); + + /* 调用curl_easy_setopt()设置传输选项 */ + res = curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + if (res != CURLE_OK) + { + fclose(fp); + curl_easy_cleanup(curl); + return -1; + } + /* 根据curl_easy_setopt()设置的传输选项,实现回调函数以完成用户特定任务 */ + res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writedata2file); + if (res != CURLE_OK){ + fclose(fp); + curl_easy_cleanup(curl); + return -1; + } + /* 根据curl_easy_setopt()设置的传输选项,实现回调函数以完成用户特定任务 */ + res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); + if (res != CURLE_OK) + { + fclose(fp); + curl_easy_cleanup(curl); + return -1; + } + + res = curl_easy_perform(curl); + // 调用curl_easy_perform()函数完成传输任务 + fclose(fp); + /* Check for errors */ + if(res != CURLE_OK){ + fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(res)); + curl_easy_cleanup(curl); + return -1; + } + + /* always cleanup */ + curl_easy_cleanup(curl); + // 调用curl_easy_cleanup()释放内存 + + } + curl_global_cleanup(); + return 0; +} int DataTrans::Post(const std::string & strUrl, const std::string & strPost, std::string & strResponse) { diff --git a/datatransfer/SH_Datatrans.hpp b/datatransfer/SH_Datatrans.hpp index c7caea6..d2439b5 100644 --- a/datatransfer/SH_Datatrans.hpp +++ b/datatransfer/SH_Datatrans.hpp @@ -95,7 +95,7 @@ public: int Send_Dir_socket(const char *dirname); int download(char* pFilename,string& strUrl,string& strResponse,bool bDownload); - + int dl_curl_post_req(const string &url, const string &postParams, string& filename); public: void SetDebug(bool bDebug); private: diff --git a/dbaccess/SH_SqlDB.cpp b/dbaccess/SH_SqlDB.cpp index 10e7335..11b0423 100644 --- a/dbaccess/SH_SqlDB.cpp +++ b/dbaccess/SH_SqlDB.cpp @@ -2,6 +2,7 @@ #include "../API_log/SH_log.h" #include "../common/SH_global.h" #include +#include "../calculation/Calculation.hpp" bool SqlSwitch() { @@ -12,6 +13,7 @@ bool SqlSwitch() } SqliteDB *sql_ctl = SqliteDB::instance(); +Calculation *pCalculation = Calculation::instance(); SqliteDB::SqliteDB() { @@ -28,7 +30,7 @@ void SqliteDB::SqliteInit(const char *pDbName, bool isDB2) //创建传感器信息存储表 memset(sql_exec, 0, 2048); - sprintf(sql_exec, "create table if not exists %s(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);", + sprintf(sql_exec, "create table if not exists %s(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);", T_SENSOR_INFO(TNAME), T_SENSOR_INFO(DATANODENO), T_SENSOR_INFO(DATANODENAME), @@ -43,6 +45,11 @@ void SqliteDB::SqliteInit(const char *pDbName, bool isDB2) T_SENSOR_INFO(BPNO), T_SENSOR_INFO(SERIALNO), T_SENSOR_INFO(FIRSTPOWERNO), + "WakeupTime", + "StaticTime", + "WaveTime", + "BateryV", + "ProductNo", T_SENSOR_INFO(CONFIGFLAG), T_SENSOR_INFO(STARTBRANDS), T_SENSOR_INFO(STOPBRANDS), @@ -58,15 +65,32 @@ void SqliteDB::SqliteInit(const char *pDbName, bool isDB2) T_SENSOR_INFO(ZIGBEESHORTADDR), T_SENSOR_INFO(ZIGBEELONGADDR), T_SENSOR_INFO(ZIGBEEDESADDR), + "ZigbeePower", + "ZigbeeRetry", + "ZigbeeRetryGap", + "ACCSampleTime", T_SENSOR_INFO(STATUS), T_SENSOR_INFO(TIMESTAMP), T_SENSOR_INFO(VIFF), - T_SENSOR_INFO(RSSI)), + T_SENSOR_INFO(RSSI), + "UpdateFlag", + "LooseValue", + "batteryPower"), CreateTable(sql_exec, isDB2); + int iRet = GetTableRows(" sqlite_master "," name = 't_sensor_info' and sql LIKE '%LooseValue%' "); + if(iRet == 0){ + CreateTable("ALTER TABLE t_sensor_info ADD COLUMN 'LooseValue'"); + } + + iRet = GetTableRows(" sqlite_master "," name = 't_sensor_info' and sql LIKE '%batteryPower%' "); + if(iRet == 0){ + CreateTable("ALTER TABLE t_sensor_info ADD COLUMN 'batteryPower'"); + } + //创建传感器数据存储表 memset(sql_exec, 0, 2048); - sprintf(sql_exec, "create table if not exists %s(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);", + sprintf(sql_exec, "create table if not exists %s(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s integer,%s,%s);", T_DATA_INFO(TNAME), T_DATA_INFO(DATANODENO), T_DATA_INFO(CHANNELID), @@ -84,14 +108,20 @@ void SqliteDB::SqliteInit(const char *pDbName, bool isDB2) T_DATA_INFO(PHASE2), T_DATA_INFO(PHASE3), T_DATA_INFO(PHASE4), - T_DATA_INFO(TIMESTAMP)); + T_DATA_INFO(STATICINDEX), + T_DATA_INFO(TIMESTAMP), + T_DATA_INFO(SENDMSG), + T_DATA_INFO(NODERESEND)); CreateTable(sql_exec, isDB2); - + iRet = GetTableRows(" sqlite_master "," name = 't_data_info' and sql LIKE '%nodeResend%' "); + if(iRet == 0){ + CreateTable("ALTER TABLE t_data_info ADD COLUMN 'nodeResend'"); + } //创建传感器静态数据存储表 memset(sql_exec, 0, 2048); - sprintf(sql_exec, "create table if not exists %s(%s,%s,%s,%s,%s,%s,%s);", + sprintf(sql_exec, "create table if not exists %s(%s,%s,%s,%s,%s,%s,%s,%s integer,%s,%s);", T_DATASTATIC_INFO(TNAME), T_DATASTATIC_INFO(DATANODENO), T_DATASTATIC_INFO(CHANNELID), @@ -99,10 +129,152 @@ void SqliteDB::SqliteInit(const char *pDbName, bool isDB2) T_DATASTATIC_INFO(TEMBOT), T_DATASTATIC_INFO(DIP), T_DATASTATIC_INFO(VOLTAGE), - T_DATASTATIC_INFO(TIMESTAMP)); - CreateTable(sql_exec, isDB2); + "Battery", + T_DATASTATIC_INFO(STATICINDEX), + T_DATASTATIC_INFO(TIMESTAMP), + T_DATASTATIC_INFO(SENDMSG), + T_DATASTATIC_INFO(NODERESEND)); + CreateTable(sql_exec, isDB2); + iRet = GetTableRows(" sqlite_master "," name = 't_datastatic_info' and sql LIKE '%nodeResend%' "); + if(iRet == 0){ + CreateTable("ALTER TABLE t_datastatic_info ADD COLUMN 'nodeResend'"); + } + + memset(sql_exec, 0, 2048); + sprintf(sql_exec, "create table if not exists %s(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);", + T_GATEWAY_INFO(TNAME), + T_GATEWAY_INFO(GATEWAYMAC), + T_GATEWAY_INFO(SENSORVER), + T_GATEWAY_INFO(GATEWAYLOCATION), + T_GATEWAY_INFO(ZIGBEEPANID), + T_GATEWAY_INFO(ZIGBEECHANNEL), + T_GATEWAY_INFO(COMMUNICATIONTYPE), + T_GATEWAY_INFO(SIGNAL), + T_GATEWAY_INFO(LOCALIP), + T_GATEWAY_INFO(SYSTEMVERSION), + T_GATEWAY_INFO(PROGRAMVERSION), + T_GATEWAY_INFO(WEBVERSION), + T_GATEWAY_INFO(SERVERIP), + T_GATEWAY_INFO(SERVERPORT), + T_GATEWAY_INFO(STATUS), + T_GATEWAY_INFO(GATEWAYUPDATE), + T_GATEWAY_INFO(MAC2)); + CreateTable(sql_exec, isDB2); + + memset(sql_exec, 0, 2048); + sprintf(sql_exec, "create table if not exists %s(%s,%s,%s,%s,%s);", + "t_data_waveSend","channelID","waveName","timeStamp","sendMsg","save"); + CreateTable(sql_exec, isDB2); + + iRet = GetTableRows(" sqlite_master "," name = 't_data_waveSend' and sql LIKE '%sendMsg%' "); + if(iRet == 0){ + CreateTable("ALTER TABLE t_data_waveSend ADD COLUMN 'sendMsg'"); + } + iRet = GetTableRows(" sqlite_master "," name = 't_data_waveSend' and sql LIKE '%save%' "); + if(iRet == 0){ + CreateTable("ALTER TABLE t_data_waveSend ADD COLUMN 'save'"); + } + /*memset(sql_exec, 0, 2048); + sprintf(sql_exec, "create table if not exists %s(%s,%s,%s,%s,%s integer,%s integer ,%s integer ,%s integer,%s integer);", + T_DATANODE_TIME(TNAME), + T_DATANODE_TIME(DATANODENO), + T_DATANODE_TIME(SHORTADDR), + T_DATANODE_TIME(STATICCYCLE), + T_DATANODE_TIME(WAVECYCLE), + T_DATANODE_TIME(NODEGROUP), + T_DATANODE_TIME(NODEINDEX), + T_DATANODE_TIME(NODEWAVEINDEX), + T_DATANODE_TIME(STATICTIME), + T_DATANODE_TIME(STATICSTARTTIME)); + CreateTable(sql_exec, isDB2);*/ + +} +void SqliteDB::Createtable(const char *ptableName) +{ + char sql_exec[2048]; + //创建传感器数据存储表 + memset(sql_exec, 0, 2048); + sprintf(sql_exec, "create table if not exists %s(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s integer,%s,%s,%s);", + ptableName, + T_DATA_INFO(DATANODENO), + T_DATA_INFO(CHANNELID), + T_DATA_INFO(DIAGNOSISEAK), + T_DATA_INFO(INTEGRATPK), + T_DATA_INFO(INTEGRATRMS), + T_DATA_INFO(RMSVALUES), + T_DATA_INFO(ENVELOPNERGY), + T_DATA_INFO(AMP1), + T_DATA_INFO(AMP2), + T_DATA_INFO(AMP3), + T_DATA_INFO(AMP4), + T_DATA_INFO(AMP5), + T_DATA_INFO(PHASE1), + T_DATA_INFO(PHASE2), + T_DATA_INFO(PHASE3), + T_DATA_INFO(PHASE4), + "StaticIndex", + T_DATA_INFO(TIMESTAMP), + "sendMsg", + "nodeResend"); + CreateTable(sql_exec, 0); + memset(sql_exec, 0, 2048); + sprintf(sql_exec,"CREATE INDEX %s_1 \ + ON %s (%s)",ptableName,ptableName,T_DATA_INFO(DATANODENO)); + CreateTable(sql_exec, 0); } +void SqliteDB::SqliteInitDel(const char *pDbName) +{ + Deletetable(T_DATA_INFO(TNAME)); + Deletetable(T_DATASTATIC_INFO(TNAME)); + vec_t vecResult = GetDataMultiLineOfOneColumn(T_SENSOR_INFO(TNAME),T_SENSOR_INFO(ZIGBEELONGADDR),NULL); + for(int i = 0; i < vecResult.size() && vecResult.size() > 0;i++) + { + char sztableName[100]={0x00}; + sprintf(sztableName,"t_data_%s",vecResult[i].c_str()); + Deletetable(sztableName); + sprintf(sztableName,"t_dataStatic_%s",vecResult[i].c_str()); + Deletetable(sztableName); + } +} +void SqliteDB::Deletetable(const char *ptableName) +{ + char sql_exec[2048]; + //创建传感器数据存储表 + memset(sql_exec, 0, 2048); + sprintf(sql_exec,"DROP TABLE %s ;",ptableName); + int iRet = sqlite3_exec(GetDbHandle(false), sql_exec, 0, 0, NULL); + if (iRet != SQLITE_OK) { + perror_info("sqlite3_exec"); + } + +} +void SqliteDB::CreatedataStatictable(const char *ptableName) +{ + char sql_exec[2048]; + //创建传感器数据存储表 + memset(sql_exec, 0, 2048); + sprintf(sql_exec, "create table if not exists %s(%s,%s,%s,%s,%s,%s,%s,%s integer,%s,%s,%s);", + ptableName, + T_DATASTATIC_INFO(DATANODENO), + T_DATASTATIC_INFO(CHANNELID), + T_DATASTATIC_INFO(TEMTOP), + T_DATASTATIC_INFO(TEMBOT), + T_DATASTATIC_INFO(DIP), + T_DATASTATIC_INFO(VOLTAGE), + "zigbeeSignal", + "StaticIndex", + T_DATASTATIC_INFO(TIMESTAMP), + "sendMsg", + "nodeResend" + //"zigbeeRSSIType" + ); + CreateTable(sql_exec, 0); + memset(sql_exec, 0, 2048); + sprintf(sql_exec,"CREATE INDEX %s_1 \ + ON %s (%s)",ptableName,ptableName,T_DATA_INFO(DATANODENO)); + CreateTable(sql_exec, 0); +} bool SqliteDB::OpenDB(const char *pDbName, bool isDB2) { if (isDB2 == false) { @@ -255,11 +427,36 @@ vec_t SqliteDB::GetDataSingleLine(const char *tablename, const char *column, con return vecResult; } - +char* SqliteDB::GetDataChar(const char *tablename, const char *column, const char *whereCon) +{ + char szRes[100]={0x00}; + std::string strSql = "select "; + if (whereCon != NULL) { + strSql = strSql + column + " from " + tablename + " where " + whereCon + ";"; + } + else { + strSql = strSql + column + " from " + tablename + ";"; + } + print_light_green("%s\n", strSql.c_str()); + // if (SqlSwitch()) log_system->log_write_system("[info]","%s\n", strSql.c_str()); + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(mDBAcess, strSql.c_str(), -1, &stmt, 0) != SQLITE_OK) { + print_error("sqlite3_prepare_v2:%s\n", sqlite3_errmsg(mDBAcess)); + sqlite3_finalize(stmt); + return NULL; + } + int retStep = sqlite3_step(stmt); + if (retStep == SQLITE_ROW) { + char *columninfo = (char*)sqlite3_column_text(stmt, 0); + memcpy(szRes,columninfo,sizeof(szRes)); + } + sqlite3_finalize(stmt); + return szRes; +} std::string SqliteDB::GetData(const char *tablename, const char *column, const char *whereCon) { - std::string strRes; + std::string strRes = ""; std::string strSql = "select "; if (whereCon != NULL) { strSql = strSql + column + " from " + tablename + " where " + whereCon + ";"; @@ -270,9 +467,11 @@ std::string SqliteDB::GetData(const char *tablename, const char *column, const c print_light_green("%s\n", strSql.c_str()); // if (SqlSwitch()) log_system->log_write_system("[info]","%s\n", strSql.c_str()); sqlite3_stmt *stmt; + g_tDbMutex.Lock(); if (sqlite3_prepare_v2(mDBAcess, strSql.c_str(), -1, &stmt, 0) != SQLITE_OK) { print_error("sqlite3_prepare_v2:%s\n", sqlite3_errmsg(mDBAcess)); sqlite3_finalize(stmt); + g_tDbMutex.UnLock(); return strRes; } int retStep = sqlite3_step(stmt); @@ -281,6 +480,7 @@ std::string SqliteDB::GetData(const char *tablename, const char *column, const c strRes = columninfo != NULL ? columninfo : ""; } sqlite3_finalize(stmt); + g_tDbMutex.UnLock(); return strRes; } @@ -294,12 +494,15 @@ array_t SqliteDB::GetDataMultiLine(const char *tablename, const char *column, co else { strSql = strSql + column + " from " + tablename + ";"; } + print_light_green("%s\n", strSql.c_str()); // if (SqlSwitch()) log_system->log_write_system("[info]","%s\n", strSql.c_str()); sqlite3_stmt *stmt; + g_tDbMutex.Lock(); if (sqlite3_prepare_v2(mDBAcess, strSql.c_str(), -1, &stmt, 0) != SQLITE_OK) { print_error("sqlite3_prepare_v2:%s\n", sqlite3_errmsg(mDBAcess)); sqlite3_finalize(stmt); + g_tDbMutex.UnLock(); return arrResult; } int retStep = sqlite3_step(stmt); @@ -315,9 +518,47 @@ array_t SqliteDB::GetDataMultiLine(const char *tablename, const char *column, co retStep = sqlite3_step(stmt); } sqlite3_finalize(stmt); + g_tDbMutex.UnLock(); return arrResult; } +array_t SqliteDB::GetDataMultiLineTransaction(const char *tablename, const char *column, const char *whereCon) +{ + array_t arrResult; + std::string strSql = "select "; + if (whereCon != NULL) { + strSql = strSql + column + " from " + tablename + " where " + whereCon + ";"; + } + else { + strSql = strSql + column + " from " + tablename + ";"; + } + print_light_green("%s\n", strSql.c_str()); +// if (SqlSwitch()) log_system->log_write_system("[info]","%s\n", strSql.c_str()); + sqlite3_exec(mDBAcess, "BEGIN", 0, 0, NULL); + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(mDBAcess, strSql.c_str(), -1, &stmt, 0) != SQLITE_OK) { + print_error("sqlite3_prepare_v2:%s\n", sqlite3_errmsg(mDBAcess)); + sqlite3_finalize(stmt); + return arrResult; + } + sqlite3_reset(stmt); + sqlite3_bind_int(stmt, 1, 0); + int retStep = sqlite3_step(stmt); + int column_count = sqlite3_column_count(stmt); + while (retStep == SQLITE_ROW) { + vec_t vecResult; + for (int iCol = 0; iCol < column_count; iCol++) { + char *columninfo = (char*)sqlite3_column_text(stmt, iCol); + std::string str = columninfo != NULL ? columninfo : ""; + vecResult.push_back(str); + } + arrResult.push_back(vecResult); + retStep = sqlite3_step(stmt); + } + sqlite3_finalize(stmt); + sqlite3_exec(mDBAcess, "COMMIT", 0, 0, NULL); + return arrResult; +} vec_t SqliteDB::GetDataMultiLineOfOneColumn(const char *tablename, const char *column, const char *whereCon) { vec_t vecResult; @@ -346,7 +587,33 @@ vec_t SqliteDB::GetDataMultiLineOfOneColumn(const char *tablename, const char *c sqlite3_finalize(stmt); return vecResult; } - +vec_Value SqliteDB::GetDataMultiLineOfOneColumnDouble(const char *tablename, const char *column, const char *whereCon) +{ + vec_Value vecResult; + std::string strSql = "select "; + if (whereCon != NULL) { + strSql = strSql + column + " from " + tablename + " where " + whereCon + ";"; + } + else { + strSql = strSql + column + " from " + tablename + ";"; + } + print_light_green("%s\n", strSql.c_str()); + // if (SqlSwitch()) log_system->log_write_system("[info]","%s\n", strSql.c_str()); + sqlite3_stmt *stmt; + if (sqlite3_prepare_v2(mDBAcess, strSql.c_str(), -1, &stmt, 0) != SQLITE_OK) { + print_error("sqlite3_prepare_v2:%s\n", sqlite3_errmsg(mDBAcess)); + sqlite3_finalize(stmt); + return vecResult; + } + int retStep = sqlite3_step(stmt); + while (retStep == SQLITE_ROW) { + double columninfo = sqlite3_column_double(stmt, 0); + vecResult.push_back(columninfo); + retStep = sqlite3_step(stmt); + } + sqlite3_finalize(stmt); + return vecResult; +} int SqliteDB::DeleteTableData(const char* tablename, const char* whereCond, bool isDB2) @@ -358,6 +625,7 @@ int SqliteDB::DeleteTableData(const char* tablename, const char* whereCond, bool else { strSql = strSql + tablename + ";"; } + // LOG_INFO("strSql = %s",strSql.c_str()); print_light_green("%s\n", strSql.c_str()); // if (SqlSwitch()) log_system->log_write_system("[info]","%s\n", strSql.c_str()); char *msg; @@ -390,7 +658,34 @@ int SqliteDB::DeleteTableDataOneConditon(const char* tablename, const char* cond } return iRet; } +int SqliteDB::UpdateNodeNameData(const char* tablename, const char* updateColumn, const char* whereCond, bool isDB2) +{ + std::string strSql = "update "; + char szSql[1024] = {0x00}; + strcat(szSql,"update "); + if (whereCond != NULL) { + strcat(szSql,tablename); + strcat(szSql," set "); + strcat(szSql,updateColumn); + strcat(szSql," where "); + strcat(szSql,whereCond); + strcat(szSql,";"); + strSql = strSql + tablename + " set " + updateColumn + " where " + whereCond + ";"; + } + else { + strSql = strSql + tablename + " set " + updateColumn + ";"; + } + print_light_green("%s\n", strSql.c_str()); + // if (SqlSwitch()) log_system->log_write_system("[info]","%s\n", strSql.c_str()); + char *msg; + int iRet = sqlite3_exec(GetDbHandle(isDB2), szSql, 0, 0, &msg); + if (iRet != SQLITE_OK) { + print_error("sqlite3 error: code=%d msg=%s\n", iRet, msg); + sqlite3_free(msg); + } + return iRet; +} int SqliteDB::UpdateTableData(const char* tablename, const char* updateColumn, const char* whereCond, bool isDB2) { std::string strSql = "update "; @@ -403,12 +698,14 @@ int SqliteDB::UpdateTableData(const char* tablename, const char* updateColumn, c print_light_green("%s\n", strSql.c_str()); // if (SqlSwitch()) log_system->log_write_system("[info]","%s\n", strSql.c_str()); char *msg; + g_tDbMutex.Lock(); int iRet = sqlite3_exec(GetDbHandle(isDB2), strSql.c_str(), 0, 0, &msg); if (iRet != SQLITE_OK) { print_error("sqlite3 error: code=%d msg=%s\n", iRet, msg); sqlite3_free(msg); } + g_tDbMutex.UnLock(); return iRet; } @@ -484,7 +781,357 @@ int SqliteDB::InsertData(const char* tablename, const char* insertValues, int re } return iRet; } +int SqliteDB::InsertData(const char* insertSql) +{ + char *msg; + int iRet = sqlite3_exec(GetDbHandle(false), insertSql, 0, 0, &msg); + if (iRet != SQLITE_OK) { + print_error("sqlite3 error: code=%d msg=%s\n", iRet, msg); + sqlite3_free(msg); + } + return iRet; +} +int SqliteDB::CalculateBattery() +{ + float dayStaticPower = 6.5,dayWavePower = 237;// + char whereCon[1024] = {0}; + char selectSql[1024] = { 0 }; + memset(whereCon,0x00,sizeof(whereCon)); + memset(selectSql,0x00,sizeof(selectSql)); + sprintf(selectSql," DataNodeNo,StaticTime,WaveTime,featureInterVal,waveInterVal,samplingRate "); + array_t vecRes ; + vecRes = GetDataMultiLine(T_SENSOR_INFO(TNAME), selectSql, NULL); + if(vecRes.size() > 0){ + for(int i = 0; i < vecRes.size(); i++){ + if(vecRes[i][5] == "12800"){ + }else if(vecRes[i][5] == "3200"){ + + } + float dayStaticTime = 0.0; + float dayWaveTime = 0.0; + if(atoi(vecRes[i][3].c_str()) == 0){ + dayStaticTime = 0; + }else{ + dayStaticTime = 24*60/atoi(vecRes[i][3].c_str()); + } + if(atoi(vecRes[i][4].c_str()) == 0){ + dayWaveTime = 0; + }else{ + dayWaveTime = 24*60/atoi(vecRes[i][4].c_str()); + } + + float dayPower = dayStaticTime * dayStaticPower + dayWaveTime * dayWavePower + 24*3.26;//static + wave + sleep + float usePower = atoi(vecRes[i][1].c_str()) * dayStaticPower + atoi(vecRes[i][2].c_str()) * dayWavePower; + if(dayPower == 0) + dayPower = 1; + float remainDay = (19000000*0.5 - usePower)/dayPower; + float bateryProportion = remainDay/(19000000*0.5/dayPower); + char updateSql[1024] = { 0x00 }; + char tmpParam[1024] = {0x00}; + memset(whereCon,0x00,sizeof(whereCon)); + memset(updateSql,0x00,sizeof(updateSql)); + sprintf(whereCon,"dataNodeNo = '%s' ",vecRes[i][0].c_str()); + sprintf(updateSql,"batteryPower = '%f,%f' ",bateryProportion,remainDay); + int iRet = UpdateTableData(T_SENSOR_INFO(TNAME), updateSql, whereCon); + print_info("iRet = %d\n",iRet); + string strData = sql_ctl->GetNodeConfigureInfor(whereCon); + data_publish(strData.c_str(), GlobalConfig::Topic_G.mPubConfig.c_str()); + } + } + + print_info("CalculateBattery \n"); + return 0; +} +int SqliteDB::CalculateDip() +{ + char whereCon[1024] = {0}; + char selectSql[1024] = { 0 }; + char updateSql[1024] = { 0 }; + memset(whereCon,0x00,sizeof(whereCon)); + memset(selectSql,0x00,sizeof(selectSql)); + sprintf(selectSql," DataNodeNo"); + array_t vecRes ; + vecRes = GetDataMultiLine(T_SENSOR_INFO(TNAME), selectSql, NULL); + for(int i = 0 ; i < vecRes.size(); i++){ + char szTablename[32]={0x00}; + sprintf(szTablename,"t_dataStatic_%s",vecRes[i][0].c_str()); + vec_Value vecResDip = GetDataMultiLineOfOneColumnDouble(szTablename," Dip ", NULL); + float sample_variance = pCalculation->getSample_variance(vecResDip); + print_info("sample_variance = %f\n",sample_variance); + memset(whereCon,0x00,sizeof(whereCon)); + memset(updateSql,0x00,sizeof(updateSql)); + sprintf(whereCon,"dataNodeNo = '%s' ",vecRes[i][0].c_str()); + sprintf(updateSql,"LooseValue = '%f' ",sample_variance); + UpdateTableData(T_SENSOR_INFO(TNAME),updateSql,whereCon); + } +} +int SqliteDB::InintGateway() +{ + //更新网关配置表 + string strIP = GetGwIp_("eth0"); + string strServerIP = ReadStrByOpt(SERVERCONFIG, "Server", "localServerIpAddress"); + string strServerPort = ReadStrByOpt(SERVERCONFIG, "Server", "localServerPort"); + string strwebVersion = ReadStrByOpt(SYSTEMINFOFILE, "Version", "WebVersion"); + string strsystemVersion = ReadStrByOpt(SYSTEMINFOFILE, "Version", "SystemVersion"); + string strGatewayVersion = ReadStrByOpt(SYSTEMINFOFILE, "Version", "GateWayVersion"); + std::string strchan = ReadStrByOpt(ZIGBEECONFIG, "Zigbee", "channel"); + if(0 == sql_ctl->GetTableRows(T_GATEWAY_INFO(TNAME), NULL)){ + + char strSql[1024] = { 0 }; + sprintf(strSql,"insert into t_gateway_info(gatewayMAC,zigbeePanID,zigbeeChannel,\ + localIP,systemVersion,programVersion,webVersion,serverIP,serverPort,MAC2)\ + values('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s');",GlobalConfig::MacAddr_G.c_str(),GlobalConfig::MacAddr_G.substr(8).c_str(),strchan.c_str(),strIP.c_str(),\ + strsystemVersion.c_str(),strGatewayVersion.c_str(),strwebVersion.c_str(),strServerIP.c_str(),strServerPort.c_str(),GlobalConfig::MacAddr_G2.c_str()); + sql_ctl->InsertData(strSql); + print_info("strSql = %s\n",strSql); + }else{ + char whereCon[1024] = {0}; + char updateSql[1024] = { 0 }; + sprintf(updateSql, "zigbeePanID = '%s',zigbeeChannel = '%s',localIP = '%s',systemVersion='%s',programVersion='%s',webVersion='%s',serverIP='%s',serverPort='%s'",\ + GlobalConfig::MacAddr_G.substr(8).c_str(),strchan.c_str(),strIP.c_str(),\ + strsystemVersion.c_str(),strGatewayVersion.c_str(),strwebVersion.c_str(),strServerIP.c_str(),strServerPort.c_str()); + sprintf(whereCon, "gatewayMAC='%s'", GlobalConfig::MacAddr_G.c_str()); + sql_ctl->UpdateTableData(T_GATEWAY_INFO(TNAME), updateSql, whereCon); + } + + //上传网关配置到MQTT + Json::Value jsSystemSetting; + Json::Value jsBody; + Json::FastWriter showValue; + Json::Value jsonVal; + jsonVal.clear(); + + jsonVal["cmd"] = "23"; + jsonVal["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; + jsSystemSetting["WebVersion"] = strwebVersion; + jsSystemSetting["SystemVersion"] = strsystemVersion; + jsSystemSetting["GateWayVersion"] = strGatewayVersion; + jsBody["localServerIpAddress"] = ReadStrByOpt(SERVERCONFIG, "Server", "localServerIpAddress"); + jsBody["localServerPort"] = atoi(ReadStrByOpt(SERVERCONFIG, "Server", "localServerPort").c_str()); + jsBody["CommMode"] = atoi(ReadStrByOpt(SERVERCONFIG, "Server", "CommMode").c_str()); + jsBody["Password"] = (ReadStrByOpt(SERVERCONFIG, "Server", "Password")); + jsBody["UserName"] = (ReadStrByOpt(SERVERCONFIG, "Server", "UserName")); + std::string dataBody = showValue.write(jsBody); + jsonVal["cmdBody"] = dataBody; + data_publish(showValue.write(jsonVal).c_str(), GlobalConfig::Topic_G.mPubConfig.c_str()); + + jsBody.clear(); + jsonVal["cmd"] = "25"; + jsBody["dnsName"] = ReadStrByOpt(NETWORKCONFIG, "Net", "dnsName"); + jsBody["networkPortStatus"] = ReadStrByOpt(NETWORKCONFIG, "Net", "networkPortStatus"); + jsBody["gateway"] = ReadStrByOpt(NETWORKCONFIG, "Net", "gateway"); + jsBody["subnetMask"] = ReadStrByOpt(NETWORKCONFIG, "Net", "subnetMask"); + jsBody["dataWatchIpAddress"] = ReadStrByOpt(NETWORKCONFIG, "Net", "ipAddress"); + jsBody["hostName"] = ReadStrByOpt(NETWORKCONFIG, "Net", "hostName"); + + dataBody = showValue.write(jsBody); + jsonVal["cmdBody"] = dataBody; + data_publish(showValue.write(jsonVal).c_str(), GlobalConfig::Topic_G.mPubConfig.c_str()); +} + +std::string SqliteDB::GetNodeConfigureInfor(const char* whereCon) +{ + vec_t vecRes = GetDataSingleLine(T_SENSOR_INFO(TNAME), "*", whereCon); + printf("vecRes = %d\n",vecRes.size()); + if(vecRes.size() < 1) + return ""; + Json::Value jsSensorData; + Json::Value jsonVal; + jsonVal.clear(); + jsonVal["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; + jsonVal["cmd"] = "26"; + jsSensorData["dataNodeNo"] = vecRes[0]; + jsSensorData["dataNodeName"] = vecRes[1]; + jsSensorData["initFlag"] = atoi(vecRes[2].c_str()); + jsSensorData["accFlag"] = atoi(vecRes[3].c_str()); + jsSensorData["zigbeeFlag"] = atoi(vecRes[4].c_str()); + jsSensorData["temTopFlag"] = atoi(vecRes[5].c_str()); + jsSensorData["temBotFlag"] = atoi(vecRes[6].c_str()); + jsSensorData["hardVersion"] = vecRes[8]; + jsSensorData["softVersion"] = vecRes[9]; + jsSensorData["bpNo"] = vecRes[10]; + jsSensorData["serialNo"] = vecRes[11]; + jsSensorData["firstPowerTime"] = vecRes[12]; + jsSensorData["WakeupTime"] = atoi(vecRes[13].c_str()); + jsSensorData["StaticTime"] = atoi(vecRes[14].c_str()); + jsSensorData["WaveTime"] = atoi(vecRes[15].c_str()); + jsSensorData["BateryV"] = vecRes[16]; + jsSensorData["ProductNo"] = vecRes[17]; + jsSensorData["configFlag"] = atoi(vecRes[18].c_str()); + jsSensorData["startBrands"] = vecRes[19]; + jsSensorData["stopBrands"] = vecRes[20]; + jsSensorData["featureInterVal"] = (vecRes[21]); + jsSensorData["waveInterVal"] = atoi(vecRes[22].c_str()); + jsSensorData["samplingRate"] = atoi(vecRes[23].c_str()); + jsSensorData["range"] = atoi(vecRes[25].c_str()); + jsSensorData["envelopeBandPass"] = vecRes[26]; + jsSensorData["faultFrequency"] = vecRes[27]; + jsSensorData["zigbeePanId"] = vecRes[28]; + jsSensorData["zigbeeChannel"] = (vecRes[29]); + jsSensorData["zigbeeAddr"] = vecRes[30]; + jsSensorData["zigbeeLongAddr"] = vecRes[31]; + jsSensorData["zigbeeDesAddr"] = vecRes[32]; + jsSensorData["ZigbeePower"] = atoi(vecRes[33].c_str()); + jsSensorData["ZigbeeRetry"] = atoi(vecRes[34].c_str()); + jsSensorData["ZigbeeRetryGap"] = atoi(vecRes[35].c_str()); + jsSensorData["ACCSampleTime"] = atoi(vecRes[36].c_str()); + jsSensorData["status"] = atoi(vecRes[37].c_str()); + jsSensorData["timeStamp"] = vecRes[38]; + jsSensorData["viff"] = atoi(vecRes[39].c_str()); + jsSensorData["RSSI"] = atoi(vecRes[40].c_str()); + jsSensorData["Update"] = atoi(vecRes[41].c_str()); + jsSensorData["LooseValue"] = (vecRes[42].c_str()); + jsSensorData["batteryPower"] = (vecRes[43].c_str()); + + Json::FastWriter showValue; + Json::Value jsBody; + jsBody["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; + jsBody["dataNodeData"] = jsSensorData; + std::string dataBody = showValue.write(jsBody); + jsonVal["cmdBody"] = dataBody; + return showValue.write(jsonVal); +} + +int SqliteDB::QueryofflineData() +{ + vec_t vecRet = GetDataMultiLineOfOneColumn(T_SENSOR_INFO(TNAME),T_SENSOR_INFO(DATANODENO),NULL); + for(int i = 0; i < vecRet.size();i++){ + char StaticTableName[50]={0x00}; + sprintf(StaticTableName,"t_dataStatic_%s",vecRet[i].c_str()); + + array_t arrRetData = GetDataMultiLine(StaticTableName, "*","sendMsg = '0' order by timeStamp asc"); + LOG_INFO("mqttresend check datanodeNo %s,data count %d\n",vecRet[i].c_str(),arrRetData.size()); + if(arrRetData.size() < 1) + continue; + for(int j = 0; j < arrRetData.size();j++){ + char dataTableName[50]={0x00}; + sprintf(dataTableName,"t_data_%s",vecRet[i].c_str()); + char tmpWhere[128]={0x00}; + sprintf(tmpWhere,"sendMsg = '0' and timeStamp = '%s'",arrRetData[j][8].c_str()); + array_t arrRet = GetDataMultiLine(dataTableName, "*","sendMsg = '0'"); + if(arrRet.size() > 0){ + Json::Value valNodeData; + Json::Value valNodeFeature; + for(int k = 0; k < arrRet.size();k++){ + + valNodeFeature["dataNodeNo"] = arrRet[k][0].c_str(); + valNodeFeature["ChannelId"] = arrRet[k][1].c_str(); + valNodeFeature["diagnosisPk"] = atof(arrRet[k][2].c_str()); + valNodeFeature["integratPk"] = atof(arrRet[k][3].c_str()); + valNodeFeature["integratRMS"] = atof(arrRet[k][4].c_str()); + valNodeFeature["rmsValues"] = atof(arrRet[k][5].c_str()); + valNodeFeature["envelopEnergy"] = atof(arrRet[k][6].c_str()); + valNodeFeature["Amp1"] = atof(arrRet[k][7].c_str()); + valNodeFeature["Amp2"] = atof(arrRet[k][8].c_str()); + valNodeFeature["Amp3"] = atof(arrRet[k][9].c_str()); + valNodeFeature["Amp4"] = atof(arrRet[k][10].c_str()); + valNodeFeature["Amp5"] = atof(arrRet[k][1].c_str()); + valNodeFeature["Phase1"] = atof(arrRet[k][12].c_str()); + valNodeFeature["Phase2"] = atof(arrRet[k][13].c_str()); + valNodeFeature["Phase3"] = atof(arrRet[k][14].c_str()); + valNodeFeature["Phase4"] = atof(arrRet[k][15].c_str()); + valNodeFeature["timeStamp"] = atoi(arrRet[k][17].c_str()); + valNodeData.append(valNodeFeature); + } + } + //无线传感器信息 + Json::Value root; + Json::Value valdatastatic; + Json::Value valNodeData; + valdatastatic["TemperatureTop"] = atof(arrRetData[j][2].c_str()); + valdatastatic["TemperatureBot"] = atof(arrRetData[j][3].c_str()); + valdatastatic["Dip"] = atof(arrRetData[j][4].c_str()); + valdatastatic["Voltage"] = atof(arrRetData[j][5].c_str()); + valdatastatic["ChannelType"] = "STATUS"; + valdatastatic["ChannelId"] = (arrRetData[j][1].c_str()); + valdatastatic["TimeStamp"] = atoi(arrRetData[j][8].c_str()); + + valdatastatic["dataNodeNo"] = arrRetData[j][0].c_str(); + valNodeData.append(valdatastatic); + + root["data"] = valNodeData; + root["TimeStamp"] = atoi(arrRetData[j][8].c_str()); + root["dataNodeNo"] = arrRetData[j][0].c_str(); + root["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; + root["status"] = "resend"; + Json::FastWriter featureValue; + std::string strstatisticData = featureValue.write(root); + + int iRet = data_publish(strstatisticData.c_str(), GlobalConfig::Topic_G.mPubData.c_str()); + //print_info("dataNodeNo = '%s' and TimeStamp = '%s',MQTT ret = %d\n",arrRetData[j][0].c_str(),nowTimetamp.c_str(),iRet); + if(iRet == 0){ + char updateSql[1024] = { 0 }; + char whereCon[64] = { 0 }; + memset(whereCon, 0, 64); + sprintf(whereCon, "dataNodeNo = '%s' and TimeStamp = '%s'", arrRetData[j][0].c_str(),arrRetData[j][8].c_str()); + memcpy(updateSql, "sendMsg='1'",sizeof(updateSql)); + sql_ctl->UpdateTableData(StaticTableName, updateSql, whereCon); + sql_ctl->UpdateTableData(dataTableName, updateSql, whereCon); + LOG_INFO("resend success dataNodeNo = %s,TimeStamp = '%s'\n",arrRetData[j][0].c_str(),arrRetData[j][8].c_str()); + } + sleep(1); + } + } + char whereCon[1024] = {0x00}; + sprintf(whereCon, " SendMsg = 0 "); + array_t arrRetData = GetDataMultiLine("t_data_waveSend", "*",whereCon); + LOG_INFO("mqttresend check wave count %d\n",arrRetData.size()); + if(arrRetData.size() > 0){ + for(int i = 0; i < arrRetData.size();i++){ + std::string strWaveData = ""; + if (access(arrRetData[i][1].c_str(), 0) >= 0) + { + std::vector vecWave; + char localtimestamp[32] = { 0 }; + float fTemp = 0; + std::ifstream inFile(arrRetData[i][1].c_str(),ios::in|ios::binary); + inFile.read((char *)localtimestamp,sizeof(localtimestamp)); + while(inFile.read((char *)&fTemp,sizeof(fTemp))){ + vecWave.push_back(fTemp); + } + + for (int i = 0; i < vecWave.size(); i++) { + char buf[33]={0x00}; + memset(buf,0x00,sizeof(buf)); + sprintf(buf, "%.2f", vecWave[i]); + std::string waveTemp(buf); + if(i == 0){ + strWaveData = waveTemp; + } + strWaveData = strWaveData + "," + waveTemp; + } + inFile.close(); + } + Json::Value valWaveData; + int length = strWaveData.length(); + valWaveData["number"] = length; + valWaveData["channelId"] = arrRetData[i][0]; + valWaveData["dataNodeNo"] = arrRetData[i][0]; + valWaveData["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; + valWaveData["SensorEngineeringUnit"] = ""; + valWaveData["timeStamp"] = arrRetData[i][2]; + valWaveData["waveData"] = strWaveData; + Json::FastWriter WaveValue; + std::string WaveData = WaveValue.write(valWaveData); + int iRet = data_publish(WaveData.c_str(), GlobalConfig::Topic_G.mPubWaveData.c_str()); + if(iRet == 0){ + char whereCon[1024] = {0x00}; + char updateSql[1024] = {0x00}; + sprintf(whereCon, "channelID='%s' and timeStamp = '%s' ", arrRetData[i][0].c_str(),arrRetData[i][2].c_str()); + sprintf(updateSql, "SendMsg = 1"); + sql_ctl->UpdateTableData("t_data_waveSend", updateSql, whereCon); + //char whereCon[64]={0x00}; + //sprintf(whereCon,"waveName = '%s'",arrRetData[i][1].c_str()); + //DeleteTableData("t_data_waveSend", whereCon); + std::string strCmd = "rm " + arrRetData[i][1]; + system(strCmd.c_str()); + LOG_INFO("resend success waveName = %s\n",arrRetData[i][1].c_str()); + } + } + + } +} int SqliteDB::TransBegin() { return sqlite3_exec(mDBAcess, "begin;", 0, 0, 0); diff --git a/dbaccess/SH_SqlDB.hpp b/dbaccess/SH_SqlDB.hpp index 43f942e..afd1a7b 100644 --- a/dbaccess/SH_SqlDB.hpp +++ b/dbaccess/SH_SqlDB.hpp @@ -14,9 +14,12 @@ extern "C"{ #define T_SENSOR_INFO(x) T_SENSOR_INFO[T_SENSOR_INFO_##x] #define T_DATA_INFO(x) T_DATA_INFO[T_DATA_INFO_##x] #define T_DATASTATIC_INFO(x) T_DATASTATIC_INFO[T_DATASTATIC_INFO_##x] +#define T_GATEWAY_INFO(x) T_GATEWAY_INFO[T_GATEWAY_INFO_##x] +#define T_DATANODE_TIME(x) T_DATANODE_TIME[T_DATANODE_TIME_##x] typedef std::map map_t; typedef std::vector vec_t; +typedef std::vector vec_Value; typedef std::vector array_t; class SqliteDB : public MySingleton < SqliteDB > { @@ -25,6 +28,10 @@ public: virtual ~SqliteDB(); bool OpenDB(const char *pDbName, bool isDB2=false); void SqliteInit(const char *pDbName, bool isDB2=false); + void SqliteInitDel(const char *pDbName); + void Createtable(const char *ptableName); + void Deletetable(const char *ptableName); + void CreatedataStatictable(const char *ptableName); int TransBegin(); int TransRollback(); int TransCommit(); @@ -34,14 +41,24 @@ public: int AlterTable(const char *tablename, const char *column, bool isAdd = true, bool isDB2=false); vec_t GetDataSingleLine(const char *tablename, const char *column, const char *whereCon); std::string GetData(const char *tablename, const char *column, const char *whereCon); + char* GetDataChar(const char *tablename, const char *column, const char *whereCon); array_t GetDataMultiLine(const char *tablename, const char *column, const char *whereCon); + array_t GetDataMultiLineTransaction(const char *tablename, const char *column, const char *whereCon); vec_t GetDataMultiLineOfOneColumn(const char *tablename, const char *column, const char *whereCon); + vec_Value GetDataMultiLineOfOneColumnDouble(const char *tablename, const char *column, const char *whereCon); int DeleteTableData(const char* tablename, const char* whereCond = NULL, bool isDB2=false); int DeleteTableDataOneConditon(const char* tablename, const char* condColumnName, const char * condColumnValue, bool isDB2=false); int UpdateTableData(const char* tablename, const char* updateColumn, const char* whereCond, bool isDB2 = false); + int UpdateNodeNameData(const char* tablename, const char* updateColumn, const char* whereCond, bool isDB2 = false); int UpdateTableDataOneColumn(const char* tablename, const char* columnName, const char* columnValue, const char* whereColName = NULL, const char * whereColValue = NULL, bool isDB2 = false); int UpdateTableData(const char* directSql, bool isDB2 = false); int InsertData(const char* tablename, const char* insertValues, int replace = 0, bool expandalbe = false, bool isDB2 = false); + int InsertData(const char* insertSql); + int CalculateBattery(); + int CalculateDip(); + int InintGateway(); + int QueryofflineData(); + std::string GetNodeConfigureInfor(const char* whereCon); int CloseDB(); private: @@ -107,9 +124,12 @@ typedef enum { T_DATA_INFO_PHASE2, T_DATA_INFO_PHASE3, T_DATA_INFO_PHASE4, + T_DATA_INFO_STATICINDEX, T_DATA_INFO_TIMESTAMP, + T_DATA_INFO_SENDMSG, + T_DATA_INFO_NODERESEND }T_DATA_INFO_Index; -const static char* T_DATA_INFO[] = { "t_data_info", "dataNodeNo", "channelID", "diagnosisPk", "integratPk","integratRMS","rmsValues","envelopEnergy","Amp1","Amp2","Amp3","Amp4","Amp5","Phase1","Phase2","Phase3","Phase4","timeStamp"}; +const static char* T_DATA_INFO[] = { "t_data_info", "dataNodeNo", "channelID", "diagnosisPk", "integratPk","integratRMS","rmsValues","envelopEnergy","Amp1","Amp2","Amp3","Amp4","Amp5","Phase1","Phase2","Phase3","Phase4","StaticIndex","timeStamp","sendMsg","nodeResend"}; typedef enum { @@ -120,8 +140,46 @@ typedef enum { T_DATASTATIC_INFO_TEMBOT, T_DATASTATIC_INFO_DIP, T_DATASTATIC_INFO_VOLTAGE, + T_DATASTATIC_INFO_STATICINDEX, T_DATASTATIC_INFO_TIMESTAMP, + T_DATASTATIC_INFO_SENDMSG, + T_DATASTATIC_INFO_NODERESEND }T_DATASTATIC_INFO_Index; -const static char* T_DATASTATIC_INFO[] = { "t_datastatic_info","dataNodeNo","channelID","temTop","temBot","dip","voltage","timeStamp"}; +const static char* T_DATASTATIC_INFO[] = { "t_datastatic_info","dataNodeNo","channelID","temTop","temBot","dip","voltage","StaticIndex","timeStamp","sendMsg","nodeResend"}; +typedef enum { + T_DATANODE_TIME_TNAME = 0, + T_DATANODE_TIME_DATANODENO, + T_DATANODE_TIME_SHORTADDR, + T_DATANODE_TIME_STATICCYCLE, + T_DATANODE_TIME_WAVECYCLE, + T_DATANODE_TIME_NODEGROUP, + T_DATANODE_TIME_NODEINDEX, + T_DATANODE_TIME_NODEWAVEINDEX, + T_DATANODE_TIME_STATICTIME, + T_DATANODE_TIME_STATICSTARTTIME +}T_DATANODE_TIME_Index; +const static char* T_DATANODE_TIME[] = { "t_datanode_time","dataNodeNo","shortaddr","staticcycle","wavecycle","nodegroup","nodeindex","nodewaveindex","statictime","staticstarttime"}; + + +typedef enum { + T_GATEWAY_INFO_TNAME = 0, + T_GATEWAY_INFO_GATEWAYMAC, + T_GATEWAY_INFO_SENSORVER, + T_GATEWAY_INFO_GATEWAYLOCATION, + T_GATEWAY_INFO_ZIGBEEPANID, + T_GATEWAY_INFO_ZIGBEECHANNEL, + T_GATEWAY_INFO_COMMUNICATIONTYPE, + T_GATEWAY_INFO_SIGNAL, + T_GATEWAY_INFO_LOCALIP, + T_GATEWAY_INFO_SYSTEMVERSION, + T_GATEWAY_INFO_PROGRAMVERSION, + T_GATEWAY_INFO_WEBVERSION, + T_GATEWAY_INFO_SERVERIP, + T_GATEWAY_INFO_SERVERPORT, + T_GATEWAY_INFO_STATUS, + T_GATEWAY_INFO_GATEWAYUPDATE, + T_GATEWAY_INFO_MAC2, +}T_GATEWAY_INFO_Index; +const static char* T_GATEWAY_INFO[] = { "t_gateway_info","gatewayMAC","sensorVersion","gatewayLocation","zigbeePanID","zigbeeChannel","communicationType","signal","localIP","systemVersion","programVersion","webVersion","serverIP","serverPort","status","gateWayUpdate","MAC2"}; #endif diff --git a/dial5G/Dial.cpp b/dial5G/Dial.cpp new file mode 100644 index 0000000..d1158f1 --- /dev/null +++ b/dial5G/Dial.cpp @@ -0,0 +1,296 @@ +/* + * Dial.cpp + * + * Created on: 2023年6月13日 + * Author: chaos + */ +#include +#include +#include +#include +#include +#include +#include "../common/SH_CommonFunc.hpp" +#include "Dial.h" + + +Dial::Dial() { + // TODO Auto-generated constructor stub + m_fd = 0; + m_curState = CPIN; + m_dial = 0; + m_APN = 0; +} + +Dial::~Dial() { + // TODO Auto-generated destructor stub +} + +int Dial::openPort(const char* pPort) +{ + m_fd = config_uart(pPort,115200); + print_info("m_fd = %d\n",m_fd); + return m_fd; +} +int Dial::parseData(Event event,const char* pData) +{ + print_info("m_curState = %d,event = %d\n",m_curState,event); + string signal; + string ret; + std::string str; + int pos = 0; + switch(event){ + case Event_CPIN: + if(!strncmp(pData,"READY",5)){ + m_curState = QCFGNET; + }else if(!strncmp(pData,"NOT READY",9)){ + m_curState = CPIN; + GlobalConfig::NetStatus = "\"LIMSRV\""; + } + break; + case Event_QCFGNET: + case Event_QCFGSMS: + /*ret = GetOneContent(pData,1,","); + if(ret == "0") + { + m_curState = QICSGPAPN; + }*/ + break; + case Event_QICSGPAPN: + //if(!strcmp(pData,"OK")) + { + m_curState = QNETDEVCTL; + } + break; + case Event_QENG: + GlobalConfig::NetStatus = GetOneContent(pData,1,","); + GlobalConfig::NetType = GetOneContent(pData,2,","); + signal = GetOneContent(pData,12,","); + GlobalConfig::NetSignal = atoi(signal.c_str()); + print_info("NetStatus = %s,NetSignal = %d\n",GlobalConfig::NetStatus.c_str(),GlobalConfig::NetSignal); + break; + case Event_QNETDEVCTL: + print_info("m_curState Event_QNETDEVCTL = %d\n",m_curState); + if(m_dial == 1){ + m_curState = QNETDEVSTATUS; + } + break; + case Event_QNETDEVSTATUS: + ret = GetOneContent(pData,3,","); + if(ret == "0" || ret == "") + m_curState = QDCHPC; + else + m_curState = QNETDEVSTATUS; + break; + case Event_OK: + if(m_curState == QNETDEVCTL && m_dial == 1) + { + m_dial = 0; + m_curState = QNETDEVSTATUS; + } + if(m_curState == Event_QCFGNET){ + m_curState = QNETDEVCTL; + } + if(m_curState == QICSGPAPN && m_APN == 1) + { + m_APN = 0; + m_curState = QNETDEVCTL; + } + + break; + case Event_ERROR: + if(m_curState == CPIN && !strcmp(pData,"3")){ + m_curState = CPIN; + GlobalConfig::NetStatus = "\"LIMSRV\""; + } + if(m_curState == QNETDEVCTL){ + m_curState = QNETDEVSTATUS; + } + break; + case Event_TEMP: + str = string(pData); + pos = str.find("soc-thermal"); + if(pos > 0){ + std::string socTmp = str.substr(pos+14,2); + GlobalConfig::NR5GTemp = socTmp; + print_info("NR5GTemp = %s\n",GlobalConfig::NR5GTemp.c_str()); + } + + + break; + default: + break; + } +} +int Dial::recvData() +{ + + char szbuffer[200]={0x00}; + int offSize = 0; + int timeoutflag = 0; + while(1) + { + char buff[1024]={0x00}; + + int ret = read_data(m_fd, buff, 1024, 10); + if(ret <= 0){ + timeoutflag ++; + if(timeoutflag > 5) + { + timeoutflag = 0; + const char *strQENG = "+QENG: "; + const char *strQNETDEVCTL = "+QNETDEVCTL: "; + const char *strQICSGP = "+QICSGP: "; + const char *strQNETDEVSTATUS= "+QNETDEVSTATUS: "; + const char *strQCFG= "+QCFG: "; + const char *strCPIN= "+CPIN: "; + const char *strERROR= "+CME ERROR: "; + const char *strQTEMP= "+QTEMP: "; + const char *strOK= "OK"; + char data[128] = {0}; + char *pdata = strstr((char*)szbuffer, strQENG); + if(pdata){ + strncpy(data, pdata+7, sizeof(data)); + print_purple("strQENG = %s\n",data); + parseData(Event_QENG,data); + } + pdata = strstr((char*)szbuffer, strQNETDEVCTL); + if(pdata){ + strncpy(data, pdata+13, sizeof(data)); + print_purple("strQNETDEVCTL = %s\n",data); + parseData(Event_QNETDEVCTL,data); + } + pdata = strstr((char*)szbuffer, strQICSGP); + if(pdata){ + strncpy(data, pdata+9, sizeof(data)); + print_purple("strQICSGP = %s\n",data); + parseData(Event_QICSGPAPN,data); + } + pdata = strstr((char*)szbuffer, strQNETDEVSTATUS); + if(pdata){ + strncpy(data, pdata+16, sizeof(data)); + print_purple("strQNETDEVSTATUS = %s\n",data); + parseData(Event_QNETDEVSTATUS,data); + } + pdata = strstr((char*)szbuffer, strQCFG); + if(pdata){ + strncpy(data, pdata+7, sizeof(data)); + print_purple("strQCFG = %s\n",data); + parseData(Event_QCFGNET,data); + } + pdata = strstr((char*)szbuffer, strCPIN); + if(pdata){ + strncpy(data, pdata+7, sizeof(data)); + print_purple("strCPIN = %s\n",data); + parseData(Event_CPIN,data); + } + pdata = strstr((char*)szbuffer, strQTEMP); + if(pdata){ + strncpy(data, pdata+8, sizeof(data)); + print_purple("strQTEMP = %s\n",data); + parseData(Event_TEMP,data); + } + pdata = strstr((char*)szbuffer, strERROR); + if(pdata){ + strncpy(data, pdata+12, sizeof(data)); + print_purple("strERROR = %s\n",data); + parseData(Event_ERROR,data); + } + pdata = strstr((char*)szbuffer, strOK); + if(pdata){ + parseData(Event_OK,data); + } + memset(szbuffer,0x00,sizeof(szbuffer)); + offSize = 0; + } + usleep(100); + }else if(ret > 0){ + print_info("ret = %d,buff = %s\n",ret,buff); + memcpy(szbuffer + offSize,buff,ret); + offSize = offSize + ret; + print_info("szbuffer = %s\n",szbuffer); + continue; + } + usleep(500000); + } +} +int Dial::queryPin() +{ + int iRet = write_data(m_fd,"AT+CPIN?\r\n",12); +} +int Dial::configNet() +{ + write_data(m_fd,"AT+QCFG=\"NAT\"\r\n",19); +} +int Dial::configApn() +{ + m_APN = 1; + std::string strAPN = ReadStrByOpt(SERVERCONFIG, "Server", "APN"); + char szCmd[100]={0x00}; + sprintf(szCmd,"AT+QICSGP=1,1,\"%s\",\"\",\"\",1\r\n",strAPN.c_str()); + int iRet = write_data(m_fd,szCmd,strlen(strAPN.c_str()) + 34); + print_info("configApn = %d,data = %s\n",iRet,szCmd); +} +int Dial::getCsq() +{ + write_data(m_fd,"AT+QENG=\"servingcell\"\r\n",27); +} +int Dial::getTemp() +{ + write_data(m_fd,"AT+QTEMP\r\n",12); +} +int Dial::conncectUSB() +{ + int iRet = write_data(m_fd,"AT+QNETDEVCTL=1,1,1\r\n",23); + print_info("conncectUSB = %d\n",iRet); +} +int Dial::dial5G() +{ + while(1){ + + if(m_curState == CPIN){ + queryPin(); + } + if(m_curState == QCFGNET){ + configNet(); + //configims(); + } + if(m_curState == QICSGPAPN){ + configApn(); + } + if(m_curState == QENG){ + getCsq(); + + } + if(m_curState == QNETDEVCTL){ + conncectUSB(); + m_dial = 1; + } + if(m_curState == QNETDEVSTATUS){ + write_data(m_fd,"AT+QNETDEVSTATUS=1\r\n",22); + } + if(m_curState == QDCHPC){ + configdhcp(); + m_curState = QENG; + } + sleep(5); + getTemp(); + sleep(15); + } +} +int Dial::configims() +{ + write_data(m_fd,"AT+QCFG=\"ims\",0\r\n",21); +} +int Dial::configdhcp() +{ + system("busybox udhcpc -f -n -q -t 5 -i usb0"); +} +int Dial::setState() +{ + m_curState = CPIN; +} +int Dial::closePort() +{ + close(m_fd); +} diff --git a/dial5G/Dial.h b/dial5G/Dial.h new file mode 100644 index 0000000..e4b18cd --- /dev/null +++ b/dial5G/Dial.h @@ -0,0 +1,70 @@ +/* + * Dial.h + * + * Created on: 2023年6月13日 + * Author: chaos + */ + +#ifndef DIAL5G_DIAL_H_ +#define DIAL5G_DIAL_H_ +#include +#include "../common/SH_global.h" +using namespace std; +class Dial { +public: + Dial(); + virtual ~Dial(); + + //枚举所有状态 + enum State + { + CPIN = 0, + QCFGNET, + QICSGPAPN, + QCFGSMS, + QENG, + QNETDEVCTL, + QNETDEVSTATUS, + QDCHPC, + NORMAL + }; + + //枚举所有事件 + enum Event + { + Event_CPIN = 0, + Event_QCFGNET, + Event_QICSGPAPN, + Event_QCFGSMS, + Event_QENG, + Event_QNETDEVCTL, + Event_QNETDEVSTATUS, + Event_OK, + Event_ERROR, + Event_TEMP + }; + + State m_curState; + int m_fd; + int m_dial; + int m_APN; + int openPort(const char* pPort); + int closePort(); + int recvData(); + int queryPin(); + int configNet(); + int configApn(); + int getCsq(); + int getTemp(); + int conncectUSB(); + int dial5G(); + int configims(); + int configdhcp(); + int parseData(Event event,const char* pData); + int setState(); + + + +}; + +#endif /* DIAL5G_DIAL_H_ */ diff --git a/jsonparse/SH_JsonCmd.cpp b/jsonparse/SH_JsonCmd.cpp index 4484706..9d488d0 100644 --- a/jsonparse/SH_JsonCmd.cpp +++ b/jsonparse/SH_JsonCmd.cpp @@ -1,6 +1,8 @@ #include "SH_JsonCmd.hpp" #include "../dbaccess/SH_SqlDB.hpp" #include "../platform/SH_PlatformInit.hpp" +#include "../MD5/md5.h" + namespace{ PlatformInit *platform = PlatformInit::instance(); @@ -35,7 +37,15 @@ std::string JsonData::JsonCmd_20(Param_20 ¶m) Json::Value jsSystemInfo; Json::Value jsBody; - + + string strwebVersion = ReadStrByOpt(SYSTEMINFOFILE, "Version", "WebVersion"); + string strsystemVersion = ReadStrByOpt(SYSTEMINFOFILE, "Version", "SystemVersion"); + string strGatewayVersion = ReadStrByOpt(SYSTEMINFOFILE, "Version", "GateWayVersion"); + + jsSystemInfo["WebVersion"] = strwebVersion; + jsSystemInfo["SystemVersion"] = strsystemVersion; + jsSystemInfo["GateWayVersion"] = strGatewayVersion; + jsSystemInfo[JSON_FIELD_NAME] = ReadStrByOpt(SYSTEMINFOFILE, "SystemInfo", "dataNodeGatewayName"); jsSystemInfo[JSON_FIELD_dataNodeGatewayNo] = GlobalConfig::MacAddr_G; jsSystemInfo[JSON_FIELD_ASSETID] = ReadStrByOpt(SYSTEMINFOFILE, "SystemInfo", "dataNodeGatewayAssetId"); @@ -50,8 +60,8 @@ std::string JsonData::JsonCmd_20(Param_20 ¶m) jsSystemInfo["zigbeeChannel"] = GlobalConfig::ZigbeeInfo_G.Channel; jsSystemInfo["zigbeeAddr"] = GlobalConfig::ZigbeeInfo_G.MyAddr; jsSystemInfo[JSON_FIELD_SERVERIP] = ReadStrByOpt(SERVERCONFIG, "Server", "localServerIpAddress"); - jsSystemInfo[JSON_FIELD_SERVERPORT] = boost::lexical_cast(ReadStrByOpt(SERVERCONFIG, "Server", "localServerPort")); - jsSystemInfo[JSON_FIELD_CommMode] = boost::lexical_cast(ReadStrByOpt(SERVERCONFIG, "Server", "CommMode")); + jsSystemInfo[JSON_FIELD_SERVERPORT] = atoi(ReadStrByOpt(SERVERCONFIG, "Server", "localServerPort").c_str()); + jsSystemInfo[JSON_FIELD_CommMode] = atoi(ReadStrByOpt(SERVERCONFIG, "Server", "CommMode").c_str()); jsBody["SystemInfo"] = jsSystemInfo; std::string dataBody = showValue.write(jsBody); @@ -96,11 +106,18 @@ std::string JsonData::JsonCmd_23(Param_23 ¶m) WriteStr2Config(SERVERCONFIG, "Server", "localServerIpAddress", param.mServerIp); WriteStr2Config(SERVERCONFIG, "Server", "localServerPort", param.mPort); WriteStr2Config(SERVERCONFIG, "Server", "CommMode", param.mCommMode); - printf("param.mCommMode = %s\n",param.mCommMode.c_str()); + WriteStr2Config(SERVERCONFIG, "Server", "Password", param.mPassword); + WriteStr2Config(SERVERCONFIG, "Server", "UserName", param.mUserName); + print_info("param.mCommMode = %s\n",param.mCommMode.c_str()); if("1" == param.mCommMode){//有线连接 system("mv /etc/init.d/S91quectel-CM.sh /etc/init.d/wireless.sh"); - }else if("2" == param.mCommMode){//无线连接 - system("mv /etc/init.d/wireless.sh /etc/init.d/S91quectel-CM.sh"); + system("mv /etc/init.d/S95check5G /etc/init.d/wireless5G"); + }else if("2" == param.mCommMode){//无线连接 4G + system("mv /etc/init.d/wireless4G /etc/init.d/S91check4G"); + system("mv /etc/init.d/S95check5G /etc/init.d/wireless5G"); + }else if("3" == param.mCommMode){//无线连接 5G + system("mv /etc/init.d/wireless5G /etc/init.d/S95check5G"); + system("mv /etc/init.d/S91check4G /etc/init.d/wireless4G"); } sleep(1); system("reboot"); @@ -114,9 +131,23 @@ std::string JsonData::JsonCmd_23(Param_23 ¶m) Json::Value jsSystemSetting; Json::Value jsBody; + Json::Value jsHeart; + Json::FastWriter fw; + jsHeart["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; + jsHeart["status"] = "online_V1.0.1"; + std::string strJson = fw.write(jsHeart); + int iRet = data_publish(strJson.c_str(), GlobalConfig::Topic_G.mPubHeart.c_str()); + if(iRet == 0){ + jsBody["status"] = 0; + }else{ + jsBody["status"] = -1; + } + jsBody[JSON_FIELD_SERVERIP] = ReadStrByOpt(SERVERCONFIG, "Server", "localServerIpAddress"); - jsBody[JSON_FIELD_SERVERPORT] = boost::lexical_cast(ReadStrByOpt(SERVERCONFIG, "Server", "localServerPort")); - jsBody[JSON_FIELD_CommMode] = boost::lexical_cast(ReadStrByOpt(SERVERCONFIG, "Server", "CommMode")); + jsBody[JSON_FIELD_SERVERPORT] = atoi(ReadStrByOpt(SERVERCONFIG, "Server", "localServerPort").c_str()); + jsBody[JSON_FIELD_CommMode] = atoi(ReadStrByOpt(SERVERCONFIG, "Server", "CommMode").c_str()); + jsBody["Password"] = (ReadStrByOpt(SERVERCONFIG, "Server", "Password")); + jsBody["UserName"] = (ReadStrByOpt(SERVERCONFIG, "Server", "UserName")); std::string dataBody = showValue.write(jsBody); jsonVal["cmdBody"] = dataBody; @@ -128,39 +159,62 @@ std::string JsonData::JsonCmd_23(Param_23 ¶m) std::string JsonData::JsonCmd_25(Param_25 ¶m) { - Json::Value jsonVal; - jsonVal.clear(); - jsonVal["success"] = true; - jsonVal["message"] = ""; - if (0 == param.mMode) { - WriteStr2Config(NETWORKCONFIG, "Net", "dnsName", param.mDnsName); - WriteStr2Config(NETWORKCONFIG, "Net", "networkPortStatus", param.mNetworkPortStatus); - WriteStr2Config(NETWORKCONFIG, "Net", "gateway", param.mGateway); - WriteStr2Config(NETWORKCONFIG, "Net", "subnetMask", param.mSubnetMask); - WriteStr2Config(NETWORKCONFIG, "Net", "ipAddress", param.mIp); - WriteStr2Config(NETWORKCONFIG, "Net", "hostName", param.mHostName); - system("reboot"); - } + Json::Value jsonVal; + jsonVal.clear(); + jsonVal["success"] = true; + jsonVal["message"] = " "; + jsonVal["cmd"] = "25"; + bool bFlag1 = CheckIP(param.mGateway.c_str()); + bool bFlag2 = IsValidMask(param.mSubnetMask); + bool bFlag3 = CheckIP(param.mIp.c_str()); + bool bFlag4 = false; + if(param.mDnsName.size()>0){ + bFlag4 = CheckIP(param.mDnsName.c_str()); + }else{ + bFlag4 = true; + } + print_info("bFlag1 = %d,bFlag2 = %d,bFlag3 = %d,bFlag4 = %d\n",bFlag1,bFlag2,bFlag3,bFlag4); - jsonVal["cmd"] = "25"; - jsonVal["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; - jsonVal["cmdSerial"] = param.mCmdSerial; + if (0 == param.mMode &&(bFlag1 && bFlag2 && bFlag3 && bFlag4) && param.mNetworkPortStatus == "STATIC") { + WriteStr2Config(NETWORKCONFIG, param.mNet, "dnsName", param.mDnsName); + WriteStr2Config(NETWORKCONFIG, param.mNet, "networkPortStatus", param.mNetworkPortStatus); + WriteStr2Config(NETWORKCONFIG, param.mNet, "gateway", param.mGateway); + WriteStr2Config(NETWORKCONFIG, param.mNet, "subnetMask", param.mSubnetMask); + WriteStr2Config(NETWORKCONFIG, param.mNet, "ipAddress", param.mIp); + WriteStr2Config(NETWORKCONFIG, param.mNet, "hostName", param.mHostName); - Json::Value jsSystemSetting; - Json::Value jsBody; +#ifdef IMX6UL_GATEWAY + char GateWay[100]={0x00}; + sprintf(GateWay,"sed -i '7c route add default gw %s' /etc/init.d/S90start_userapp.sh",param.mGateway.c_str()); + print_info("GateWay = %s\n",GateWay); + system(GateWay); +#endif + platform->EquipIpInit(param.mNet); + }else if(0 == param.mMode && param.mNetworkPortStatus == "DHCP"){ + WriteStr2Config(NETWORKCONFIG, param.mNet, "dnsName", ""); + WriteStr2Config(NETWORKCONFIG, param.mNet, "networkPortStatus", param.mNetworkPortStatus); + WriteStr2Config(NETWORKCONFIG, param.mNet, "gateway", ""); + WriteStr2Config(NETWORKCONFIG, param.mNet, "subnetMask", ""); + WriteStr2Config(NETWORKCONFIG, param.mNet, "ipAddress", ""); + WriteStr2Config(NETWORKCONFIG, param.mNet, "hostName", ""); - jsBody["dnsName"] = ReadStrByOpt(NETWORKCONFIG, "Net", "dnsName"); - jsBody["networkPortStatus"] = ReadStrByOpt(NETWORKCONFIG, "Net", "networkPortStatus"); - jsBody["gateway"] = ReadStrByOpt(NETWORKCONFIG, "Net", "gateway"); - jsBody["subnetMask"] = ReadStrByOpt(NETWORKCONFIG, "Net", "subnetMask"); - jsBody["dataWatchIpAddress"] = ReadStrByOpt(NETWORKCONFIG, "Net", "ipAddress"); - jsBody["hostName"] = ReadStrByOpt(NETWORKCONFIG, "Net", "hostName"); +#ifdef IMX6UL_GATEWAY + system("sed -i '7c udhcpc -i eth0 > /dev/null &' /etc/init.d/S90start_userapp.sh"); +#endif + platform->EquipIpInit(param.mNet); - std::string dataBody = showValue.write(jsBody); - jsonVal["cmdBody"] = dataBody; + }else if(0 == param.mMode &&(!bFlag1 || !bFlag2 || !bFlag3 || !bFlag4) && param.mNetworkPortStatus == "STATIC"){ + jsonVal["success"] = false; + } - return showValue.write(jsonVal); + jsonVal["content"]["dnsName"] = ReadStrByOpt(NETWORKCONFIG, param.mNet, "dnsName"); + jsonVal["content"]["networkPortStatus"] = ReadStrByOpt(NETWORKCONFIG, param.mNet, "networkPortStatus"); + jsonVal["content"]["gateway"] = ReadStrByOpt(NETWORKCONFIG, param.mNet, "gateway"); + jsonVal["content"]["subnetMask"] = ReadStrByOpt(NETWORKCONFIG, param.mNet, "subnetMask"); + jsonVal["content"]["dataWatchIpAddress"] = ReadStrByOpt(NETWORKCONFIG, param.mNet, "ipAddress"); + jsonVal["content"]["hostName"] = ReadStrByOpt(NETWORKCONFIG, param.mNet, "hostName"); + return showValue.write(jsonVal); } @@ -182,45 +236,46 @@ std::string JsonData::JsonCmd_26(Param_26 ¶m) Json::Value jsSensorData; jsSensorData["dataNodeNo"] = arrRes[j][0]; jsSensorData["dataNodeName"] = arrRes[j][1]; - jsSensorData["initFlag"] = boost::lexical_cast(arrRes[j][2]); - jsSensorData["accFlag"] = boost::lexical_cast(arrRes[j][3]); - jsSensorData["zigbeeFlag"] = boost::lexical_cast(arrRes[j][4]); - jsSensorData["temTopFlag"] = boost::lexical_cast(arrRes[j][5]); - jsSensorData["temBotFlag"] = boost::lexical_cast(arrRes[j][6]); + jsSensorData["initFlag"] = atoi(arrRes[j][2].c_str()); + jsSensorData["accFlag"] = atoi(arrRes[j][3].c_str()); + jsSensorData["zigbeeFlag"] = atoi(arrRes[j][4].c_str()); + jsSensorData["temTopFlag"] = atoi(arrRes[j][5].c_str()); + jsSensorData["temBotFlag"] = atoi(arrRes[j][6].c_str()); + jsSensorData["equipsta"] = atoi(arrRes[j][7].c_str()); jsSensorData["hardVersion"] = arrRes[j][8]; jsSensorData["softVersion"] = arrRes[j][9]; jsSensorData["bpNo"] = arrRes[j][10]; jsSensorData["serialNo"] = arrRes[j][11]; jsSensorData["firstPowerTime"] = arrRes[j][12]; - jsSensorData["WakeupTime"] = boost::lexical_cast(arrRes[j][13]); - jsSensorData["StaticTime"] = boost::lexical_cast(arrRes[j][14]); - jsSensorData["WaveTime"] = boost::lexical_cast(arrRes[j][15]); + jsSensorData["WakeupTime"] = atoi(arrRes[j][13].c_str()); + jsSensorData["StaticTime"] = atoi(arrRes[j][14].c_str()); + jsSensorData["WaveTime"] = atoi(arrRes[j][15].c_str()); jsSensorData["BateryV"] = arrRes[j][16]; jsSensorData["ProductNo"] = arrRes[j][17]; - jsSensorData["configFlag"] = boost::lexical_cast(arrRes[j][18]); + jsSensorData["configFlag"] = atoi(arrRes[j][18].c_str()); jsSensorData["startBrands"] = arrRes[j][19]; jsSensorData["stopBrands"] = arrRes[j][20]; - jsSensorData["featureInterVal"] = boost::lexical_cast(arrRes[j][21]); - jsSensorData["waveInterVal"] = boost::lexical_cast(arrRes[j][22]); - jsSensorData["samplingRate"] = boost::lexical_cast(arrRes[j][23]); - printf("stopBrands11111 = %s\n",arrRes[j][20].c_str()); - // jsSensorData["scope"] = boost::lexical_cast(arrRes[j][24]); - jsSensorData["range"] = boost::lexical_cast(arrRes[j][25]); + jsSensorData["featureInterVal"] = (arrRes[j][21]); + jsSensorData["waveInterVal"] = atoi(arrRes[j][22].c_str()); + jsSensorData["samplingRate"] = atoi(arrRes[j][23].c_str()); + // jsSensorData["scope"] = atoi(arrRes[j][24]); + jsSensorData["range"] = atoi(arrRes[j][25].c_str()); jsSensorData["envelopeBandPass"] = arrRes[j][26]; jsSensorData["faultFrequency"] = arrRes[j][27]; jsSensorData["zigbeePanId"] = arrRes[j][28]; - jsSensorData["zigbeeChannel"] = boost::lexical_cast(arrRes[j][29]); + jsSensorData["zigbeeChannel"] = (arrRes[j][29]); jsSensorData["zigbeeAddr"] = arrRes[j][30]; jsSensorData["zigbeeLongAddr"] = arrRes[j][31]; jsSensorData["zigbeeDesAddr"] = arrRes[j][32]; - jsSensorData["ZigbeePower"] = boost::lexical_cast(arrRes[j][33]); - jsSensorData["ZigbeeRetry"] = boost::lexical_cast(arrRes[j][34]); - jsSensorData["ZigbeeRetryGap"] = boost::lexical_cast(arrRes[j][35]); - jsSensorData["ACCSampleTime"] = boost::lexical_cast(arrRes[j][36]); - jsSensorData["status"] = boost::lexical_cast(arrRes[j][37]); + jsSensorData["ZigbeePower"] = atoi(arrRes[j][33].c_str()); + jsSensorData["ZigbeeRetry"] = atoi(arrRes[j][34].c_str()); + jsSensorData["ZigbeeRetryGap"] = atoi(arrRes[j][35].c_str()); + jsSensorData["ACCSampleTime"] = atoi(arrRes[j][36].c_str()); + jsSensorData["status"] = atoi(arrRes[j][37].c_str()); jsSensorData["timeStamp"] = arrRes[j][38]; - jsSensorData["viff"] = boost::lexical_cast(arrRes[j][39]); - jsSensorData["RSSI"] = boost::lexical_cast(arrRes[j][40]); + jsSensorData["viff"] = atoi(arrRes[j][39].c_str()); + jsSensorData["RSSI"] = atoi(arrRes[j][40].c_str()); + jsSensorData["Update"] = atoi(arrRes[j][41].c_str()); jsArray.append(jsSensorData); } } else { @@ -257,6 +312,7 @@ std::string JsonData::JsonCmd_27(Json::Value & recvBody) sql_ctl->DeleteTableData(T_SENSOR_INFO(TNAME), whereCon); sql_ctl->DeleteTableData(T_DATA_INFO(TNAME), whereCon); sql_ctl->DeleteTableData(T_DATASTATIC_INFO(TNAME), whereCon); + sql_ctl->DeleteTableData(T_DATANODE_TIME(TNAME), whereCon); } } else { jsonVal["success"] = false; @@ -277,22 +333,42 @@ std::string JsonData::JsonCmd_50(Json::Value & recvBody) std::string updateDevice = recvBody["updateDevice"].asString();//1 DataNode 2 GateWay std::string updateURL = recvBody["updateURL"].asString(); std::string updateName = recvBody["updateName"].asString(); + std::string md5 = recvBody["MD5"].asString(); std::string strResponse; - updateName = "/opt/update/DataNode/" + updateName; - bool bDownload = 1; - int iRet = pDataTrans->download( (char*)updateName.c_str(),updateURL, strResponse, bDownload); + updateName = "/opt/" + updateName; + if (access(updateName.c_str(), 0) == 0){ + char cmd[100]={0x00}; + sprintf(cmd,"rm -rf %s",updateName.c_str()); + system(cmd); + } + sleep(2); +// int iRet = pDataTrans->download( (char*)updateName.c_str(),updateURL, strResponse, bDownload); + int iRet = pDataTrans->dl_curl_post_req( updateURL,"",updateName); if(iRet != 0){ jsonVal["success"] = false; jsonVal["message"] = "download failed"; return showValue.write(jsonVal); } + string md5Val = md5file(updateName.c_str()); + printf("md5Val = %s\n",md5Val.c_str()); + printf("md5 = %s\n",md5.c_str()); + if(md5 != md5Val){ + jsonVal["success"] = false; + jsonVal["message"] = "download file check failed"; + return showValue.write(jsonVal); + } if(updateDevice == "1"){ - string strcmd = "tar zxvf "; + string strcmd = "tar xvf "; strcmd = strcmd + updateName; - strcmd = strcmd + " -C /opt/update/DataNode/"; + strcmd = strcmd + " -C /opt/"; system(strcmd.c_str()); - }else{ - + }else if (updateDevice == "2"){ + /* string strcmd = "tar xvf "; + strcmd = strcmd + updateName; + strcmd = strcmd + " -C /opt/update/"; + system(strcmd.c_str());*/ + sleep(3); + system("/opt/opt.sh"); } return showValue.write(jsonVal); } @@ -316,7 +392,104 @@ std::string JsonData::JsonCmd_51(Json::Value & recvBody) } return showValue.write(jsonVal); } +std::string JsonData::JsonCmd_52() +{ + Json::Value jsonVal; + jsonVal.clear(); + jsonVal["success"] = true; + jsonVal["message"] = ""; + char whereCon[512] = {}; + std::string strTimeStamp = ""; + char selectCon[128] = { 0 }; + memcpy(selectCon,"sendMsg = '0'",sizeof(selectCon)); + int count = sql_ctl->GetTableRows(T_DATASTATIC_INFO(TNAME), selectCon); + if(count < 1){ + return ""; + } + for(int i = 0 ; i < count ;i++) + { + Json::Value jsSensor; + std::string strDataNodeNo = ""; + jsonVal.clear(); + jsonVal["cmd"] = "52"; + memcpy(whereCon, "sendMsg = '0' ORDER BY timeStamp DESC LIMIT 0,3",sizeof(whereCon)); + // 自数据库获取传感器特征数据 + array_t arrRes; + arrRes = sql_ctl->GetDataMultiLine(T_DATA_INFO(TNAME), "*", whereCon); + int iResult = arrRes.size(); + if (iResult > 0) { + for (int j = 0; j < iResult; j++) { + Json::Value jsChannelData; + strDataNodeNo = arrRes[j][0]; + jsChannelData["ChannelId"] = arrRes[j][1]; + jsChannelData["ChannelType"] = "ACCELEROMETER"; + jsChannelData["DiagnosisPeak"] = atof(arrRes[j][2].c_str()); + jsChannelData["IntegratPk2Pk/2"] = atof(arrRes[j][3].c_str()); + jsChannelData["IntegratRMS"] = atof(arrRes[j][4].c_str()); + jsChannelData["RMSValues"] = atof(arrRes[j][5].c_str()); + jsChannelData["EnvelopEnergy"] = atof(arrRes[j][6].c_str()); + jsChannelData["1xAmp"] = atof(arrRes[j][7].c_str()); + jsChannelData["2xAmp"] = atof(arrRes[j][8].c_str()); + jsChannelData["3xAmp"] = atof(arrRes[j][9].c_str()); + jsChannelData["4xAmp"] = atof(arrRes[j][10].c_str()); + jsChannelData["5xAmp"] = atof(arrRes[j][11].c_str()); + jsChannelData["1xPhase"] = atof(arrRes[j][12].c_str()); + jsChannelData["2xPhase"] = atof(arrRes[j][13].c_str()); + jsChannelData["3xPhase"] = atof(arrRes[j][14].c_str()); + jsChannelData["4xPhase"] = atof(arrRes[j][15].c_str()); + jsChannelData["TimeStamp"] = atof(arrRes[j][17].c_str()); + strTimeStamp = std::string(arrRes[j][16]); + jsSensor.append(jsChannelData); + } + } + memset(selectCon,0x00,sizeof(selectCon)); + sprintf(selectCon, "dataNodeNo='%s' and sendMsg = '0' ORDER BY timeStamp DESC LIMIT 0,1", strDataNodeNo.c_str()); + vec_t vecRes = sql_ctl->GetDataSingleLine(T_DATASTATIC_INFO(TNAME), "*", selectCon); + Json::Value jsStaticData; + if(vecRes.size()>0){ + jsStaticData["TemperatureTop"] = atof(vecRes[2].c_str()); + jsStaticData["TemperatureBot"] = atof(vecRes[3].c_str()); + jsStaticData["Dip"] = atof(vecRes[4].c_str()); + jsStaticData["Voltage"] = atof(vecRes[5].c_str()); + jsStaticData["ChannelType"] = "STATUS"; + jsStaticData["ChannelId"] = vecRes[1]; + jsStaticData["TimeStamp"] = vecRes[7]; + jsStaticData["dataNodeNo"] = strDataNodeNo; + } + + jsSensor.append(jsStaticData); + + jsonVal["content"].append(jsSensor); + std::string data = showValue.write(jsonVal); + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon,"sendMsg = '0' and timeStamp = '%s'",strTimeStamp.c_str()); + int iRet = data_publish(data.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); + if(iRet == 0){ + sql_ctl->DeleteTableData(T_DATA_INFO(TNAME),whereCon,0); + sql_ctl->DeleteTableData(T_DATASTATIC_INFO(TNAME),whereCon,0); + } + usleep(100); + } + return ""; +} +std::string JsonData::JsonCmd_53(Json::Value & recvBody) +{ + Json::Value jsonVal; + jsonVal.clear(); + jsonVal["success"] = true; + jsonVal["message"] = ""; + jsonVal["cmd"] = "53"; + jsonVal["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; + std::string looseValue = recvBody["looseValue"].asString(); + + int iRet = writeStringVlaue("config", "loose",(char*)looseValue.c_str(),(char*)GlobalConfig::Config_G.c_str()); + if(iRet != 0){ + jsonVal["success"] = false; + jsonVal["message"] = "update failed"; + } + return showValue.write(jsonVal); +} std::string JsonData::JsonCmd_29(Param_29 ¶m) { Json::Value jsonVal; @@ -325,23 +498,22 @@ std::string JsonData::JsonCmd_29(Param_29 ¶m) jsonVal.clear(); jsonVal["cmd"] = "29"; jsonVal["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; - jsonVal["cmdSerial"] = param.mCmdSerial; - +// jsonVal["cmdSerial"] = param.mCmdSerial; array_t arrRes; arrRes = sql_ctl->GetDataMultiLine(T_SENSOR_INFO(TNAME), "*", NULL); int iResult = arrRes.size(); +// LOG_INFO("iResult = %d",iResult); if (iResult > 0) { for (int i = 0; i < iResult; i++) { Json::Value jsDataNode; - jsDataNode["dataNodeNo"] = arrRes[i][1]; - jsDataNode["status"] = boost::lexical_cast(arrRes[i][24]); + jsDataNode["dataNodeNo"] = arrRes[i][0]; + jsDataNode["status"] = atoi(arrRes[i][37].c_str()); jsBody["dataNodeArray"].append(jsDataNode); } } - + std::string strBody = showValue.write(jsBody); jsonVal["cmdBody"] = strBody; - return showValue.write(jsonVal); } @@ -382,34 +554,38 @@ void JsonData::JsonCmd_39(Json::Value &recvBody) } void JsonData::DataNodeStatusCheck() { - vec_t vetRes = sql_ctl->GetDataMultiLineOfOneColumn(T_SENSOR_INFO(TNAME), T_SENSOR_INFO(DATANODENO), NULL); + array_t vetRes = sql_ctl->GetDataMultiLine(T_SENSOR_INFO(TNAME), "*", NULL); int nSize = vetRes.size(); char localtimestamp[32] = { 0 }; GetTimeNet(localtimestamp, 1); std::string nowTimetamp = std::string(localtimestamp); - int lNowTime = boost::lexical_cast(nowTimetamp); - + int lNowTime = atoi(nowTimetamp.c_str()); + int onlineCheck = readIntValue( "config", "online",(char*)GlobalConfig::Config_G.c_str()); + int loseTime = readIntValue( "config", "loseTime",(char*)GlobalConfig::Config_G.c_str()); if (nSize > 0) { for (int i = 0; i < nSize; i++) { - std::string strDataNodeNo = vetRes[i]; + std::string strDataNodeNo = vetRes[i][0]; std::string strChannelId= strDataNodeNo + "-X"; - char whereCon[64] = {}; + char whereCon[512] = {0x00},tablename[128]={0x00}; sprintf(whereCon, "dataNodeNo='%s' and channelID='%s' ORDER BY timeStamp DESC LIMIT 0,1", strDataNodeNo.c_str(), strChannelId.c_str()); - array_t arrRes; - std::string strTimeRes = sql_ctl->GetData(T_DATA_INFO(TNAME), T_DATA_INFO(TIMESTAMP), whereCon); + sprintf(tablename,"t_data_%s",strDataNodeNo.c_str()); + std::string strTimeRes = sql_ctl->GetData(tablename, "timeStamp", whereCon); if (strTimeRes.length() > 0) { - int llastTime = boost::lexical_cast(strTimeRes); + int llastTime = atoi(strTimeRes.c_str()); int lTimeTemp = lNowTime - llastTime; - LOG_INFO("lNowTime = %d,llastTime = %d",lNowTime,llastTime); lTimeTemp = abs(lTimeTemp); - if (lTimeTemp > onlineCheck) { - LOG_INFO("0-lTimeTemp = %d,onlineCheck = %d",lTimeTemp,onlineCheck); + if (lTimeTemp > onlineCheck){ + LOG_DEBUG("离线 DataNodeStatusCheck lNowTime = %d,llastTime = %d,interval = %s\n",lNowTime,llastTime,vetRes[i][21].c_str()); char whereCon[32] = { 0 }; sprintf(whereCon, "dataNodeNo='%s'", strDataNodeNo.c_str()); sql_ctl->UpdateTableData(T_SENSOR_INFO(TNAME), "status='0'", whereCon); + }else if(lTimeTemp > (loseTime * atoi(vetRes[i][21].c_str()) * 60)){ + LOG_DEBUG("掉线 DataNodeStatusCheck lNowTime = %d,llastTime = %d,interval = %s\n",lNowTime,llastTime,vetRes[i][21].c_str()); + char whereCon[32] = { 0 }; + sprintf(whereCon, "dataNodeNo='%s'", strDataNodeNo.c_str()); + sql_ctl->UpdateTableData(T_SENSOR_INFO(TNAME), "status='2'", whereCon); }else { - LOG_INFO("1-lTimeTemp = %d,onlineCheck = %d",lTimeTemp,onlineCheck); char whereCon[32] = { 0 }; sprintf(whereCon, "dataNodeNo='%s'", strDataNodeNo.c_str()); sql_ctl->UpdateTableData(T_SENSOR_INFO(TNAME), "status='1'", whereCon); @@ -481,7 +657,7 @@ std::string JsonData::JsonCmd_Cgi_02(Param_02 ¶m) if (0 == param.mMode) { jsonVal["type"] = "SET"; SetTime((unsigned long)param.mTimeStamp); - boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + usleep(200); system("hwclock -w"); } else if (1 == param.mMode) { char cmd[256] = { 0 }; @@ -489,7 +665,7 @@ std::string JsonData::JsonCmd_Cgi_02(Param_02 ¶m) GetTimeNet(localtimestamp, 1); std::string nowTimetamp = std::string(localtimestamp); jsonVal["type"] = "GET"; - jsonVal["timeStamp"] = boost::lexical_cast(nowTimetamp); + jsonVal["timeStamp"] = atoi(nowTimetamp.c_str()); } return showValue.write(jsonVal); @@ -554,81 +730,290 @@ std::string JsonData::JsonCmd_Cgi_08() return showValue.write(jsonVal); } -std::string JsonData::JsonCmd_Cgi_09() +std::string JsonData::JsonCmd_Cgi_09(Param_09 ¶m) { - Json::Value jsonVal; - jsonVal.clear(); + Json::Value jsonVal; + jsonVal.clear(); - jsonVal[JSON_FIELD_CMD] = "09"; - jsonVal["success"] = true; - jsonVal["message"] = " "; + jsonVal[JSON_FIELD_CMD] = "09"; + jsonVal["success"] = true; + jsonVal["message"] = " "; - vec_t vetRes = sql_ctl->GetDataMultiLineOfOneColumn(T_SENSOR_INFO(TNAME), T_SENSOR_INFO(DATANODENO), NULL); - int nSize = vetRes.size(); - - if (nSize > 0) { - for (int i = 0; i < nSize; i++) { - print_info("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@vetRes=%s\n",vetRes[i].c_str()); - Json::Value jsSensor; - std::string strDataNodeNo = vetRes[i]; - char whereCon[64] = {}; - sprintf(whereCon, "dataNodeNo='%s' ORDER BY timeStamp DESC LIMIT 0,3", strDataNodeNo.c_str()); - // 自数据库获取传感器特征数据 - array_t arrRes; - arrRes = sql_ctl->GetDataMultiLine(T_DATA_INFO(TNAME), "*", whereCon); - int iResult = arrRes.size(); - if (iResult > 0) { - for (int j = 0; j < iResult; j++) { - Json::Value jsChannelData; - jsChannelData["ChannelId"] = arrRes[j][1]; - jsChannelData["ChannelType"] = "ACCELEROMETER"; - jsChannelData["DiagnosisPeak"] = boost::lexical_cast(arrRes[j][2]); - jsChannelData["IntegratPk2Pk/2"] = boost::lexical_cast(arrRes[j][3]); - jsChannelData["IntegratRMS"] = boost::lexical_cast(arrRes[j][4]); - jsChannelData["RMSValues"] = boost::lexical_cast(arrRes[j][5]); - jsChannelData["EnvelopEnergy"] = boost::lexical_cast(arrRes[j][6]); - jsChannelData["1xAmp"] = boost::lexical_cast(arrRes[j][7]); - jsChannelData["2xAmp"] = boost::lexical_cast(arrRes[j][8]); - jsChannelData["3xAmp"] = boost::lexical_cast(arrRes[j][9]); - jsChannelData["4xAmp"] = boost::lexical_cast(arrRes[j][10]); - jsChannelData["5xAmp"] = boost::lexical_cast(arrRes[j][11]); - jsChannelData["1xPhase"] = boost::lexical_cast(arrRes[j][12]); - jsChannelData["2xPhase"] = boost::lexical_cast(arrRes[j][13]); - jsChannelData["3xPhase"] = boost::lexical_cast(arrRes[j][14]); - jsChannelData["4xPhase"] = boost::lexical_cast(arrRes[j][15]); - jsChannelData["TimeStamp"] = boost::lexical_cast(arrRes[j][16]); - jsSensor.append(jsChannelData); - } - } - - char selectCon[128] = { 0 }; - sprintf(selectCon, "dataNodeNo='%s' ORDER BY timeStamp DESC LIMIT 0,1", strDataNodeNo.c_str()); - vec_t vecRes = sql_ctl->GetDataSingleLine(T_DATASTATIC_INFO(TNAME), "*", selectCon); - Json::Value jsStaticData; - if(vecRes.size()>0){ - jsStaticData["TemperatureTop"] = boost::lexical_cast(vecRes[2]); - jsStaticData["TemperatureBot"] = boost::lexical_cast(vecRes[3]); - jsStaticData["Dip"] = boost::lexical_cast(vecRes[4]); - jsStaticData["Voltage"] = boost::lexical_cast(vecRes[5]); - jsStaticData["ChannelType"] = "STATUS"; - jsStaticData["ChannelId"] = vecRes[1]; - jsStaticData["TimeStamp"] = vecRes[6]; - jsStaticData["dataNodeNo"] = strDataNodeNo; - } + char localtimestamp[32] = { 0 }; + GetTimeNet(localtimestamp, 1); + std::string nowTimetamp = std::string(localtimestamp); + char looseValue[10]={0x00}; + readStringValue("config", "loose",looseValue,(char*)GlobalConfig::Config_G.c_str()); - jsSensor.append(jsStaticData); + vec_t vetRes = sql_ctl->GetDataMultiLineOfOneColumn(T_SENSOR_INFO(TNAME), T_SENSOR_INFO(DATANODENO), NULL); + int nSize = vetRes.size(); + if (nSize > 0) { + int packgeNo = param.mPackageFlag; + int packgeMax = 0; + int packgeNum = 0; + jsonVal["package"] = packgeNo; + int lastSize = nSize % 10; + int index = nSize / 10; + if(lastSize > 0 && index > 0){ + packgeMax = index +1; + if(packgeNo +1 == packgeMax){ + packgeNum = nSize; + jsonVal["packageMax"] = index + 1; + } + else{ + packgeNum = (packgeNo+1) * 10; + jsonVal["packageMax"] = index +1; + } + } + else if(lastSize == 0 && index > 0){ + packgeNum = (packgeNo+1) * 10; + packgeMax = index; + jsonVal["packageMax"] = index; + }else if(lastSize > 0 && index == 0){ + packgeNum = lastSize; + packgeMax = index+1; + jsonVal["packageMax"] = index+1; + } - jsonVal["content"].append(jsSensor); - } - } else { - jsonVal["content"].resize(0); - } + printf("09 packgeNo = %d,packgeNum = %d,lastSize = %d,index = %d\n",packgeNo,packgeNum,lastSize,index); + for (int i = packgeNo * 10; i < packgeNum; i++) { + print_info("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@vetRes=%s\n",vetRes[i].c_str()); + Json::Value jsSensor; + std::string strDataNodeNo = vetRes[i]; + char whereCon[512] = {}; + sprintf(whereCon, "dataNodeNo='%s' ORDER BY timeStamp DESC LIMIT 0,3", strDataNodeNo.c_str()); + // 自数据库获取传感器特征数据 + array_t arrRes; + arrRes = sql_ctl->GetDataMultiLineTransaction(T_DATA_INFO(TNAME), "*", whereCon); + int iResult = arrRes.size(); + if (iResult > 0) { + for (int j = 0; j < iResult; j++) { + Json::Value jsChannelData; + jsChannelData["ChannelId"] = arrRes[j][1]; + jsChannelData["ChannelType"] = "ACCELEROMETER"; + jsChannelData["DiagnosisPeak"] = atof(arrRes[j][2].c_str()); + jsChannelData["IntegratPk2Pk/2"] = atof(arrRes[j][3].c_str()); + jsChannelData["IntegratRMS"] = atof(arrRes[j][4].c_str()); + jsChannelData["RMSValues"] = atof(arrRes[j][5].c_str()); + jsChannelData["EnvelopEnergy"] = atof(arrRes[j][6].c_str()); + jsChannelData["1xAmp"] = atof(arrRes[j][7].c_str()); + jsChannelData["2xAmp"] = atof(arrRes[j][8].c_str()); + jsChannelData["3xAmp"] = atof(arrRes[j][9].c_str()); + jsChannelData["4xAmp"] = atof(arrRes[j][10].c_str()); + jsChannelData["5xAmp"] = atof(arrRes[j][11].c_str()); + jsChannelData["1xPhase"] = atof(arrRes[j][12].c_str()); + jsChannelData["2xPhase"] = atof(arrRes[j][13].c_str()); + jsChannelData["3xPhase"] = atof(arrRes[j][14].c_str()); + jsChannelData["4xPhase"] = atof(arrRes[j][15].c_str()); + jsChannelData["TimeStamp"] = atof(arrRes[j][17].c_str()); + jsSensor.append(jsChannelData); + } + } - return showValue.write(jsonVal); + char selectCon[128] = { 0 }; + char column[128]={0}; + char tablename[256]={0}; + sprintf(selectCon, "t_datastatic_%s.dataNodeNo='%s' ORDER BY timeStamp DESC LIMIT 0,1",strDataNodeNo.c_str(),strDataNodeNo.c_str()); + sprintf(column," t_datastatic_%s.*,t_sensor_info.status,t_sensor_info.LooseValue,t_sensor_info.batteryPower ",strDataNodeNo.c_str()); + sprintf(tablename," t_datastatic_%s LEFT JOIN t_sensor_info \ + ON t_datastatic_%s.dataNodeNo = t_sensor_info.dataNodeNo ",strDataNodeNo.c_str(),strDataNodeNo.c_str()); + + + vec_t vecRes = sql_ctl->GetDataSingleLine(tablename,column, selectCon); + Json::Value jsStaticData; + if(vecRes.size()>0){ + jsStaticData["TemperatureTop"] = atof(vecRes[2].c_str()); + jsStaticData["TemperatureBot"] = atof(vecRes[3].c_str()); + jsStaticData["Dip"] = atof(vecRes[4].c_str()); + jsStaticData["Voltage"] = atof(vecRes[5].c_str()); + jsStaticData["ChannelType"] = "STATUS"; + jsStaticData["ChannelId"] = vecRes[1]; + jsStaticData["TimeStamp"] = vecRes[8]; + jsStaticData["battery"] = vecRes[13]; + jsStaticData["dataNodeNo"] = strDataNodeNo; + jsStaticData["status"] = vecRes[11]; + if(atof(looseValue) < atof(vecRes[12].c_str())){ + jsStaticData["loose"] = "1"; + }else{ + jsStaticData["loose"] = "0"; + } + }else{ + jsStaticData["TemperatureTop"] = ""; + jsStaticData["TemperatureBot"] = ""; + jsStaticData["Dip"] = ""; + jsStaticData["Voltage"] = ""; + jsStaticData["ChannelType"] = "STATUS"; + jsStaticData["ChannelId"] = ""; + jsStaticData["TimeStamp"] = ""; + jsStaticData["battery"] = ""; + jsStaticData["dataNodeNo"] = strDataNodeNo; + jsStaticData["status"] = "0"; + jsStaticData["loose"] = "0"; + } + + jsSensor.append(jsStaticData); + + jsonVal["content"].append(jsSensor); + } + + } else { + jsonVal["success"] = true; + jsonVal["content"].resize(0); + } + + return showValue.write(jsonVal); +} +std::string JsonData::JsonCmd_Cgi_10(Param_10 ¶m) +{ + Json::Value jsonVal; + jsonVal.clear(); + + jsonVal[JSON_FIELD_CMD] = "10"; + jsonVal["success"] = true; + jsonVal["message"] = " "; + vec_t vetRes = sql_ctl->GetDataMultiLineOfOneColumn(T_SENSOR_INFO(TNAME), T_SENSOR_INFO(DATANODENO), NULL); + int nSize = vetRes.size(); + if (nSize > 0) { + char selectCon[256] = { 0 },szTableName[100] = {0x00},whereCon[256]={0x00}; + sprintf(selectCon, "%s,channelID,timeStamp",param.strStatic.c_str()); + if(param.straxis == "S") + { + sprintf(szTableName,"t_dataStatic_%s",param.strDataNode.c_str()); + }else{ + sprintf(szTableName,"t_data_%s",param.strDataNode.c_str()); + } + if(param.timeEnd == ""){ + sprintf(whereCon,"dataNodeNo = '%s' and %s <> '' ",\ + param.strDataNode.c_str(),param.strStatic.c_str()); + }else{ + sprintf(whereCon,"dataNodeNo = '%s' and %s <> '' and timeStamp < '%s' and timeStamp > '%s' ",\ + param.strDataNode.c_str(),param.strStatic.c_str(),param.timeEnd.c_str(),param.timeStart.c_str()); + } + int rows = sql_ctl->GetTableRows(szTableName,whereCon); + printf("rows : %d\n",rows); + int packgeNo = param.mPackageFlag; + int packgeMax = 0; + int packgeNum = 0; + jsonVal["package"] = packgeNo; + int lastSize = rows % 550; + int index = rows / 550; + if(lastSize > 0 && index > 0){ + packgeMax = index +1; + if(packgeNo +1 == packgeMax){ + packgeNum = rows-lastSize; + jsonVal["packageMax"] = index + 1; + } + else{ + packgeNum = (packgeNo) * 550; + jsonVal["packageMax"] = index +1;} + } + else if(lastSize == 0 && index > 0){ + packgeNum = (packgeNo+1) * 550; + packgeMax = index; + jsonVal["packageMax"] = index; + }else if(lastSize > 0 && index == 0){ + packgeNum = 0; + packgeMax = index+1; + jsonVal["packageMax"] = index; + } + + printf("10 packgeNo = %d,packgeNum = %d,lastSize = %d,index = %d\n",packgeNo,packgeNum,lastSize,index); + memset(whereCon,0x00,sizeof(whereCon)); + + if(param.timeEnd == ""){ + sprintf(whereCon,"dataNodeNo = '%s' and %s <> '' order by timeStamp asc LIMIT %d OFFSET %d",\ + param.strDataNode.c_str(),param.strStatic.c_str(),550,packgeNum); + }else{ + sprintf(whereCon,"dataNodeNo = '%s' and %s <> '' and timeStamp < '%s' and timeStamp > '%s' order by timeStamp asc LIMIT %d OFFSET %d",\ + param.strDataNode.c_str(),param.strStatic.c_str(),param.timeEnd.c_str(),param.timeStart.c_str(),550,packgeNum); + } + array_t vecRes; + + vecRes = sql_ctl->GetDataMultiLine(szTableName, selectCon,whereCon); + + if(vecRes.size() > 0){ + Json::Value jsStaticData ; + for(int i = 0 ; i < vecRes.size(); i++){ + Json::Value iTem; + if(vecRes[i][1] == param.strDataNode + "-X"){ + iTem.append(vecRes[i][0]); + iTem.append(vecRes[i][2]); + jsStaticData["X"].append(iTem); + }if(vecRes[i][1] == param.strDataNode + "-Y"){ + iTem.append(vecRes[i][0]); + iTem.append(vecRes[i][2]); + jsStaticData["Y"].append(iTem); + }if(vecRes[i][1] == param.strDataNode + "-Z"){ + iTem.append(vecRes[i][0]); + iTem.append(vecRes[i][2]); + jsStaticData["Z"].append(iTem); + } + if(vecRes[i][1] == param.strDataNode + "-S"){ + iTem.append(vecRes[i][0]); + iTem.append(vecRes[i][2]); + jsStaticData["S"].append(iTem); + } + //jsStaticData.append(value) + } + jsonVal["content"] = (jsStaticData); + jsonVal["Static"] = param.strStatic; + print_info("vecRes = %d,channelID = %s\n",vecRes.size(),vecRes[0][0].c_str()); + }else{ + jsonVal["success"] = false; + jsonVal["content"].resize(0); + } + }else{ + jsonVal["success"] = false; + jsonVal["content"].resize(0); + } + return showValue.write(jsonVal); } +std::string JsonData::JsonCmd_Cgi_11(Param_11 ¶m) +{ + Json::Value jsonVal,jsSensor; + jsonVal.clear(); + jsonVal[JSON_FIELD_CMD] = "11"; + jsonVal["success"] = true; + jsonVal["message"] = " "; + char whereCon[512] = {}; + sprintf(whereCon, "dataNodeNo='%s' ORDER BY timeStamp DESC LIMIT 0,3", param.DataNodeNo.c_str()); + // 自数据库获取传感器特征数据 + array_t arrRes; + arrRes = sql_ctl->GetDataMultiLineTransaction(T_DATA_INFO(TNAME), "*", whereCon); + int iResult = arrRes.size(); + print_info("iResult = %d\n",iResult); + if (iResult > 0) { + for (int j = 0; j < iResult; j++) { + Json::Value jsChannelData; + jsChannelData["ChannelId"] = arrRes[j][1]; + jsChannelData["ChannelType"] = "ACCELEROMETER"; + jsChannelData["DiagnosisPeak"] = atof(arrRes[j][2].c_str()); + jsChannelData["IntegratPk2Pk/2"] = atof(arrRes[j][3].c_str()); + jsChannelData["IntegratRMS"] = atof(arrRes[j][4].c_str()); + jsChannelData["RMSValues"] = atof(arrRes[j][5].c_str()); + jsChannelData["EnvelopEnergy"] = atof(arrRes[j][6].c_str()); + jsChannelData["1xAmp"] = atof(arrRes[j][7].c_str()); + jsChannelData["2xAmp"] = atof(arrRes[j][8].c_str()); + jsChannelData["3xAmp"] = atof(arrRes[j][9].c_str()); + jsChannelData["4xAmp"] = atof(arrRes[j][10].c_str()); + jsChannelData["5xAmp"] = atof(arrRes[j][11].c_str()); + jsChannelData["1xPhase"] = atof(arrRes[j][12].c_str()); + jsChannelData["2xPhase"] = atof(arrRes[j][13].c_str()); + jsChannelData["3xPhase"] = atof(arrRes[j][14].c_str()); + jsChannelData["4xPhase"] = atof(arrRes[j][15].c_str()); + jsChannelData["TimeStamp"] = atof(arrRes[j][17].c_str()); + jsSensor.append(jsChannelData); + } + }else { + jsonVal["success"] = false; + jsonVal["content"].resize(0); + } + jsonVal["content"] = jsSensor; + return showValue.write(jsonVal); +} std::string JsonData::JsonCmd_Cgi_20(Param_20 ¶m) { @@ -669,6 +1054,44 @@ std::string JsonData::JsonCmd_Cgi_20(Param_20 ¶m) jsSystemInfo["zigbeePanId"] = GlobalConfig::ZigbeeInfo_G.PanID; jsSystemInfo["zigbeeChannel"] = GlobalConfig::ZigbeeInfo_G.Channel; jsSystemInfo["zigbeeAddr"] = GlobalConfig::ZigbeeInfo_G.MyAddr; + jsSystemInfo["GateWayVersion"] = ReadStrByOpt(SYSTEMINFOFILE, "Version", "GateWayVersion"); + jsSystemInfo["SystemVersion"] = ReadStrByOpt(SYSTEMINFOFILE, "Version", "SystemVersion"); + jsSystemInfo["WebVersion"] = ReadStrByOpt(SYSTEMINFOFILE, "Version", "WebVersion"); + jsSystemInfo["GateWayHwVesion"] = ReadStrByOpt(SYSTEMINFOFILE, "Version", "GateWayHwVesion"); + jsSystemInfo["GateWayProduct"] = ReadStrByOpt(SYSTEMINFOFILE, "Version", "GateWayProduct"); + jsSystemInfo["serverStatus"] = GlobalConfig::serverStatus ; + + if(GlobalConfig::NetType == "\"NR5G-SA\"" || GlobalConfig::NetType == "\"NR5G-NSA\"" || + GlobalConfig::NetType == "\"NR5G\""){ + GlobalConfig::NetType = "5G"; + }else if(GlobalConfig::NetType == "\"LTE\""){ + GlobalConfig::NetType = "4G"; + } + if(GlobalConfig::NetStatus == "\"NOCONN\"" || GlobalConfig::NetStatus == "\"CONNECT\""){ + + if(GlobalConfig::NetSignal == 0){ + jsSystemInfo["communicationSignal"] = GlobalConfig::NetType + ",未知"; + } + else if(GlobalConfig::NetSignal > -80){ + jsSystemInfo["communicationSignal"] = GlobalConfig::NetType + ",优"; + }else if(GlobalConfig::NetSignal > -90 && GlobalConfig::NetSignal < -80){ + jsSystemInfo["communicationSignal"] = GlobalConfig::NetType + ",良"; + }else if(GlobalConfig::NetSignal > -105 && GlobalConfig::NetSignal < -90){ + jsSystemInfo["communicationSignal"] = GlobalConfig::NetType + ",一般"; + }else if(GlobalConfig::NetSignal < -105){ + jsSystemInfo["communicationSignal"] = GlobalConfig::NetType + ",弱"; + }else if(GlobalConfig::NetSignal < -115){ + jsSystemInfo["communicationSignal"] = GlobalConfig::NetType + ",不稳定"; + } + + }else if(GlobalConfig::NetStatus == "\"SEARCH\""){ + jsSystemInfo["communicationSignal"] = GlobalConfig::NetType + ",搜索网络"; + }else if(GlobalConfig::NetStatus == "\"LIMSRV\""){ + jsSystemInfo["communicationSignal"] = GlobalConfig::NetType + ",未插卡"; + }else{ + jsSystemInfo["communicationSignal"] = "未知"; + } + jsBody["SystemInfo"] = jsSystemInfo; @@ -719,7 +1142,13 @@ std::string JsonData::JsonCmd_Cgi_23(Param_23 ¶m) WriteStr2Config(SERVERCONFIG, "Server", "localServerIpAddress", param.mServerIp); WriteStr2Config(SERVERCONFIG, "Server", "localServerPort", param.mPort); - WriteStr2Config(SERVERCONFIG, "Server", "CommMode", param.mCommMode); + WriteStr2Config(SERVERCONFIG, "Server", "CommMode", /*param.mCommMode*/"2"); + WriteStr2Config(SERVERCONFIG, "Server", "UserName", param.mUserName); + WriteStr2Config(SERVERCONFIG, "Server", "Password", param.mPassword); + WriteStr2Config(SERVERCONFIG, "Server", "APN", param.mAPN); + char APN[100]={0x00}; + sprintf(APN,"sed -i '15c \t\t\t\t/opt/quectel-CM/quectel-CM -s %s > /dev/null &' /etc/init.d/S95check5G",param.mAPN.c_str()); + system(APN); system("reboot"); }else if(0 == param.mMode && !(CheckIP(param.mServerIp.c_str()))){ jsonVal["success"] = false; @@ -729,11 +1158,16 @@ std::string JsonData::JsonCmd_Cgi_23(Param_23 ¶m) Json::Value jsBody; jsSystemSetting["ServerIpAddress"] = ReadStrByOpt(SERVERCONFIG, "Server", "localServerIpAddress"); - jsSystemSetting["ServerPort"] = boost::lexical_cast(ReadStrByOpt(SERVERCONFIG, "Server", "localServerPort")); - jsSystemSetting["CommMode"] = boost::lexical_cast(ReadStrByOpt(SERVERCONFIG, "Server", "CommMode")); - + jsSystemSetting["ServerPort"] = atoi(ReadStrByOpt(SERVERCONFIG, "Server", "localServerPort").c_str()); + jsSystemSetting["CommMode"] = atoi(ReadStrByOpt(SERVERCONFIG, "Server", "CommMode").c_str()); + jsSystemSetting["ServerStatus"] = 1; + jsSystemSetting["UserName"] = ReadStrByOpt(SERVERCONFIG, "Server", "UserName"); + jsSystemSetting["Password"] = ReadStrByOpt(SERVERCONFIG, "Server", "Password"); + jsSystemSetting["APN"] = ReadStrByOpt(SERVERCONFIG, "Server", "APN"); jsBody["SystemSettings"] = jsSystemSetting; - jsonVal["content"] = jsBody; + jsonVal["content"] = jsBody; + + return showValue.write(jsonVal); } @@ -743,6 +1177,7 @@ std::string JsonData::JsonCmd_Cgi_23(Param_23 ¶m) std::string JsonData::JsonCmd_Cgi_25(Param_25 ¶m) { Json::Value jsonVal; + Json::Value jsonValnet; jsonVal.clear(); jsonVal["success"] = true; jsonVal["message"] = " "; @@ -750,32 +1185,71 @@ std::string JsonData::JsonCmd_Cgi_25(Param_25 ¶m) bool bFlag1 = CheckIP(param.mGateway.c_str()); bool bFlag2 = IsValidMask(param.mSubnetMask); bool bFlag3 = CheckIP(param.mIp.c_str()); - bool bFlag4 = CheckIP(param.mDnsName.c_str()); + bool bFlag4 = false; + if(param.mDnsName.size()>0){ + bFlag4 = CheckIP(param.mDnsName.c_str()); + }else{ + bFlag4 = true; + } + print_info("bFlag1 = %d,bFlag2 = %d,bFlag3 = %d,bFlag4 = %d\n",bFlag1,bFlag2,bFlag3,bFlag4); - if (0 == param.mMode &&(bFlag1 && bFlag2 && bFlag3 && bFlag4)) { - WriteStr2Config(NETWORKCONFIG, "Net", "dnsName", param.mDnsName); - WriteStr2Config(NETWORKCONFIG, "Net", "networkPortStatus", param.mNetworkPortStatus); - WriteStr2Config(NETWORKCONFIG, "Net", "gateway", param.mGateway); - WriteStr2Config(NETWORKCONFIG, "Net", "subnetMask", param.mSubnetMask); - WriteStr2Config(NETWORKCONFIG, "Net", "ipAddress", param.mIp); - WriteStr2Config(NETWORKCONFIG, "Net", "hostName", param.mHostName); - platform->EquipIpInit(); - system("reboot"); - }else if(0 == param.mMode &&(!bFlag1 || !bFlag2 || !bFlag3 || !bFlag4)){ + if (0 == param.mMode &&(bFlag1 && bFlag2 && bFlag3 && bFlag4) && param.mNetworkPortStatus == "STATIC") { + WriteStr2Config(NETWORKCONFIG, param.mNet, "dnsName", param.mDnsName); + WriteStr2Config(NETWORKCONFIG, param.mNet, "networkPortStatus", param.mNetworkPortStatus); + WriteStr2Config(NETWORKCONFIG, param.mNet, "gateway", param.mGateway); + WriteStr2Config(NETWORKCONFIG, param.mNet, "subnetMask", param.mSubnetMask); + WriteStr2Config(NETWORKCONFIG, param.mNet, "ipAddress", param.mIp); + WriteStr2Config(NETWORKCONFIG, param.mNet, "hostName", param.mHostName); + +#ifdef IMX6UL_GATEWAY + char GateWay[100]={0x00}; + sprintf(GateWay,"sed -i '7c route add default gw %s' /etc/init.d/S90start_userapp.sh",param.mGateway.c_str()); + print_info("GateWay = %s\n",GateWay); + system(GateWay); +#endif + platform->EquipIpInit(param.mNet); + + }else if(0 == param.mMode && param.mNetworkPortStatus == "DHCP"){ + WriteStr2Config(NETWORKCONFIG, param.mNet, "dnsName", ""); + WriteStr2Config(NETWORKCONFIG, param.mNet, "networkPortStatus", param.mNetworkPortStatus); + WriteStr2Config(NETWORKCONFIG, param.mNet, "gateway", ""); + WriteStr2Config(NETWORKCONFIG, param.mNet, "subnetMask", ""); + WriteStr2Config(NETWORKCONFIG, param.mNet, "ipAddress", ""); + WriteStr2Config(NETWORKCONFIG, param.mNet, "hostName", ""); + +#ifdef IMX6UL_GATEWAY + system("sed -i '7c udhcpc -i eth0 > /dev/null &' /etc/init.d/S90start_userapp.sh"); +#endif + platform->EquipIpInit(param.mNet); + + }else if(0 == param.mMode &&(!bFlag1 || !bFlag2 || !bFlag3 || !bFlag4) && param.mNetworkPortStatus == "STATIC"){ jsonVal["success"] = false; } - jsonVal["content"]["dnsName"] = ReadStrByOpt(NETWORKCONFIG, "Net", "dnsName"); - jsonVal["content"]["networkPortStatus"] = ReadStrByOpt(NETWORKCONFIG, "Net", "networkPortStatus"); - jsonVal["content"]["gateway"] = ReadStrByOpt(NETWORKCONFIG, "Net", "gateway"); - jsonVal["content"]["subnetMask"] = ReadStrByOpt(NETWORKCONFIG, "Net", "subnetMask"); - jsonVal["content"]["dataWatchIpAddress"] = ReadStrByOpt(NETWORKCONFIG, "Net", "ipAddress"); - jsonVal["content"]["hostName"] = ReadStrByOpt(NETWORKCONFIG, "Net", "hostName"); + jsonValnet["dnsName"] = ReadStrByOpt(NETWORKCONFIG, "eth0", "dnsName"); + jsonValnet["networkPortStatus"] = ReadStrByOpt(NETWORKCONFIG, "eth0", "networkPortStatus"); + jsonValnet["gateway"] = ReadStrByOpt(NETWORKCONFIG, "eth0" ,"gateway"); + jsonValnet["subnetMask"] = ReadStrByOpt(NETWORKCONFIG, "eth0", "subnetMask"); + jsonValnet["dataWatchIpAddress"] = ReadStrByOpt(NETWORKCONFIG, "eth0", "ipAddress"); + jsonValnet["hostName"] = ReadStrByOpt(NETWORKCONFIG, "eth0", "hostName"); + jsonVal["content"]["eth0"] = jsonValnet; + jsonVal["content"]["gatewaytype"] = 0; + +#ifdef G2UL_GATEWAY + jsonValnet["dnsName"] = ReadStrByOpt(NETWORKCONFIG, "eth1", "dnsName"); + jsonValnet["networkPortStatus"] = ReadStrByOpt(NETWORKCONFIG, "eth1", "networkPortStatus"); + jsonValnet["gateway"] = ReadStrByOpt(NETWORKCONFIG, "eth1", "gateway"); + jsonValnet["subnetMask"] = ReadStrByOpt(NETWORKCONFIG, "eth1", "subnetMask"); + jsonValnet["dataWatchIpAddress"] = ReadStrByOpt(NETWORKCONFIG, "eth1", "ipAddress"); + jsonValnet["hostName"] = ReadStrByOpt(NETWORKCONFIG, "eth1", "hostName"); + jsonVal["content"]["eth1"] =jsonValnet; + jsonVal["content"]["gatewaytype"] = 1; +#endif return showValue.write(jsonVal); } -std::string JsonData::JsonCmd_Cgi_26() +std::string JsonData::JsonCmd_Cgi_26(Param_26 ¶m) { Json::Value jsonVal; jsonVal.clear(); @@ -785,59 +1259,107 @@ std::string JsonData::JsonCmd_Cgi_26() jsonVal["success"] = true; jsonVal["message"] = " "; + char looseValue[10]={0x00}; + readStringValue("config", "loose",looseValue,(char*)GlobalConfig::Config_G.c_str()); + print_debug("loose = %f \n",atof(looseValue)); Json::Value jsArray; array_t arrRes; - arrRes = sql_ctl->GetDataMultiLine(T_SENSOR_INFO(TNAME), "*", NULL); + arrRes = sql_ctl->GetDataMultiLineTransaction(T_SENSOR_INFO(TNAME), "*", NULL); int iResult = arrRes.size(); - printf("iResult = %d\n",iResult); if (iResult > 0) { - for (int j = 0; j < iResult; j++) { + int packgeNo = param.mPackageFlag; + int packgeMax = 0; + int packgeNum = 0; + jsonVal["package"] = packgeNo; + int lastSize = iResult % 10; + int index = iResult / 10; + if(lastSize > 0 && index > 0){ + packgeMax = index +1; + if(packgeNo +1 == packgeMax){ + packgeNum = iResult; + jsonVal["packageMax"] = index + 1; + } + else{ + packgeNum = (packgeNo+1) * 10; + jsonVal["packageMax"] = index +1;} + } + else if(lastSize == 0 && index > 0){ + packgeNum = (packgeNo+1) * 10; + packgeMax = index; + jsonVal["packageMax"] = index; + }else if(lastSize > 0 && index == 0){ + packgeNum = lastSize; + packgeMax = index+1; + jsonVal["packageMax"] = index; + } + + printf("26 packgeNo = %d,packgeNum = %d,lastSize = %d,index = %d\n",packgeNo,packgeNum,lastSize,index); + for (int j = packgeNo * 10; j < packgeNum; j++) { Json::Value jsSensorData; jsSensorData["dataNodeNo"] = arrRes[j][0]; jsSensorData["dataNodeName"] = arrRes[j][1]; - jsSensorData["initFlag"] = boost::lexical_cast(arrRes[j][2]); - jsSensorData["accFlag"] = boost::lexical_cast(arrRes[j][3]); - jsSensorData["zigbeeFlag"] = boost::lexical_cast(arrRes[j][4]); - jsSensorData["temTopFlag"] = boost::lexical_cast(arrRes[j][5]); - jsSensorData["temBotFlag"] = boost::lexical_cast(arrRes[j][6]); + jsSensorData["initFlag"] = atoi(arrRes[j][2].c_str()); + jsSensorData["accFlag"] = atoi(arrRes[j][3].c_str()); + jsSensorData["zigbeeFlag"] = atoi(arrRes[j][4].c_str()); + jsSensorData["temTopFlag"] = atoi(arrRes[j][5].c_str()); + jsSensorData["temBotFlag"] = atoi(arrRes[j][6].c_str()); jsSensorData["hardVersion"] = arrRes[j][8]; jsSensorData["softVersion"] = arrRes[j][9]; jsSensorData["bpNo"] = arrRes[j][10]; jsSensorData["serialNo"] = arrRes[j][11]; jsSensorData["firstPowerTime"] = arrRes[j][12]; - jsSensorData["WakeupTime"] = boost::lexical_cast(arrRes[j][13]); - jsSensorData["StaticTime"] = boost::lexical_cast(arrRes[j][14]); - jsSensorData["WaveTime"] = boost::lexical_cast(arrRes[j][15]); + jsSensorData["WakeupTime"] = atoi(arrRes[j][13].c_str()); + jsSensorData["StaticTime"] = atoi(arrRes[j][14].c_str()); + jsSensorData["WaveTime"] = atoi(arrRes[j][15].c_str()); jsSensorData["BateryV"] = arrRes[j][16]; jsSensorData["ProductNo"] = arrRes[j][17]; - jsSensorData["configFlag"] = boost::lexical_cast(arrRes[j][18]); + jsSensorData["configFlag"] = atoi(arrRes[j][18].c_str()); jsSensorData["startBrands"] = arrRes[j][19]; jsSensorData["stopBrands"] = arrRes[j][20]; - jsSensorData["featureInterVal"] = boost::lexical_cast(arrRes[j][21]); - jsSensorData["waveInterVal"] = boost::lexical_cast(arrRes[j][22]); - jsSensorData["samplingRate"] = boost::lexical_cast(arrRes[j][23]); - // jsSensorData["scope"] = boost::lexical_cast(arrRes[j][24]); - jsSensorData["range"] = boost::lexical_cast(arrRes[j][25]); + jsSensorData["featureInterVal"] = atoi(arrRes[j][21].c_str()); + jsSensorData["waveInterVal"] = atoi(arrRes[j][22].c_str()); + jsSensorData["samplingRate"] = atoi(arrRes[j][23].c_str()); + // jsSensorData["scope"] = atoi(arrRes[j][24]); + jsSensorData["range"] = atoi(arrRes[j][25].c_str()); jsSensorData["envelopeBandPass"] = arrRes[j][26]; jsSensorData["faultFrequency"] = arrRes[j][27]; jsSensorData["zigbeePanId"] = arrRes[j][28]; - jsSensorData["zigbeeChannel"] = boost::lexical_cast(arrRes[j][29]); + jsSensorData["zigbeeChannel"] = (arrRes[j][29]); jsSensorData["zigbeeAddr"] = arrRes[j][30]; jsSensorData["zigbeeLongAddr"] = arrRes[j][31]; jsSensorData["zigbeeDesAddr"] = arrRes[j][32]; - jsSensorData["ZigbeePower"] = boost::lexical_cast(arrRes[j][33]); - jsSensorData["ZigbeeRetry"] = boost::lexical_cast(arrRes[j][34]); - jsSensorData["ZigbeeRetryGap"] = boost::lexical_cast(arrRes[j][35]); - jsSensorData["ACCSampleTime"] = boost::lexical_cast(arrRes[j][36]); - jsSensorData["status"] = boost::lexical_cast(arrRes[j][37]); + jsSensorData["ZigbeePower"] = atoi(arrRes[j][33].c_str()); + jsSensorData["ZigbeeRetry"] = atoi(arrRes[j][34].c_str()); + jsSensorData["ZigbeeRetryGap"] = atoi(arrRes[j][35].c_str()); + jsSensorData["ACCSampleTime"] = atoi(arrRes[j][36].c_str()); + jsSensorData["status"] = atoi(arrRes[j][37].c_str()); jsSensorData["timeStamp"] = arrRes[j][38]; - jsSensorData["viff"] = boost::lexical_cast(arrRes[j][39]); - jsSensorData["RSSI"] = boost::lexical_cast(arrRes[j][40]); + jsSensorData["viff"] = atoi(arrRes[j][39].c_str()); + if(atof(looseValue) < atof(arrRes[j][42].c_str())){ + jsSensorData["loose"] = "1"; + }else{ + jsSensorData["loose"] = "0"; + } + + //获取最新zigbee信号 + char szTableName[50]={0x00},selectCon[128]={0x00}; + sprintf(szTableName,"t_dataStatic_%s",arrRes[j][0].c_str()); + memset(selectCon,0x00,sizeof(selectCon)); + sprintf(selectCon, "zigbeeSignal <> '' ORDER BY timeStamp desc LIMIT 0,1"); + string strZigbeeSignal = sql_ctl->GetData(szTableName, "zigbeeSignal", selectCon); + if(strZigbeeSignal == "") + jsSensorData["RSSI"] = arrRes[j][40]; + else + jsSensorData["RSSI"] = strZigbeeSignal; + jsSensorData["update"] = atoi(arrRes[j][41].c_str()); jsArray.append(jsSensorData); } } else { jsArray.resize(0); + jsonVal["success"] = true; } + jsonVal["gatewayMac"] = GlobalConfig::MacAddr_G ; + jsonVal["gatewayIP"] = GlobalConfig::IpAddr_G ; jsonVal["content"]["dataNodeArray"] = jsArray; return showValue.write(jsonVal); } @@ -859,6 +1381,13 @@ std::string JsonData::JsonCmd_Cgi_27(Param_27 ¶m) sql_ctl->DeleteTableData(T_SENSOR_INFO(TNAME), whereCon); sql_ctl->DeleteTableData(T_DATA_INFO(TNAME), whereCon); sql_ctl->DeleteTableData(T_DATASTATIC_INFO(TNAME), whereCon); + sql_ctl->DeleteTableData(T_DATANODE_TIME(TNAME), whereCon); + char szTableName[50]={0x00}; + sprintf(szTableName,"DROP TABLE t_data_%s",param.mDataNodeNo.c_str()); + sql_ctl->CreateTable(szTableName, 0); + memset(szTableName,0x00,sizeof(szTableName)); + sprintf(szTableName,"DROP TABLE t_dataStatic_%s",param.mDataNodeNo.c_str()); + sql_ctl->CreateTable(szTableName, 0); } else { jsonVal["success"] = false; jsonVal["message"] = "没有传感器号"; @@ -900,6 +1429,12 @@ std::string JsonData::JsonCmd_Cgi_29(Param_29 ¶m) jsonVal["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; jsonVal["success"] = true; jsonVal["message"] = " "; + std::vector vecWave; + /* 新增代码 */ + char whereCon[64] = {}; + sprintf(whereCon, "dataNodeNo='%s'",param.mDataNodeNo.c_str()); + vec_t res = sql_ctl->GetDataSingleLine(T_SENSOR_INFO(TNAME)," * ",whereCon); + char localtimestamp[32] = { 0 }; std::string strWaveData = ""; std::string filename = "/opt/data/" + param.mChannelId + ".dat"; if (access(filename.c_str(), 0) >= 0) { @@ -910,10 +1445,21 @@ std::string JsonData::JsonCmd_Cgi_29(Param_29 ¶m) jsonVal["message"] = "error"; } else { float fTemp = 0; - std::vector vecWave; + + //std::vector hanningWave; + inFile.read((char *)localtimestamp,sizeof(localtimestamp)); while (inFile.read((char *)&fTemp, sizeof(fTemp))) { vecWave.push_back(fTemp); } + //测试正弦波 + //pCalculation->GenerateSin(vecWave); + + //添加汉宁窗 + /*pCalculation->Hanning(vecWave, hanningWave); + for(int i = 0; i < vecWave.size();i++){ + vecWave[i] = (vecWave[i]*hanningWave[i]); + }*/ + int flag = param.mPackageFlag; flag = (flag + 1) * 1024; int number = vecWave.size(); @@ -952,8 +1498,18 @@ std::string JsonData::JsonCmd_Cgi_29(Param_29 ¶m) jsBody["channelId"] = param.mChannelId; jsBody["package"] = param.mPackageFlag; - jsBody["Data"] = strWaveData; + print_info("vecWave.size() = %d,sample = %d,second = %f\n",vecWave.size(),atoi(res[23].c_str()),float(vecWave.size()/atoi(res[23].c_str()))); + string::size_type comper = param.mChannelId.find("Z"); + if (comper != string::npos && res[17]=="02"){ + jsBody["second"] = float((float)vecWave.size()/(float)atoi(res[23].c_str())); + }else if(res[17]=="01"){ + jsBody["second"] = float((float)vecWave.size()/(float)atoi(res[23].c_str())); + }else{ + jsBody["second"] = 1; + } + jsBody["Data"] = strWaveData; + jsBody["timestamp"] = string(localtimestamp); jsonVal["content"] = jsBody; return showValue.write(jsonVal); @@ -961,52 +1517,7 @@ std::string JsonData::JsonCmd_Cgi_29(Param_29 ¶m) std::string JsonData::JsonCmd_Cgi_30(Param_30 ¶m) { - /*Json::Value jsonVal; - jsonVal.clear(); - jsonVal["cmd"] = "30"; - jsonVal["success"] = true; - jsonVal["message"] = ""; - Json::Value jsBody; - std::string strWaveData; - // if (GlobalConfig::WaveCgi.flag == 1) { - // int number = GlobalConfig::WaveCgi.number; - // char buf[32]; - // int flag = param.mPackageFlag; - // flag = (flag + 1) * 1024; - // int start = param.mPackageFlag * 1024; - // if ( number < 1024) { - // flag = number; - // start = 0; - // } - - // for (int i = start; i < flag; i++) { - // if ( i == start ) { - // strWaveData = (boost::lexical_cast(GlobalConfig::WaveCgi.waveData[i])).substr(0.4); - // } else { - // memset(buf, 0, 32); - // sprintf(buf, "%.2f", GlobalConfig::WaveCgi.waveData[i]); - // std::string waveTemp(buf); - // strWaveData = strWaveData + "," + waveTemp; - // } - // } - // int max = number / 1024; - // if (max == 0 && number > 0) { - // max = 1; - // } - // jsBody["packageMax"] = max; - // } else { - // jsonVal["success"] = false; - // jsonVal["message"] = "数据获取失败"; - // } - - - jsBody["channelId"] = param.mChannelId; - jsBody["package"] = param.mPackageFlag; - jsBody["Data"] = strWaveData; - - jsonVal["content"] = jsBody; - return showValue.write(jsonVal);*/ Json::Value jsonVal; Json::Value jsBody; Json::Value SystemSetting; @@ -1019,6 +1530,16 @@ std::string JsonData::JsonCmd_Cgi_30(Param_30 ¶m) int i = 0; std::string strWaveData; std::string filename = "/opt/data/" + param.mChannelId + ".dat"; + char localtimestamp[32] = { 0 }; + std::vector vecWave; + std::vector hanningWave; + std::vector addhanningWave; + std::vector fftWave; + int sampleRateReference = 0; + /* 新增代码 */ + char whereCon[64] = {}; + sprintf(whereCon, "dataNodeNo='%s'",param.mDataNodeNo.c_str()); + vec_t res = sql_ctl->GetDataSingleLine(T_SENSOR_INFO(TNAME)," * ",whereCon); if (access(filename.c_str(), 0) >= 0) { std::ifstream inFile(filename.c_str(),ios::in|ios::binary); @@ -1029,109 +1550,64 @@ std::string JsonData::JsonCmd_Cgi_30(Param_30 ¶m) jsonVal["message"] = "error"; }else{ float fTemp = 0; - std::vector vecWave; - std::vector fftWave; - while(inFile.read((char *)&fTemp,sizeof(fTemp))) - { // 取8K进行计算 - if(i < 8192) - { - vecWave.push_back(fTemp); - }else{ - break; + + + inFile.read((char *)localtimestamp,sizeof(localtimestamp)); + string::size_type comper = param.mChannelId.find("Z"); + if (comper != string::npos && res[17]=="02") { + while(inFile.read((char *)&fTemp,sizeof(fTemp))) + { + vecWave.push_back(fTemp); } - i++; - } - /*std::string strWaveData1 = ""; - char buff[32] = {0}; - for(int j=0;j %s,vecWave.size()=%d\n", strWaveData1.c_str(),vecWave.size());*/ - //进行傅立叶变换 - pCalculation->FFTSpec(vecWave, fftWave); - printf("2---------------------------------------------->%d\n",fftWave.size()); - printf("2---------------------------------------------->%f\n",fftWave[10]); - /*std::string strWaveData2 = ""; - char bufff[32] = {0}; - for(int k=0;kfftWave.size()=%d\n", fftWave.size()); - //print_info("after fft---------------------------------------------------> %s,fftWave.size()=%d\n", strWaveData2.c_str(),fftWave.size()); - /* int flag = param.mPackageFlag; - //print_info("*********************************param.mPackageFlag=%d\n",param.mPackageFlag); - flag = (flag + 1) * 1024; - int number = fftWave.size(); - int start = param.mPackageFlag * 1024; - if (number < 1024) - { - flag = number; - start = 0; - } - char buf[32] = {0}; - //print_info("start=%d,flag=%d\n",start,flag); - for (int i = start; i < flag; i++) - { - if (i == start) - { - memset(buf, 0, 32); - sprintf(buf, "%.2f", fftWave[i]); - std::string waveTemp(buf); - if (0 == i) + //进行傅立叶变换 + pCalculation->FFTSpec(vecWave, fftWave); + sampleRateReference = 1000; + + }else{ + while(inFile.read((char *)&fTemp,sizeof(fTemp))) + { // 取8K进行计算 + if(i < 8192) { - strWaveData = boost::lexical_cast(0); + vecWave.push_back(fTemp); }else{ - strWaveData = waveTemp; + break; } - }else{ - memset(buf, 0, 32); - sprintf(buf, "%.2f", fftWave[i]); - std::string waveTemp(buf); - strWaveData = strWaveData + "," + waveTemp; - } + i++; + } + //测试正弦波 + //pCalculation->GenerateSin(vecWave); + + if(vecWave.size() < 8192){ + for(int i = vecWave.size(); i < 8192;i++){ + vecWave.push_back(0); + } + } + //添加汉宁窗 + pCalculation->Hanning(vecWave, hanningWave); + for(int i = 0; i < vecWave.size();i++){ + addhanningWave.push_back(vecWave[i]*hanningWave[i]); + } + + //进行傅立叶变换 + pCalculation->FFTSpec(addhanningWave, fftWave); + sampleRateReference = 1024; } - //print_info("@strwavedata=%s@,strWaveData.sizeof=%d,fftWave.size()=%d\n",strWaveData.c_str(),strWaveData.size(),fftWave.size()); - int max = number / 1024; - //print_info("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&max=%d\n",max); - if (max == 0 && number > 0) - { - max = 1; - } - jsBody["packageMax"] = max; */ + /*for(int i = 0; i < fftWave.size();i++){ + fftWave[i] = fftWave[i]*2; + }*/ + printf("2---------------------------------------------->vecWave = %d,fftWave = %d\n",vecWave.size(),fftWave.size()); + int flag = param.mPackageFlag; - flag = (flag + 1) * 1024; + flag = (flag + 1) * sampleRateReference; int number = fftWave.size(); - int start = param.mPackageFlag * 1024; + printf("number---------------------------------------------->%d\n",number); + int start = param.mPackageFlag * sampleRateReference; printf("param.mPackageFlag = %d\n",param.mPackageFlag); printf("param.start = %d\n",start); printf("param.flag = %d\n",flag); - if (number < 1024) { - flag = number; - start = 0; + if (number < sampleRateReference) { + flag = number; + start = 0; } char buf[32]; for (int i = start; i < flag; i++) { @@ -1149,29 +1625,51 @@ std::string JsonData::JsonCmd_Cgi_30(Param_30 ¶m) } } - int max = number / 1024; + int max = number / sampleRateReference; if (max == 0 && number > 0) { - max = 1; + max = 1; } jsBody["packageMax"] = max; + + + } } else { - jsonVal["success"] = false; - jsonVal["message"] = "数据获取失败"; - } + jsonVal["success"] = false; + jsonVal["message"] = "没有数据文件"; + } jsBody["channelId"] = param.mChannelId; jsBody["package"] = param.mPackageFlag; + jsBody["timestamp"] = string(localtimestamp); jsBody["Data"] = strWaveData; - /* 新增代码 */ - char whereCon[64] = {}; - sprintf(whereCon, "dataNodeNo='%s'",param.mDataNodeNo.c_str()); - std::string sample_rate = sql_ctl->GetData(T_SENSOR_INFO(TNAME), T_SENSOR_INFO(SAMPLINGRATE), whereCon); - printf("@@@@@@@@@@@@@@@@@@@@sample_rate=%s\n",sample_rate.c_str()); - int SampleRate = boost::lexical_cast(sample_rate.c_str()); - double resolution = (double)SampleRate / 8192; - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@the sample rate is %d,the resolution %f\n",SampleRate,resolution); + + + + double resolution = 0.0; + int SampleRate =0; + print_info("sensor type %s\n",res[17].c_str()); + if(res[17]=="01"){ + SampleRate = atoi(res[23].c_str()); + printf("@@@@@@@@@@@@@@@@@@@@sample_rate=%d\n",SampleRate); + resolution = (((double)SampleRate/1000)*1024)/ 8192; + + }else if(res[17]=="02"){ + string::size_type comper = param.mChannelId.find("Z"); + if (comper != string::npos) { + SampleRate = atoi(res[23].c_str()); + resolution = (double)SampleRate/vecWave.size(); + //resolution = (((double)vecWave.size()/1000)*1024)/ (SampleRate * ((vecWave.size()/SampleRate))); + printf("@@@@@@@@@@@@@@@@@@@@sample_rate=%d,resolution = %f\n",SampleRate,resolution); + }else{ + SampleRate = 8000; + printf("@@@@@@@@@@@@@@@@@@@@sample_rate=%d\n",SampleRate); + resolution = (((double)SampleRate/1024)*1024)/ 8192; + } + } + + print_info("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@the sample rate is %d,the resolution %f\n",SampleRate,resolution); char buf[32]; memset(buf, 0, 32); sprintf(buf, "%f", resolution); @@ -1180,6 +1678,253 @@ std::string JsonData::JsonCmd_Cgi_30(Param_30 ¶m) jsonVal["content"] = jsBody; return showValue.write(jsonVal); } +std::string JsonData::JsonCmd_Cgi_40(Param_40 ¶m) +{ + + Json::Value jsonVal; + Json::Value jsBody; + Json::Value SystemSetting; + jsonVal.clear(); + + jsonVal["cmd"] = "40"; + jsonVal["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; + jsonVal["success"] = true; + jsonVal["message"] = ""; + int i = 0; + int sampleRateReference = 0; + std::vector vecWave; + /* 新增代码 */ + char whereCon[64] = {}; + sprintf(whereCon, "dataNodeNo='%s'",param.mDataNodeNo.c_str()); + vec_t res = sql_ctl->GetDataSingleLine(T_SENSOR_INFO(TNAME)," * ",whereCon); + std::string strWaveData; + std::string filename = "/opt/data/" + param.mChannelId + ".dat"; + char localtimestamp[32] = { 0 }; + if (access(filename.c_str(), 0) >= 0) + { + std::ifstream inFile(filename.c_str(),ios::in|ios::binary); + if(!inFile) + { + print_error("read channel data error\n"); + jsonVal["success"] = "false"; + jsonVal["message"] = "error"; + }else{ + float fTemp = 0; + + std::vector envWave; + std::vector hanningWave; + std::vector addhanningWave; + inFile.read((char *)localtimestamp,sizeof(localtimestamp)); + string::size_type comper = param.mChannelId.find("Z"); + if (comper != string::npos && res[17]=="02") { + while(inFile.read((char *)&fTemp,sizeof(fTemp))) + { + vecWave.push_back(fTemp); + } + //添加汉宁窗 + pCalculation->Hanning(vecWave, hanningWave); + for(int i = 0; i < vecWave.size();i++){ + addhanningWave.push_back(vecWave[i]*hanningWave[i]); + } + + //进行傅立叶变换 + if(param.StartFrequency == 0){ + param.StartFrequency = 3000; + param.EndFrequency = 5000; + } + + pCalculation->envSpec(addhanningWave, envWave,param.StartFrequency,param.EndFrequency); + sampleRateReference = 1000; + + }else{ + while(inFile.read((char *)&fTemp,sizeof(fTemp))) + { // 取8K进行计算 + if(i < 8192) + { + vecWave.push_back(fTemp); + }else{ + break; + } + i++; + } + if(vecWave.size() < 8192){ + for(int i = vecWave.size(); i < 8192;i++){ + vecWave.push_back(0); + } + } + + //添加汉宁窗 + pCalculation->Hanning(vecWave, hanningWave); + for(int i = 0; i < vecWave.size();i++){ + addhanningWave.push_back(vecWave[i]*hanningWave[i]); + } + + //进行傅立叶变换 + if(param.StartFrequency == 0){ + param.StartFrequency = 3000; + param.EndFrequency = 5000; + } + + pCalculation->envSpec(addhanningWave, envWave,param.StartFrequency,param.EndFrequency); + sampleRateReference = 1024; + } + /*for(int i = 0; i < envWave.size();i++){ + envWave[i] = envWave[i]*2; + }*/ + + printf("2---------------------------------------------->%d\n",envWave.size()); + printf("2---------------------------------------------->%f\n",envWave[10]); + + print_info("after fft--------------------------------------------------->fftWave.size()=%d\n", envWave.size()); + + int flag = param.mPackageFlag; + flag = (flag + 1) * sampleRateReference; + int number = envWave.size(); + int start = param.mPackageFlag * sampleRateReference; + printf("param.mPackageFlag = %d\n",param.mPackageFlag); + printf("param.start = %d\n",start); + printf("param.flag = %d\n",flag); + if (number < sampleRateReference) { + flag = number; + start = 0; + } + char buf[32]; + for (int i = start; i < flag; i++) { + if ( i == start ) { + memset(buf, 0, 32); + sprintf(buf, "%.6f", envWave[i]); + std::string waveTemp(buf); + strWaveData = waveTemp; + + } else { + memset(buf, 0, 32); + sprintf(buf, "%.6f", envWave[i]); + std::string waveTemp(buf); + strWaveData = strWaveData + "," + waveTemp; + } + } + + int max = number / sampleRateReference; + if (max == 0 && number > 0) { + max = 1; + } + jsBody["packageMax"] = max; + + } + } else { + jsonVal["success"] = false; + jsonVal["message"] = "没有数据文件"; + } + + + jsBody["channelId"] = param.mChannelId; + jsBody["package"] = param.mPackageFlag; + jsBody["timestamp"] = string(localtimestamp); + jsBody["Data"] = strWaveData; + + double resolution = 0.0; + int SampleRate =0; + print_info("sensor type %s\n",res[17].c_str()); + if(res[17]=="01"){ + SampleRate = atoi(res[23].c_str()); + printf("@@@@@@@@@@@@@@@@@@@@sample_rate=%d\n",SampleRate); + resolution = (((double)SampleRate/1000)*1024)/ 8192; + }else if(res[17]=="02"){ + string::size_type comper = param.mChannelId.find("Z"); + if (comper != string::npos) { + SampleRate = atoi(res[23].c_str()); + + resolution = (double)SampleRate/vecWave.size(); + printf("@@@@@@@@@@@@@@@@@@@@sample_rate=%d,resolution = %f\n",SampleRate,resolution); + }else{ + SampleRate = 8000; + printf("@@@@@@@@@@@@@@@@@@@@sample_rate=%d\n",SampleRate); + resolution = (((double)SampleRate/1000)*1024)/ 8192; + } + } + + printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@the sample rate is %d,the resolution %f\n",SampleRate,resolution); + char buf[32]; + memset(buf, 0, 32); + sprintf(buf, "%f", resolution); + jsBody["resolution"] = std::string(buf); + + jsonVal["content"] = jsBody; + return showValue.write(jsonVal); +} +std::string JsonData::JsonCmd_Cgi_41(std::vector ¶m) +{ + Json::Value jsonVal; + jsonVal.clear(); + + jsonVal["cmd"] = "41"; + jsonVal["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; + jsonVal["success"] = true; + jsonVal["message"] = " "; + + char whereCon[1024] = {0}; + char updateSql[1024] = { 0 }; + //int WaveInteerVal = param.mwaveInterVal/param.mfeatureInterVal; + for(int i = 0; i < param.size();i++){ + sprintf(updateSql, "featureInterVal='%d',waveInterVal='%d',range='%d',samplingRate='%d',AccSampleTime = '%d',\ + startBrands = '%s',stopBrands = '%s',envelopeBandPass = '%s',viff = '%d',faultFrequency = '%s' ,UpdateFlag = 0", + param[i].mfeatureInterVal, param[i].mwaveInterVal,param[i].mrange,\ + param[i].msamplingRate,param[i].mAccSampleTime, param[i].mstartBrands.c_str(),\ + param[i].mstopBrands.c_str(),param[i].menvelopeBandPass.c_str(),param[i].mviff,param[i].mfaultFrequency.c_str()); + sprintf(whereCon, "dataNodeNo='%s'", param[i].mdataNodeNo.c_str()); + + int iRet = sql_ctl->UpdateTableData(T_SENSOR_INFO(TNAME), updateSql, whereCon); + memset(whereCon,0x00,sizeof(whereCon)); + memset(updateSql,0x00,sizeof(updateSql)); + if(iRet != 0) + jsonVal["success"] = false; + } + return showValue.write(jsonVal); +} +std::string JsonData::JsonCmd_Cgi_42(Param_42 ¶m) +{ + Json::Value jsonVal; + jsonVal.clear(); + jsonVal["cmd"] = "42"; + jsonVal["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; + jsonVal["success"] = true; + jsonVal["message"] = "上传成功!"; + char cmd[100]={0x00}; + strcpy(cmd,"rm -rf /tmp/cgic*"); + system(cmd); + if(param.fileName == "DataNode.tar"){ + string strcmd = "tar xvf /opt/"; + strcmd = strcmd + param.fileName; + strcmd = strcmd + " -C /opt/"; + print_info("strcmd = %s\n",strcmd.c_str()); + system(strcmd.c_str()); + }else if(param.fileName == "rfsbu.tar"){ + sleep(3); + print_info("strcmd = %s\n",param.fileName.c_str()); + system("/opt/opt.sh"); + }else if(param.fileName == "update.json"){ + print_info("strcmd = %s\n",param.fileName.c_str()); + + ReadStrConfig("/opt/update.json"); + }else if(param.fileName == "DataNode.csv"){ + print_info("strcmd = %s\n",param.fileName.c_str()); + + int iRet = UpdataDataNodeConfig("/opt/DataNode.csv"); + string str = to_string(iRet) + "个传感器更新成功"; + if(iRet < 0){ + jsonVal["success"] = false; + jsonVal["message"] = "更新失败!"; + }else{ + jsonVal["success"] = true; + jsonVal["message"] = str; + } + + }else { + jsonVal["success"] = false; + jsonVal["message"] = "文件名错误!"; + } + return showValue.write(jsonVal); +} std::string JsonData::JsonCmd_Cgi_31(Param_31 ¶m) { @@ -1202,6 +1947,8 @@ std::string JsonData::JsonCmd_Cgi_31(Param_31 ¶m) jsonVal["success"] = true; jsBody["channel"] = ReadStrByOpt(ZIGBEECONFIG, "Zigbee", "channel"); jsBody["panID"] = GlobalConfig::ZigbeeInfo_G.PanID; + jsBody["RetryNum"] = GlobalConfig::ZigbeeInfo_G.RetryNum; + jsBody["TranTimeout"] = GlobalConfig::ZigbeeInfo_G.TranTimeout; jsBody["status"] = "1"; jsonVal["content"] = jsBody; @@ -1368,5 +2115,167 @@ std::string JsonData::JsonCmd_Cgi_47(Param_47 ¶m) return showValue.write(jsonVal); } +std::string JsonData::JsonCmd_Cgi_50() +{ + Json::Value jsonVal; + jsonVal.clear(); + + jsonVal[JSON_FIELD_CMD] = "50"; + jsonVal["success"] = true; + jsonVal["message"] = ""; + + std::string strFileName = "",strSoftVersion = ""; + Json::Value root; + Json::Value jsBody; + Json::Reader reader; + std::vector value; + std::vector vecDataNodeUpdate; + DataNodeUpdate datanodeUpdate; + std::fstream is; + is.open("/opt/DataNode/config.json", std::ios::in); + if (reader.parse(is, root)) { + jsBody["sensor"] = root; + } + jsBody["GateWayVersion"] = ReadStrByOpt(SYSTEMINFOFILE, "Version", "GateWayVersion"); + jsBody["SystemVersion"] = ReadStrByOpt(SYSTEMINFOFILE, "Version", "SystemVersion"); + jsBody["WebVersion"] = ReadStrByOpt(SYSTEMINFOFILE, "Version", "WebVersion"); + jsonVal["content"] = jsBody; + return showValue.write(jsonVal); +} +std::string JsonData::JsonCmd_Cgi_51(Param_51 ¶m) +{ + Json::Value jsonVal; + jsonVal.clear(); + Json::Value jsBody; + jsonVal[JSON_FIELD_CMD] = "51"; + jsonVal["success"] = true; + jsonVal["message"] = ""; + + char whereCon[1024] = {0}; + char updateSql[1024] = { 0 }; + string gatewayLocation = ""; + + sprintf(updateSql, "gatewayLocation='%s'", + param.strGateWayLocation.c_str()); + sprintf(whereCon, "gatewayMAC='%s'", param.strGateWayMAC.c_str()); + if(param.mMode == 0){ + int iRet = sql_ctl->UpdateTableData(T_GATEWAY_INFO(TNAME), updateSql, whereCon); + if(iRet != 0) + jsonVal["success"] = false; + }else{ + gatewayLocation = sql_ctl->GetData(T_GATEWAY_INFO(TNAME) ,"gatewayLocation", NULL); + jsBody["gateWayLocation"] = gatewayLocation; + } + + + + jsonVal["content"] = jsBody; + + return showValue.write(jsonVal); +} +std::string JsonData::JsonCmd_Cgi_52(Param_52 ¶m) +{ + Json::Value jsonVal; + Json::Value jsBody; + + jsonVal.clear(); + jsonVal["cmd"] = "52"; + jsonVal["dataWatchNo"] = GlobalConfig::MacAddr_G; + jsonVal["cmdSerial"] = param.mCmdSerial; + jsonVal["success"] = true; + jsonVal["message"] = " "; + + if (0 == param.mMode) { // 扫描 + wifi::WPAClient wpa; + std::string netssid = wpa.GetNetSsid(); + std::vector vecSsid; + boost::split(vecSsid, netssid, boost::is_any_of("\n"), boost::token_compress_off); + jsBody["type"] = "SCAN"; + print_info("netssid : %s %d\n", netssid.c_str(), vecSsid.size()); + for (unsigned int i = 1; i < vecSsid.size() - 1; i++) { + std::vector data; + boost::split(data, vecSsid[i], boost::is_any_of("\t"), boost::token_compress_off); + Json::Value wifiInfo; + wifiInfo["bssid"] = data[0]; + wifiInfo["frequency"] = data[1]; + wifiInfo["signallevel"] = data[2]; + wifiInfo["secure"] = data[3]; + wifiInfo["ssid"] = data[4]; + jsBody["wifilist"].append(wifiInfo); + + } + } else if ( 1 == param.mMode) { // 设置 + print_info("set WiFi\n"); + wifi::WPAClient wpa; + jsBody["ssid"] = param.mSsid; + if (param.mPassWord.length() > 0) { + if (wpa.ConnectWiFi(param.mSsid.c_str(), param.mPassWord.c_str())) { + jsBody["status"] = true; + } else { + jsBody["status"] = false; + } + } else { + if (wpa.ConnectWiFiWithNoPassword(param.mSsid.c_str())) { + jsBody["status"] = true; + } else { + jsBody["status"] = false; + } + } + } else if ( 2 == param.mMode ) { // 获取 + wifi::WPAClient wpa; + std::string ssid = " "; + int rssi = 0; + ssid = wpa.GetCurrentSSID(); + rssi = wpa.GetWiFiRssi() ; + jsBody["ssid"] = ssid; + jsBody["rssi"] = rssi; + } else if ( 3 == param.mMode ) { + wifi::WPAClient wpa; + if (wpa.CleanWifi()) { + jsonVal["message"] = "wifi断开成功"; + } else { + jsonVal["message"] = "wifi断开失败"; + } + } + + jsonVal["content"] = jsBody; + return showValue.write(jsonVal); +} + +std::string JsonData::JsonCmd_Cgi_53(std::vector ¶m) +{ + Json::Value jsonVal; + jsonVal.clear(); + + jsonVal["cmd"] = "53"; + jsonVal["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; + jsonVal["success"] = true; + jsonVal["message"] = " "; + + char whereCon[1024] = {0}; + char updateSql[1024] = { 0 }; + for(int i = 0; i < param.size();i++){ + if(param[i].mUpdateKey2 == ""){ + sprintf(updateSql, "%s='%s',UpdateFlag = 0", + param[i].mUpdateKey.c_str(), param[i].mUpdateValue.c_str()); + }else if(param[i].mUpdateKey3 == "" && param[i].mUpdateKey2 != ""){ + sprintf(updateSql, "%s='%s',%s='%s',UpdateFlag = 0", + param[i].mUpdateKey.c_str(), param[i].mUpdateValue.c_str(),param[i].mUpdateKey2.c_str(), param[i].mUpdateValue2.c_str()); + }else if(param[i].mUpdateKey3 != "" && param[i].mUpdateKey2 != ""){ + sprintf(updateSql, "%s='%s',%s='%s',%s='%s',UpdateFlag = 0", + param[i].mUpdateKey.c_str(), param[i].mUpdateValue.c_str(),param[i].mUpdateKey2.c_str(), param[i].mUpdateValue2.c_str(),\ + param[i].mUpdateKey3.c_str(), param[i].mUpdateValue3.c_str()); + } + sprintf(whereCon, "dataNodeNo='%s'", param[i].mdataNodeNo.c_str()); + + int iRet = sql_ctl->UpdateTableData(T_SENSOR_INFO(TNAME), updateSql, whereCon); + memset(whereCon,0x00,sizeof(whereCon)); + memset(updateSql,0x00,sizeof(updateSql)); + if(iRet != 0) + jsonVal["success"] = false; + } + return showValue.write(jsonVal); +} + diff --git a/jsonparse/SH_JsonCmd.hpp b/jsonparse/SH_JsonCmd.hpp index 50b0013..bf0f541 100644 --- a/jsonparse/SH_JsonCmd.hpp +++ b/jsonparse/SH_JsonCmd.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -13,6 +14,7 @@ #include "../calculation/Calculation.hpp" #include "../uart/SH_Uart.hpp" #include "../datatransfer/SH_Datatrans.hpp" +#include "../wifi/wpa_client.h" class JsonData { @@ -26,8 +28,10 @@ public : std::string JsonCmd_26(Param_26 ¶m); std::string JsonCmd_27(Json::Value & recvBody); std::string JsonCmd_29(Param_29 ¶m); //系统配置信息 - std::string JsonCmd_50(Json::Value & recvBody); + std::string JsonCmd_50(Json::Value & recvBody); //download update file std::string JsonCmd_51(Json::Value & recvBody); + std::string JsonCmd_52();//upload static data + std::string JsonCmd_53(Json::Value & recvBody); void JsonCmd_38(Json::Value &recvBody); //获取原始数据 void JsonCmd_39(Json::Value &recvBody); //更新传感器程序 @@ -37,24 +41,34 @@ public : std::string JsonCmd_Cgi_07(); //获取系统内存温度硬盘等信息 std::string JsonCmd_07(); //获取系统内存温度硬盘等信息 std::string JsonCmd_Cgi_08(); //重启 - std::string JsonCmd_Cgi_09(); //实时数据获取 + std::string JsonCmd_Cgi_09(Param_09 ¶m); //实时数据获取 + std::string JsonCmd_Cgi_10(Param_10 ¶m); // + std::string JsonCmd_Cgi_11(Param_11 ¶m); // std::string JsonCmd_Cgi_20(Param_20 ¶m); //终端信息获取 std::string JsonCmd_Cgi_22(Param_22 ¶m); //时区配置 std::string JsonCmd_Cgi_23(Param_23 ¶m); //服务器配置 std::string JsonCmd_Cgi_25(Param_25 ¶m); //网口配置 - std::string JsonCmd_Cgi_26(); + std::string JsonCmd_Cgi_26(Param_26 ¶m); std::string JsonCmd_Cgi_27(Param_27 ¶m); std::string JsonCmd_Cgi_28(Param_28 ¶m); std::string JsonCmd_Cgi_29(Param_29 ¶m); //获取原始数据 std::string JsonCmd_Cgi_30(Param_30 ¶m); //获取频域数据 std::string JsonCmd_Cgi_31(Param_31 ¶m);//配置通信通道 std::string JsonCmd_Cgi_32(Param_32 ¶m); // + + std::string JsonCmd_Cgi_40(Param_40 ¶m); // + std::string JsonCmd_Cgi_41(std::vector ¶m); // + std::string JsonCmd_Cgi_42(Param_42 ¶m); //从web端更新程序 std::string JsonCmd_Cgi_43(); //检测网口状态 std::string JsonCmd_Cgi_45(Param_45 ¶m); //国家区域配置 std::string JsonCmd_Cgi_46(Param_46 ¶m); //升级固件 std::string JsonCmd_Cgi_47(Param_47 ¶m); //替换Logo + std::string JsonCmd_Cgi_50(); // + std::string JsonCmd_Cgi_51(Param_51 ¶m); // + std::string JsonCmd_Cgi_52(Param_52 ¶m); + std::string JsonCmd_Cgi_53(std::vector ¶m); std::string JsonCmd_Cgi_default(); private : diff --git a/localserver/SH_LocalServer.cpp b/localserver/SH_LocalServer.cpp index 23c608e..0c19294 100644 --- a/localserver/SH_LocalServer.cpp +++ b/localserver/SH_LocalServer.cpp @@ -21,26 +21,30 @@ void LocalServer::HandleFromServer(const char *pData_r, int pLen, const char *to } std::string data_r = (std::string)(pData_r); + LOG_INFO("MQTT recv base64 %s\n",data_r.c_str()); print_brown("pData base : %s \n", data_r.c_str()); char *base64_data = new char[data_r.length()]; memset(base64_data, 0, data_r.length()); Secure::instance()->Base64Decode(data_r.c_str(), (unsigned char*)base64_data); std::string pData = std::string(base64_data); delete[] base64_data; - + LOG_INFO("MQTT recv %s\n",pData.c_str()); print_brown("pData : %s \n", pData.c_str()); Json::Reader recvReader; Json::Value recvValue; Json::Value recvBody; if (recvReader.parse(pData, recvValue)) { - std::string cmdBody = recvValue["cmdBody"].asString(); - if (!recvReader.parse(cmdBody, recvBody)) { - print_error("recv body error"); - return; - } - // recvBody = recvValue["cmdBody"]; - std::string str = recvBody["timestamp"].asString(); - int cmdType = atoi(recvValue["cmd"].asString().c_str()); + int cmdType = atoi(recvValue["cmd"].asString().c_str()); + if(cmdType == 41){ + recvBody = recvValue["cmdBody"]; + }else{ + std::string cmdBody = recvValue["cmdBody"].asString(); + if (!recvReader.parse(cmdBody, recvBody)) { + print_error("recv body error"); + return; + } + } + switch (cmdType) { case 7:{ JsonData jd; @@ -53,8 +57,8 @@ void LocalServer::HandleFromServer(const char *pData_r, int pLen, const char *to Json::FastWriter fw; std::string strjson = fw.write(recvValue); data_publish(strjson.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); - system("echo 1 > /CIDW/start"); - boost::this_thread::sleep(boost::posix_time::seconds(1)); + //system("echo 1 > /CIDW/start"); + sleep(1); system("reboot"); } break; @@ -65,9 +69,9 @@ void LocalServer::HandleFromServer(const char *pData_r, int pLen, const char *to return; }*/ std::string timestamp = recvBody["timestamp"].asString(); - unsigned long itimestamp = boost::lexical_cast(timestamp); + unsigned long itimestamp = atol(timestamp.c_str()); SetTime(itimestamp); - boost::this_thread::sleep(boost::posix_time::milliseconds(200)); + usleep(200); system("hwclock -w"); if (!recvValue["ZoneId"].isNull() && recvValue["ZoneId"].asString().length() > 0) { std::string zoneid = recvValue["ZoneId"].asString(); @@ -134,8 +138,8 @@ void LocalServer::HandleFromServer(const char *pData_r, int pLen, const char *to if (0 == type.compare("SET")) { param.mMode = 0; param.mServerIp = recvBody["localServerIpAddress"].asString(); - param.mPort = boost::lexical_cast(recvBody["localServerPort"].asInt()); - param.mCommMode = boost::lexical_cast(recvBody["CommMode"].asInt()); + param.mPort = to_string(recvBody["localServerPort"].asInt()); + param.mCommMode = to_string(recvBody["CommMode"].asInt()); } else { param.mMode = 1; } @@ -194,11 +198,49 @@ void LocalServer::HandleFromServer(const char *pData_r, int pLen, const char *to std::string data = jd.JsonCmd_50(recvBody); data_publish(data.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); }break; + case 41:{ + + JsonData jd; + Param_41 param; + std::vector param41; + for(int i = 0; i < recvBody.size();i++){ + param.mdataNodeNo = recvBody[i]["dataNodeNo"].asString(); + param.mfeatureInterVal = recvBody[i]["featureInterVal"].asInt(); + param.mwaveInterVal = recvBody[i]["waveInterVal"].asInt(); + param.msamplingRate = recvBody[i]["samplingRate"].asInt(); + param.mrange = recvBody[i]["range"].asInt(); + param.mAccSampleTime = recvBody[i]["ACCSampleTime"].asInt(); + param.mstartBrands = recvBody[i]["startBrands"].asString(); + param.mstopBrands = recvBody[i]["stopBrands"].asString(); + param.menvelopeBandPass = recvBody[i]["envelopeBandPass"].asString(); + param.mviff = recvBody[i]["viff"].asInt(); + param.mfaultFrequency = recvBody[i]["faultFrequency"].asString(); + param41.push_back(param); + } + std::string data = jd.JsonCmd_Cgi_41(param41); + char whereCon[64] = { 0 }; + sprintf(whereCon, "dataNodeNo='%s'", param.mdataNodeNo.c_str()); + string strData = sql_ctl->GetNodeConfigureInfor(whereCon); + data_publish(strData.c_str(), GlobalConfig::Topic_G.mPubConfig.c_str()); + + } + break; case 51:{ JsonData jd; std::string data = jd.JsonCmd_51(recvBody); data_publish(data.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); }break; + case 52:{ +// JsonData jd; +// std::string data = jd.JsonCmd_52(recvBody); +// data_publish(data.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); + }break; + case 53:{ + JsonData jd; + std::string data = jd.JsonCmd_53(recvBody); + data_publish(data.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); + } + break; default: // data_publish_local(pData.c_str(), GlobalConfig::Topic_G.mPubLocalCmd.c_str()); break; @@ -274,10 +316,33 @@ try{ break; case 9:{ JsonData jd; - std::string data = jd.JsonCmd_Cgi_09(); + Param_09 param; + param.mPackageFlag = recvBody["package"].asInt(); + std::string data = jd.JsonCmd_Cgi_09(param); return data; } break; + case 10:{ + JsonData jd; + Param_10 param; + param.strDataNode = recvBody["DataNode"].asString(); + param.strStatic = recvBody["Static"].asString(); + param.straxis = recvBody["Raxis"].asString(); + param.mPackageFlag = recvBody["package"].asInt(); + param.timeStart = recvBody["timeStart"].asString(); + param.timeEnd = recvBody["timeEnd"].asString(); + std::string data = jd.JsonCmd_Cgi_10(param); + return data; + } + break; + case 11:{ + JsonData jd; + Param_11 param; + param.DataNodeNo = recvBody["DataNode"].asString(); + std::string data = jd.JsonCmd_Cgi_11(param); + return data; + } + break; case 20:{ Param_20 param; std::string type = recvBody["type"].asString(); @@ -319,7 +384,10 @@ try{ param.mMode = 0; param.mServerIp = recvBody["SystemSettings"]["ServerIpAddress"].asString(); param.mPort = boost::lexical_cast(recvBody["SystemSettings"]["ServerPort"].asInt()); - param.mCommMode = boost::lexical_cast(recvBody["SystemSettings"]["CommMode"].asInt()); + param.mCommMode = recvBody["SystemSettings"]["CommMode"].asString(); + param.mUserName = recvBody["SystemSettings"]["UserName"].asString(); + param.mPassword = recvBody["SystemSettings"]["Password"].asString(); + param.mAPN = recvBody["SystemSettings"]["APN"].asString(); } else { param.mMode = 1; } @@ -332,11 +400,12 @@ try{ case 25:{ Param_25 param; std::string type = recvBody["type"].asString(); - if (0 == type.compare("SET")) { + if (0 == type.compare("SET")) { + param.mNet = recvBody["net"].asString(); param.mDnsName = recvBody["dnsName"].asString(); param.mGateway = recvBody["gateway"].asString(); param.mHostName = recvBody["hostName"].asString(); - param.mIp = recvBody["dataNodeGatewayIpAddress"].asString(); + param.mIp = recvBody["dataWatchIpAddress"].asString(); param.mSubnetMask = recvBody["subnetMask"].asString(); param.mNetworkPortStatus = recvBody["networkPortStatus"].asString(); param.mMode = 0; @@ -351,8 +420,10 @@ try{ break; case 26:{ JsonData jd; - std::string data = jd.JsonCmd_Cgi_26(); - printf("data = %s\n",data.c_str()); + Param_26 param; + param.mPackageFlag = recvBody["package"].asInt(); + std::string data = jd.JsonCmd_Cgi_26(param); + // print_info("data = %s\n",data.c_str()); return data; } break; @@ -415,6 +486,119 @@ try{ return data; } break; + case 40:{ + JsonData jd; + Param_40 param; + param.mChannelId = recvBody["channelId"].asString(); + param.mPackageFlag = recvBody["package"].asInt(); + param.mDataNodeNo = recvBody["dataNodeNo"].asString(); + param.StartFrequency = recvBody["StartFrequency"].asInt(); + param.EndFrequency = recvBody["EndFrequency"].asInt(); + std::string data = jd.JsonCmd_Cgi_40(param); + return data; + } + break; + case 41:{ + JsonData jd; + Param_41 param; + std::vector param41; + for(int i = 0; i < recvBody.size();i++){ + param.mdataNodeNo = recvBody[i]["dataNodeNo"].asString(); + param.mfeatureInterVal = recvBody[i]["featureInterVal"].asInt(); + param.mwaveInterVal = recvBody[i]["waveInterVal"].asInt(); + param.msamplingRate = recvBody[i]["samplingRate"].asInt(); + param.mrange = recvBody[i]["range"].asInt(); + param.mAccSampleTime = recvBody[i]["ACCSampleTime"].asInt(); + param.mstartBrands = recvBody[i]["startBrands"].asString(); + param.mstopBrands = recvBody[i]["stopBrands"].asString(); + param.menvelopeBandPass = recvBody[i]["envelopeBandPass"].asString(); + param.mviff = recvBody[i]["viff"].asInt(); + param.mfaultFrequency = recvBody[i]["faultFrequency"].asString(); + param41.push_back(param); + } + std::string data = jd.JsonCmd_Cgi_41(param41); + char whereCon[64] = { 0 }; + sprintf(whereCon, "dataNodeNo='%s'", param.mdataNodeNo.c_str()); + string strData = sql_ctl->GetNodeConfigureInfor(whereCon); + data_publish(strData.c_str(), GlobalConfig::Topic_G.mPubConfig.c_str()); + return data; + } + break; + case 42:{ + JsonData jd; + Param_42 param; + param.fileName = recvBody["fileName"].asString(); + std::string data = jd.JsonCmd_Cgi_42(param); + return data; + } + break; + case 50:{ + JsonData jd; + std::string data = jd.JsonCmd_Cgi_50(); + return data; + } + + break; + case 51:{ + JsonData jd; + Param_51 param; + std::string type = recvBody["type"].asString(); + if(0 == type.compare("SET")){ + param.mMode = 0; + param.strGateWayMAC = recvBody["gateWayNo"].asString(); + param.strGateWayLocation = recvBody["gateWayLocation"].asString(); + + }else{ + param.mMode = 1; + } + std::string data = jd.JsonCmd_Cgi_51(param); + return data; + } + break; + case 52:{ + Param_52 param; + param.mCmdSerial = recvValue["cmdSerial"].asString(); + std::string type = recvBody["type"].asString(); + if (0 == type.compare("SCAN")) { + param.mMode = 0; + } + if (0 == type.compare("SET")) { + param.mMode = 1; + param.mSsid = recvBody["ssid"].asString(); + param.mPassWord = recvBody["password"].asString(); + } + if (0 == type.compare("GET")) { + param.mMode = 2; + } + if (0 == type.compare("CLEAN")) { + param.mMode = 3; + } + JsonData jd; + std::string data = jd.JsonCmd_Cgi_52(param); + return data; + } + break; + case 53:{ + JsonData jd; + Param_53 param; + std::vector param53; + for(int i = 0; i < recvBody.size();i++){ + param.mdataNodeNo = recvBody[i]["dataNodeNo"].asString(); + param.mUpdateKey = recvBody[i]["updateKey"].asString(); + param.mUpdateValue = recvBody[i]["updateValue"].asString(); + param.mUpdateKey2 = recvBody[i]["updateKey2"].asString(); + param.mUpdateValue2 = recvBody[i]["updateValue2"].asString(); + param.mUpdateKey3 = recvBody[i]["updateKey3"].asString(); + param.mUpdateValue3 = recvBody[i]["updateValue3"].asString(); + param53.push_back(param); + } + std::string data = jd.JsonCmd_Cgi_53(param53); + char whereCon[64] = { 0 }; + sprintf(whereCon, "dataNodeNo='%s'", param.mdataNodeNo.c_str()); + string strData = sql_ctl->GetNodeConfigureInfor(whereCon); + data_publish(strData.c_str(), GlobalConfig::Topic_G.mPubConfig.c_str()); + return data; + }break; default: JsonData jd; std::string data = jd.JsonCmd_Cgi_default(); @@ -428,6 +612,6 @@ try{ jsVal["message"] = "未知错误"; Json::FastWriter fw; return fw.write(jsVal); -} +} } diff --git a/main.cpp b/main.cpp index 3a78adb..869ead7 100644 --- a/main.cpp +++ b/main.cpp @@ -42,29 +42,69 @@ int main(int argc, char *argv[]) // 初始化平台配置文件 platform->PlatFormInit(); + //启动 mqtt客户端 + boost::thread startMqtt(StartMqttClient); + startMqtt.detach(); + + + sql_ctl->InintGateway(); + sql_ctl->CalculateDip(); + sql_ctl->CalculateBattery(); + pUart->InitZigbee(); // UDP,接收客户端发来的组播消息,用于外接 QT 专家系统,屏蔽之 - boost::thread searchT(attrs,SearchThread); + boost::thread searchT(SearchThread); searchT.detach(); // 串口处理线程,用于与 ZigBee 模块通信,通过ZigBee无线通信技术与无线传感器通信 boost::thread uartReadTh(UartStart); uartReadTh.detach(); + boost::thread uartTestReadTh(TestUart); + uartReadTh.detach(); + + boost::thread InitModuleReadTh(InitModule); + InitModuleReadTh.detach(); + //boost::thread uartWatchDogReadTh(WatchDog); + //uartWatchDogReadTh.detach(); + // 休眠2秒,等待串口线程初始化完毕 - boost::this_thread::sleep(boost::posix_time::seconds(2)); + sleep(2); // 串口数据处理,读取传感器原始波形数据 boost::thread uartWaveReadTh(UartStartWave); uartWaveReadTh.detach(); - //启动 mqtt客户端 - boost::thread startMqtt(StartMqttClient); - startMqtt.detach(); + //启动 mqtt 心跳 boost::thread startHeart(HeartRep); startHeart.detach(); + //启动 mqtt 心跳 + boost::thread startRunLED(RunLED); + startRunLED.detach(); + +#ifdef NR5G_MODULE + print_info("NR5G_MODULE \n"); + //5G + boost::thread startCSQ(GetCSQ); + startCSQ.detach(); +#ifndef NR5G_MEIGE + boost::thread startDial(Dial5G); + startDial.detach(); +#endif +#endif + +#ifdef Q4G_MODULE + boost::thread startCSQ(GetCSQ); + startCSQ.detach(); + print_info("4G_MODULE \n"); + +#endif +#ifdef WIFI_MODULE + print_info("WiFi_MODULE \n"); +#endif + // 通过UDP接收数据 boost::thread StartConnectSys(attrs, StartUdpSys); StartConnectSys.detach(); @@ -81,13 +121,30 @@ int main(int argc, char *argv[]) boost::thread startTcpCgi(attrs,StartCgiServer); startTcpCgi.detach(); - //pUart->UpdateZigbeeInfoCtrl(); + + sleep(5); pUart->ZigbeeInit(); + sleep(1); pUart->UpdateZigbeeInfoCtrl(); - boost::this_thread::sleep(boost::posix_time::seconds(5)); + + bool status = Ping( GlobalConfig::ServerIP.c_str(), 10000); + print_info("===========status ======== %d\n",status); + + /* char * szRes = sql_ctl->GetDataChar(T_SENSOR_INFO(TNAME), "dataNodeName", "dataNodeNo = '074cfd0000158d00'"); + printf("szRes = %s\n",szRes); + for(int i = 0; i < 64;i++){ + printf("temp = %02x ",szRes[i]); + }*/ + + int fd = OpenWatchDog(); while (GlobalConfig::QuitFlag_G) { - boost::this_thread::sleep(boost::posix_time::seconds(20)); + + gpio_set(GlobalConfig::GPIO_G.hardWatchDog,1); + usleep(20000); + gpio_set(GlobalConfig::GPIO_G.hardWatchDog,0); + WriteWatchDog(fd); + sleep(20); // data_publish(senddata.c_str(), GlobalConfig::Topic_G.mPubData.c_str()); } diff --git a/mqttclient/SH_MqttClient.cpp b/mqttclient/SH_MqttClient.cpp index 98e6606..3737870 100644 --- a/mqttclient/SH_MqttClient.cpp +++ b/mqttclient/SH_MqttClient.cpp @@ -48,21 +48,31 @@ int data_publish(const char *str, const char *topic) { int iRet = -1; if(mosq != NULL){ - print_blue("data_publish: %s %s\n", str, topic); + //print_blue("data_publish: %s %s\n", str, topic); std::string strTopic = std::string(topic); - if (strTopic.find("cmd") != std::string::npos) { + if (strTopic.find("cmd") != std::string::npos || \ + strTopic.find("configureInfo") != std::string::npos ) { std::string pData = (std::string)str; char *base64_aes = new char[pData.length() * 2]; memset(base64_aes, 0, pData.length() * 2); Secure::instance()->Base64Encode((unsigned char*)pData.c_str(), base64_aes, pData.length()); iRet = mosquitto_publish(mosq, &mid_sent, topic, strlen(base64_aes), base64_aes, ud.topic_qos, false); - print_blue("data_publish: %s \n",base64_aes); + //char *base64_data = new char[pData.length() * 2]; + //memset(base64_data, 0, pData.length() *2); + //Secure::instance()->Base64Decode(base64_aes, (unsigned char*)base64_data); + //std::string pData = std::string(base64_data); + if(base64_aes != NULL) + delete[] base64_aes; // free(out); } else { iRet = mosquitto_publish(mosq, &mid_sent, topic, strlen(str), str, ud.topic_qos, false); } } + if(iRet != 0) + { + reconnect(); + } return iRet; } @@ -93,6 +103,10 @@ int disconnect() return mosquitto_disconnect(mosq); } +int reconnect() +{ + return mosquitto_reconnect(mosq); +} int start_client(const char *boardname, const char *gwid, const char* gwip, const char *gwver, const char *gwcode, std::string &salt) { char *id = NULL; @@ -123,11 +137,11 @@ int start_client(const char *boardname, const char *gwid, const char* gwip, cons signal(SIGPIPE, SIG_IGN); int reconnect = 0; if (my_connect_callback == NULL || my_message_callback == NULL || my_subscribe_callback == NULL || my_log_callback == NULL) { - printf("please call the register_collback function first.\n"); + print_info("please call the register_collback function first.\n"); return -1; } - + int qos = readIntValue( "config", "qos",(char*)GlobalConfig::Config_G.c_str()); mosquitto_lib_init();//使用mosquitto库函数前需进行初始化 memset(&mqttsdata, 0, sizeof(mqttsdata_t)); memcpy(mqttsdata.gwid, gwid, strlen(gwid)); @@ -142,19 +156,28 @@ int start_client(const char *boardname, const char *gwid, const char* gwip, cons host = localip; mqttsdata.port = GlobalConfig::ServerPort; port = GlobalConfig::ServerPort; - +#ifdef WIFI_MODULE + mqttsdata.qos = 0; +#else + mqttsdata.qos = qos; +#endif + print_info("mqttsdata.qos = %d\n",mqttsdata.qos); // std::string username = "root"; // std::string password = "xom!*283#@XHG"; - std::string username = "chaos"; - std::string password = "HSD272*#xkd"; + std::string username = ReadStrByOpt(SERVERCONFIG, "Server", "UserName"); + std::string password = ReadStrByOpt(SERVERCONFIG, "Server", "Password"); + if(username == "" || password == ""){ + username = "chaos"; + password = "HSD272*#xkd"; + } char userName[100]; sprintf(userName, "%s", username.c_str()); char passWord[100]; sprintf(passWord, "%s", password.c_str()); - + print_info("userName = %s , passWord = %s\n",userName,passWord); ud.username = userName; ud.password = passWord; @@ -162,6 +185,7 @@ int start_client(const char *boardname, const char *gwid, const char* gwip, cons ud.dataUrl = mqttsdata.dataUrl; ud.fsUrl = mqttsdata.fsUrl; will_qos = mqttsdata.qos; + ud.topic_qos = will_qos; ud.topic_count++; ud.topics = (char**)realloc(ud.topics, ud.topic_count*sizeof(char *)); if (ud.topics == NULL) { @@ -172,15 +196,15 @@ int start_client(const char *boardname, const char *gwid, const char* gwip, cons sprintf(req_topic, "dev/cidwcc"); ud.topics[ud.topic_count - 1] = req_topic; ud.verbose = 1; - fprintf(stderr, "topic = %s!!!!!!!!!!!\n", ud.topics[ud.topic_count - 1]); + //fprintf(stderr, "topic = %s!!!!!!!!!!!\n", ud.topics[ud.topic_count - 1]); memset(res_topic, 0, 100); sprintf(res_topic, "gw/will"); - printf("res_topic:%s\n", res_topic); + print_info("res_topic:%s\n", res_topic); will_topic = res_topic; ud.resp_topic = res_topic; sprintf(will_payload, "{\"cmd\":\"15\",\"gwID\":\"%s\"}", mqttsdata.gwid); will_payloadlen = strlen(will_payload); - printf("will_payload:%s,will_payloadlen:%ld\n", will_payload, will_payloadlen); + print_info("will_payload:%s,will_payloadlen:%ld\n", will_payload, will_payloadlen); if (clean_session == false && (id_prefix || !id)){ if (!ud.quiet) fprintf(stderr, "Error: You must provide a client id if you are using the -c option.\n"); return 1; @@ -230,7 +254,7 @@ int start_client(const char *boardname, const char *gwid, const char* gwip, cons id[MOSQ_MQTT_ID_MAX_LENGTH] = '\0'; } } - printf("id:%s\n", id); + print_info("id:%s\n", id); mosq = mosquitto_new(id, clean_session, &ud); if (!mosq){ switch (errno){ @@ -316,15 +340,17 @@ int start_client(const char *boardname, const char *gwid, const char* gwip, cons else{ rc = mosquitto_connect_bind(mosq, host, port, keepalive, bind_address); } - printf("host = %s port = %d rc = %d\n",host,port,rc); + print_info("host = %s port = %d rc = %d\n",host,port,rc); if (rc){ if (!ud.quiet){ if (rc == MOSQ_ERR_ERRNO){ - strerror_r(errno, err, 1024); - fprintf(stderr, "Error_: %s\n", err); + //strerror_r(errno, err, 1024); + //fprintf(stderr, "Error_: %s\n", err); + //print_info("%s",stderr); } else{ fprintf(stderr, "Unable to connect (%d).\n", rc); + print_info("%s",stderr); } } goto mosq_free; @@ -332,7 +358,8 @@ int start_client(const char *boardname, const char *gwid, const char* gwip, cons rc = mosquitto_loop_forever(mosq, -1, 1); if (rc) { - fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc)); + //fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc)); + //print_info("%s",stderr); } mosq_free: mosquitto_destroy(mosq); diff --git a/mqttclient/SH_MqttClient.h b/mqttclient/SH_MqttClient.h index 89cb9aa..d080fc9 100644 --- a/mqttclient/SH_MqttClient.h +++ b/mqttclient/SH_MqttClient.h @@ -61,6 +61,7 @@ extern void register_collback(connect_callback connect_c, extern int data_publish(const char *str, const char* topic); extern int data_publish_wave(WAVE_CONTAIN *str, const char *topic); extern int disconnect(); +extern int reconnect(); extern int subscribe(const char* topic, int qos); extern int unsubscribe(const char* topic); extern int start_client(const char *boardname, const char *gwid, const char* gwip, const char *gwver, const char *gwcode, std::string &salt); diff --git a/platform/SH_PlatformInit.cpp b/platform/SH_PlatformInit.cpp index 41be7df..f8a207f 100644 --- a/platform/SH_PlatformInit.cpp +++ b/platform/SH_PlatformInit.cpp @@ -9,20 +9,28 @@ int GlobalConfig::RUN_MODE = 0; int GlobalConfig::QuitFlag_G = 1; int GlobalConfig::LinkStatus_G = 0; int GlobalConfig::LinkCount = 0; +int GlobalConfig::net0Status = 1; - -std::string GlobalConfig::Version = "2.0.11"; +std::string GlobalConfig::Version = "3.0"; std::string GlobalConfig::MacAddr_G = ""; +std::string GlobalConfig::MacAddr_G2 = ""; std::string GlobalConfig::IpAddr_G = ""; std::string GlobalConfig::ServerIP = ""; +std::string GlobalConfig::NetStatus = ""; +std::string GlobalConfig::NetType = ""; +std::string GlobalConfig::NR5GTemp = ""; +int GlobalConfig::serverStatus = 0; +int GlobalConfig::NetSignal = 0; int GlobalConfig::ServerPort = 0; TopicList GlobalConfig::Topic_G; ZigbeeInfo GlobalConfig::ZigbeeInfo_G; ZIGBEE GlobalConfig::Zigbee_G; +GPIOInfo GlobalConfig::GPIO_G; std::string GlobalConfig::DbName_G = "/opt/configenv/cidn.db"; //数据库名称 +std::string GlobalConfig::Config_G = "/opt/configenv/config.ini"; std::string GlobalConfig::UartName_G = "/dev/ttymxc4"; // 处理ZigBee网络接收过程的PanID切换 @@ -41,16 +49,57 @@ PlatformInit::~PlatformInit() void PlatformInit::PlatFormInit() { try{ - GlobalConfig::MacAddr_G = GetLocalMac(); + GlobalConfig::MacAddr_G = GetLocalMac("eth0"); + GlobalConfig::MacAddr_G2 = GetLocalMac("eth1"); transform(GlobalConfig::MacAddr_G.begin(), GlobalConfig::MacAddr_G.end(), GlobalConfig::MacAddr_G.begin(), ::toupper); + transform(GlobalConfig::MacAddr_G2.begin(), GlobalConfig::MacAddr_G2.end(), GlobalConfig::MacAddr_G2.begin(), ::toupper); GlobalConfig::IpAddr_G = IpAddrInit(); print_info("GlobalConfig::IpAddr_G : %s\n", GlobalConfig::IpAddr_G.c_str()); this->ConfigFileCheck(); + print_info("ConfigFileCheck\n"); this->TopicInit(); + print_info("TopicInit\n"); this->ServerIpInit(); + print_info("TopicInit\n"); this->Sqlite3Init(); - + this->GPIOInit(); + print_info("ServerIP : %s \n", GlobalConfig::ServerIP.c_str()); + std::string strMac = sql_ctl->GetData("t_gateway_info","gatewayMAC",NULL); + if(strMac == "60294D208517"){ + char szUpdateSql[100]={0x00}; + sprintf(szUpdateSql,"gatewayMAC = '%s'",GlobalConfig::MacAddr_G.c_str()); + sql_ctl->UpdateTableData("t_gateway_info",szUpdateSql,NULL); + } + else if(strMac != GlobalConfig::MacAddr_G ){ + LOG_ERROR("MAC error strMac1 = %s,MacAddr_G1 = %s\n",strMac.c_str(),GlobalConfig::MacAddr_G.c_str()); + strMac.insert(2,":"); + strMac.insert(5,":"); + strMac.insert(8,":"); + strMac.insert(11,":"); + strMac.insert(14,":"); + ModifyMac((char*)strMac.c_str()); + //system("reboot"); + } +#ifdef G2UL_GATEWAY + std::string strMac2 = sql_ctl->GetData("t_gateway_info","MAC2",NULL); + if(strMac2 == "60294D208518"){ + char szUpdateSql[100]={0x00}; + sprintf(szUpdateSql,"MAC2 = '%s'",GlobalConfig::MacAddr_G2.c_str()); + sql_ctl->UpdateTableData("t_gateway_info",szUpdateSql,NULL); + } + else if(strMac2 != GlobalConfig::MacAddr_G2 ){ + LOG_ERROR("MAC error strMac2 = %s,MacAddr_G2 = %s\n",strMac2.c_str(),GlobalConfig::MacAddr_G2.c_str()); + strMac2.insert(2,":"); + strMac2.insert(5,":"); + strMac2.insert(8,":"); + strMac2.insert(11,":"); + strMac2.insert(14,":"); + ModifyMac((char*)strMac2.c_str()); + //system("reboot"); + } +#endif + // sleep(10); } catch(...){ print_error("PlatFormInit exception happend.\n"); @@ -66,7 +115,7 @@ void PlatformInit::TopicInit() GlobalConfig::Topic_G.mPubHeart = "wireless/heart/" + GlobalConfig::MacAddr_G;// - GlobalConfig::Topic_G.mPubConfig = "wireless/configureInfor/" + GlobalConfig::MacAddr_G; + GlobalConfig::Topic_G.mPubConfig = "wireless/configureInfo/" + GlobalConfig::MacAddr_G; GlobalConfig::Topic_G.mPubWaveData = "wireless/realTimeData/" + GlobalConfig::MacAddr_G; @@ -78,6 +127,8 @@ void PlatformInit::TopicInit() GlobalConfig::Topic_G.mPubRep = "wireless/resp/" + GlobalConfig::MacAddr_G; + GlobalConfig::Topic_G.mPubTiming = "equipment/cmd/" + GlobalConfig::MacAddr_G; + GlobalConfig::Topic_G.mPubLocalWifi = "up/" + GlobalConfig::MacAddr_G + "/recive/wifi"; @@ -128,7 +179,7 @@ int PlatformInit::ServerIpInit() { if (access(SERVERCONFIG, 0) >= 0) { GlobalConfig::ServerIP = ReadStrByOpt(SERVERCONFIG, "Server", "localServerIpAddress"); - GlobalConfig::ServerPort = boost::lexical_cast(ReadStrByOpt(SERVERCONFIG, "Server", "localServerPort")); + GlobalConfig::ServerPort = atoi(ReadStrByOpt(SERVERCONFIG, "Server", "localServerPort").c_str()); } } @@ -136,10 +187,43 @@ int PlatformInit::ServerIpInit() void PlatformInit::Sqlite3Init() { sql_ctl->OpenDB(GlobalConfig::DbName_G.c_str()); + char szValue[10] = {0x00}; + int nType = readIntValue( "Update", "type",(char*)GlobalConfig::Config_G.c_str()); + if(nType== 1){ + sql_ctl->SqliteInitDel(GlobalConfig::DbName_G.c_str()); + writeIntValue("Update", "type",0,(char*)GlobalConfig::Config_G.c_str()); + } + print_info("szValue = %d\n",nType); sql_ctl->SqliteInit(GlobalConfig::DbName_G.c_str()); print_info("Sqlite3Init \n"); } +void PlatformInit::GPIOInit() +{ +#ifdef G2UL_GATEWAY + GlobalConfig::GPIO_G.zigAckrep = 507; + GlobalConfig::GPIO_G.zigAckreset = 499; + GlobalConfig::GPIO_G.zigReset = 496; + GlobalConfig::GPIO_G.commPower = 363; + GlobalConfig::GPIO_G.vol3_8 = 498; + GlobalConfig::GPIO_G.commRest = 466; + GlobalConfig::GPIO_G.wifiPower = 488; + GlobalConfig::GPIO_G.wifiReset = 474; + GlobalConfig::GPIO_G.hardWatchDog = 497; + GlobalConfig::GPIO_G.zigDef = 408; + GlobalConfig::GPIO_G.runLed = 409; + GlobalConfig::GPIO_G.errorLed = 410; + GlobalConfig::GPIO_G.netResetNet0 = 489; +#else if IMX6UL_GATEWAY + GlobalConfig::GPIO_G.zigAckrep = 119; + GlobalConfig::GPIO_G.zigAckreset = 120; + GlobalConfig::GPIO_G.zigReset = 116; + GlobalConfig::GPIO_G.wifiReset = 8; + GlobalConfig::GPIO_G.commRest = 8; + GlobalConfig::GPIO_G.power = 9; + GlobalConfig::GPIO_G.errorLed = 130; +#endif +} void PlatformInit::SystemInfoInit() { std::ifstream ifileOut(SYSTEMINFOFILE); @@ -182,14 +266,14 @@ void PlatformInit::UserInit() } } -void PlatformInit::EquipIpInit() +void PlatformInit::EquipIpInit(std::string eth) { //eth0 初始化 int flag = 0; - std::string networkPortStatus = ReadStrByOpt(NETWORKCONFIG, "Net", "networkPortStatus"); - std::string subnetMask = ReadStrByOpt(NETWORKCONFIG, "Net", "subnetMask"); - std::string gateway = ReadStrByOpt(NETWORKCONFIG, "Net", "gateway"); - std::string dataWatchIpAddress = ReadStrByOpt(NETWORKCONFIG, "Net", "ipAddress"); + std::string networkPortStatus = ReadStrByOpt(NETWORKCONFIG, eth, "networkPortStatus"); + std::string subnetMask = ReadStrByOpt(NETWORKCONFIG, eth, "subnetMask"); + std::string gateway = ReadStrByOpt(NETWORKCONFIG, eth, "gateway"); + std::string dataWatchIpAddress = ReadStrByOpt(NETWORKCONFIG, eth, "ipAddress"); std::string strStatus = GetFileContent(NETWORK, 18); print_red("strStatus:%s\n networkPortStatus:%s dataWatchIpAddress:%s subnetMask:%s gateway:%s\n",strStatus.c_str(),networkPortStatus.c_str(),dataWatchIpAddress.c_str(),subnetMask.c_str(),gateway.c_str()); @@ -197,18 +281,31 @@ void PlatformInit::EquipIpInit() { print_white("dhcp config\n"); std::string cmd = ""; +#ifdef IMX6UL_GATEWAY system("sed -i '17c auto eth0' /etc/network/interfaces"); system("sed -i '18c iface eth0 inet dhcp' /etc/network/interfaces"); system("sed -i '20c ' /etc/network/interfaces"); system("sed -i '21c ' /etc/network/interfaces"); system("sed -i '22c ' /etc/network/interfaces"); +#endif +#ifdef G2UL_GATEWAY + if(eth == "eth0"){ + system("sed -i '5c DHCP=ipv4' /etc/systemd/network/static/10-eth0-static.network"); + system("sed -i '6c ' /etc/systemd/network/static/10-eth0-static.network"); + system("sed -i '7c ' /etc/systemd/network/static/10-eth0-static.network"); + }else if(eth == "eth1"){ + system("sed -i '5c DHCP=ipv4' /etc/systemd/network/dynamic/20-eth1-dynamic.network"); + system("sed -i '6c ' /etc/systemd/network/dynamic/20-eth1-dynamic.network"); + system("sed -i '7c ' /etc/systemd/network/dynamic/20-eth1-dynamic.network"); + } +#endif flag = 0; } if(0 == networkPortStatus.compare("STATIC")) { std::string cmd = ""; print_red("static config\n"); - +#ifdef IMX6UL_GATEWAY system("sed -i '18c iface eth0 inet static' /etc/network/interfaces"); if(dataWatchIpAddress.length() > 0) { @@ -236,15 +333,34 @@ void PlatformInit::EquipIpInit() } system(cmd.c_str()); cmd.clear(); +#endif +#ifdef G2UL_GATEWAY + if(eth == "eth0"){ + cmd = "sed -i '5c Address=" + dataWatchIpAddress + "' /etc/systemd/network/static/10-eth0-static.network"; + system(cmd.c_str()); + cmd = "sed -i '6c Netmask=" + subnetMask + "' /etc/systemd/network/static/10-eth0-static.network"; + system(cmd.c_str()); + cmd = "sed -i '7c Gateway=" + gateway + "' /etc/systemd/network/static/10-eth0-static.network"; + system(cmd.c_str()); + }else if(eth == "eth1"){ + cmd = "sed -i '5c Address=" + dataWatchIpAddress + "' /etc/systemd/network/dynamic/20-eth1-dynamic.network"; + system(cmd.c_str()); + cmd = "sed -i '6c Netmask=" + subnetMask + "' /etc/systemd/network/dynamic/20-eth1-dynamic.network"; + system(cmd.c_str()); + cmd = "sed -i '7c Gateway=" + gateway + "' /etc/systemd/network/dynamic/20-eth1-dynamic.network"; + system(cmd.c_str()); + } +#endif flag = 1; } - - if(1 == flag){ //静态直接更新 - system("source /etc/config.sh"); - } - if(0 == flag) //动态重新启动获取 - { - system("reboot"); - } +#ifdef IMX6UL_GATEWAY + + + system("reboot"); + +#endif +#ifdef G2UL_GATEWAY + system("systemctl restart systemd-networkd.service"); +#endif } diff --git a/platform/SH_PlatformInit.hpp b/platform/SH_PlatformInit.hpp index 3d2c04d..0734532 100644 --- a/platform/SH_PlatformInit.hpp +++ b/platform/SH_PlatformInit.hpp @@ -52,7 +52,9 @@ public : /** *@eth0 初始化 */ - void EquipIpInit(); + void EquipIpInit(std::string eth); + + void GPIOInit(); private: /** diff --git a/searchdev/SH_SearchDev.cpp b/searchdev/SH_SearchDev.cpp index c6a92d9..ea4e66d 100644 --- a/searchdev/SH_SearchDev.cpp +++ b/searchdev/SH_SearchDev.cpp @@ -107,7 +107,7 @@ void SearchDev::HandleRecv_1(const boost::system::error_code &pEc,size_t pBytesR std::string status = jsData["status"].asString(); if(status.compare("REQ") == 0) { jsData["dataWatchNo"] = GlobalConfig::MacAddr_G.c_str(); - jsData["localServerIpAddress"] = GlobalConfig::ServerIP; + jsData["localServerIpAddress"] = GlobalConfig::IpAddr_G; jsData["status"] = "ACK"; jsData["DeviceType"] = "WirelessGateWay"; std::string strData = fw.write(jsData); @@ -122,6 +122,8 @@ void SearchDev::HandleRecv_1(const boost::system::error_code &pEc,size_t pBytesR default: break; } + }else{ + print_error("parse error\n"); } MultiCastRecv_1(); } else { diff --git a/serial/serial.c b/serial/serial.c new file mode 100644 index 0000000..3f9102c --- /dev/null +++ b/serial/serial.c @@ -0,0 +1,503 @@ +/* + * A library for Linux serial communication + * + * Author: JoStudio, 2016 + * + * Version: 0.5 + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "serial.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CMSPAR +#define CMSPAR 010000000000 +#endif + + + +/* + * convert baud_rate to speed_t + */ +static speed_t get_speed(unsigned int baud_rate) +{ + switch (baud_rate) { + case 0: + return B0; + case 50: + return B50; + case 75: + return B75; + case 110: + return B110; + case 150: + return B150; + case 200: + return B200; + case 300: + return B300; + case 600: + return B600; + case 1200: + return B1200; + case 1800: + return B1800; + case 2400: + return B2400; + case 4800: + return B4800; + case 9600: + return B9600; + case 19200: + return B19200; + case 38400: + return B38400; + case 57600: + return B57600; + case 115200: + return B115200; + case 230400: + return B230400; + case 460800: + return B460800; + case 500000: + return B500000; + case 576000: + return B576000; + case 921600: + return B921600; + case 1000000: + return B1000000; + case 1152000: + return B1152000; + case 1500000: + return B1500000; + case 2000000: + return B2000000; + case 2500000: + return B2500000; + case 3000000: + return B3000000; + case 3500000: + return B3500000; + case 4000000: + return B4000000; + default: + //unsupported baud rate + return 0; + } +} + + +/** + * set baud rate of serial port + * + * @param file_descriptor file descriptor of serial device + * @param baud_rate baud rate + * + * @return 1 if success + * return negative error code if fail + */ +int serial_set_baud_rate(int file_descriptor, int baud_rate) { +/* struct termios termio; + speed_t speed; + int fd = file_descriptor; + + if ( fd < 0 ) { + return SERIAL_INVALID_FILE; + } + + memset(&termio, 0, sizeof(termio)); + + //get old attribute + if (tcgetattr(fd, &termio)) { + return SERIAL_INVALID_RESOURCE; + } + + //calculate baud rate + speed = get_speed(baud_rate); + if (speed == 0) { + return SERIAL_ERROR_BAUDRATE; + } + cfsetispeed(&termio, speed); + cfsetospeed(&termio, speed); + + // set baud rate + if (tcsetattr(fd, TCSAFLUSH, &termio) < 0) { + return SERIAL_ERROR_BAUDRATE; + }*/ + int iFd = file_descriptor; + int len,ret; + struct termios opt; + tcgetattr(iFd, &opt); + cfsetispeed(&opt, B115200); + cfsetospeed(&opt, B115200); + if (tcgetattr(iFd, &opt)<0) { + return -1; + } + opt.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + opt.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + opt.c_oflag &= ~(OPOST); + opt.c_cflag &= ~(CSIZE | PARENB | CBAUD); + opt.c_cflag |= (CS8 | B115200); + opt.c_cc[VMIN] = 255; + opt.c_cc[VTIME] = 5; + if (tcsetattr(iFd, TCSANOW, &opt)<0) { + return -1; + } + tcflush(iFd,TCIOFLUSH); + + return 1; +} + + +/** + * set serial attributes + * + * @param file_descriptor file descriptor of serial device + * @param flow_ctrl + * @param data_bits how many bits per data, could be 7, 8, 5 + * @param parity which parity method, could be PARITY_NONE, PARITY_ODD, PARITY_EVEN + * @param stop_bits how many stop bits + * + * @return 1 if success. + * return negative error code if fail. + */ +int serial_set_attr(int file_descriptor, int data_bits, char parity, int stop_bits, int flow_ctrl) +{ + struct termios termio; + int fd = file_descriptor; + + if ( fd < 0 ) { + return SERIAL_INVALID_FILE; + } + + memset(&termio, 0, sizeof(termio)); + + if (tcgetattr(fd, &termio)) { + return SERIAL_INVALID_RESOURCE; + } + + //set flow control + switch(flow_ctrl) { + case FLOW_CONTROL_NONE : + termio.c_cflag &= ~CRTSCTS; + break; + case FLOW_CONTROL_HARDWARE : + termio.c_cflag |= CRTSCTS; + break; + case FLOW_CONTROL_SOFTWARE : + termio.c_cflag |= IXON | IXOFF | IXANY; + break; + } + + //set data bit + termio.c_cflag &= ~CSIZE; + switch (data_bits) { + case 8: + termio.c_cflag |= CS8; + break; + case 7: + termio.c_cflag |= CS7; + break; + case 6: + termio.c_cflag |= CS6; + break; + case 5: + termio.c_cflag |= CS5; + break; + default: + termio.c_cflag |= CS8; + break; + } + + //set stop bits + switch (stop_bits) { + case 1: + termio.c_cflag &= ~CSTOPB; + break; + case 2: + termio.c_cflag |= CSTOPB; + break; + default: + break; + } + + //set parity bit + switch (parity) { + case PARITY_NONE: + termio.c_cflag &= ~(PARENB | PARODD); + break; + case PARITY_EVEN: + termio.c_cflag |= PARENB; + termio.c_cflag &= ~PARODD; + break; + case PARITY_ODD: + termio.c_cflag |= PARENB | PARODD; + break; + case PARITY_MARK: + termio.c_cflag |= PARENB | CMSPAR | PARODD; + break; + case PARITY_SPACE: + termio.c_cflag |= PARENB | CMSPAR; + termio.c_cflag &= ~PARODD; + break; + } + + if (tcsetattr(fd, TCSAFLUSH, &termio) < 0) { + return SERIAL_ERROR_SETTING; + } + + return 1; +} + + +/** + * open serial port + * + * @param device_filename device file name, such as "/dev/ttyS0" + * @param baund_rate could be 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300 + * + * @return file descriptor which could be used in read() or write() + * return -1 if failed, and errno is set + */ +int serial_open_file(char *device_filename, int baud_rate) { + int fd; + struct termios termio; + + if ((fd = open(device_filename, O_RDWR | O_NOCTTY )) == -1) { + return -1; + } + + memset(&termio, 0, sizeof(termio)); + + // setup the tty and the selected baud rate + // get current modes + if (tcgetattr(fd, &termio)) { + close(fd); + return -1; + } + + // setup initial mode: 8 bit data, No parity, 1 stop bit, no echo, no flow control + cfmakeraw(&termio); + if (tcsetattr(fd, TCSAFLUSH, &termio) < 0) { + close(fd); + return -1; + } + + if (serial_set_baud_rate(fd, baud_rate) != 1) { + close(fd); + return -1; + } + + return fd; +} + +/** + * open serial port + * + * @param file_descriptor file descriptor of serial device + * @param timeout timeout in second + * + * @return 1 if success + * return negative error code if fail + */ +int serial_set_timeout(int file_descriptor, int timeout) +{ + int fd = file_descriptor; + struct termios termio; + + if (fd < 0) { + return SERIAL_INVALID_FILE; + } + + + // get current attributes + if (tcgetattr(fd, &termio)) { + return SERIAL_INVALID_RESOURCE; + } + + //set read timeout + if (timeout > 0) { + timeout = timeout / 100; + if (timeout == 0) + timeout = 1; + } + termio.c_lflag &= ~ICANON; /* Set non-canonical mode */ + termio.c_cc[VTIME] = timeout; /* Set timeout in tenth seconds */ + if (tcsetattr(fd, TCSANOW, &termio) < 0) { + return SERIAL_ERROR_SETTING; + } + + return 1; +} + + +/** + * open serial port + * + * @param port number of port, could be 0, 1 ... , the device file is /dev/ttyS0, /dev/ttyS1 respectively + * @param baund_rate could be 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300 + * + * @return file descriptor which could be used in read() or write() + * return -1 if failed, and errno is set + */ +int serial_open(char* port, int baud_rate) { + char buf[128]; + + snprintf(buf, sizeof(buf), "/dev/ttyS%d", port); + return serial_open_file(port, baud_rate); +} + + +/** + * close serial port + * + * @param file_descriptor file descriptor of serial port device file + * + * @return 0 if success. + * return -1 if failed, and errno is set. + */ +int serial_close(int file_descriptor) { + return close(file_descriptor); +} + + +/** + * The function waits until all queued output to the terminal filedes has been transmitted. + * + * tcdrain() is called. + + * @param file_descriptor file descriptor of serial port device file + * + * @return 0 if success. + * return -1 if fail, and errno is set. + */ +int serial_flush(int file_descriptor) +{ + return tcdrain(file_descriptor); +} + +/** + * whether data is available + * + * @param file_descriptor file descriptor of serial port device file + * @param timeout_millisec timeout in millisecond + * + * @return 1 if data is available + * return 0 if data is not available + */ +int serial_data_available(int file_descriptor, unsigned int timeout_millisec) +{ + int fd = file_descriptor; + struct timeval timeout; + fd_set readfds; + + if (fd < 0) { + return SERIAL_INVALID_FILE; + } + + if (timeout_millisec == 0) { + // no waiting + timeout.tv_sec = 0; + timeout.tv_usec = 0; + } else { + timeout.tv_sec = timeout_millisec / 1000; + timeout.tv_usec = (timeout_millisec % 1000) * 1000; + } + + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + + if (select(fd + 1, &readfds, NULL, NULL, &timeout) > 0) { + return 1; // data is ready + } else { + return 0; // no data + } +} + + +/** + * send data + * + * @param file_descriptor file descriptor of serial port device file + * @param buffer buffer of data to send + * @param data_len data length + * + * @return positive integer of bytes sent if success. + * return -1 if failed. + */ +int serial_send(int file_descriptor, char *buffer, size_t data_len) +{ + ssize_t len = 0; + len = write(file_descriptor, buffer, data_len); + if ( len == data_len ) { + return len; + } else { + tcflush(file_descriptor, TCOFLUSH); + return -1; + } + +} + +/** + * receive data + * + * @param file_descriptor file descriptor of serial port device file + * @param buffer buffer to receive data + * @param data_len max data length + * + * @return positive integer of bytes received if success. + * return -1 if failed. + */ +int serial_receive(int file_descriptor, char *buffer,size_t data_len) +{ + int len,fs_sel; + fd_set fs_read; + struct timeval time; + int fd = file_descriptor; + + FD_ZERO(&fs_read); + FD_SET(fd, &fs_read); + + time.tv_sec = 10; + time.tv_usec = 0; + + //use select() to achieve multiple channel communication + fs_sel = select(fd + 1, &fs_read, NULL, NULL, &time); + if ( fs_sel ) { + len = read(fd, buffer, data_len); + return len; + } else { + return -1; + } +} + + diff --git a/serial/serial.h b/serial/serial.h new file mode 100644 index 0000000..5e1eb3b --- /dev/null +++ b/serial/serial.h @@ -0,0 +1,193 @@ +/* + * A library for Linux serial communication + * + * Author: JoStudio, 2016 + * + * Version: 0.5 + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __SERIAL_H__ +#define __SERIAL_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* serial error code */ +#define SERIAL_ERROR_OPEN -1 +#define SERIAL_ERROR_READ -2 +#define SERIAL_ERROR_WRITE -3 +#define SERIAL_ERROR_BAUDRATE -4 +#define SERIAL_ERROR_SETTING -5 +#define SERIAL_INVALID_RESOURCE -6 +#define SERIAL_INVALID_FILE -7 + + +/* flow control */ +#define FLOW_CONTROL_NONE 0 +#define FLOW_CONTROL_HARDWARE 1 +#define FLOW_CONTROL_SOFTWARE 2 + +/* parity */ +#define PARITY_NONE 'N' +#define PARITY_EVEN 'E' +#define PARITY_ODD 'O' +#define PARITY_SPACE 'S' +#define PARITY_MARK 'M' + + +/** + * open serial port + * + * @param port number of port, could be 0, 1 ... , the device file is /etc/ttyS0, /etc/ttyS1 respectively + * @param baund_rate could be 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300 + * + * @return file descriptor which could be used in read() or write() + * return -1 if failed, and errno is set + */ +int serial_open(char* port, int baud_rate); + + +/** + * close serial port + * + * @param file_descriptor file descriptor of serial port device file + * + * @return 0 if success. + * return -1 if failed, and errno is set. + */ +int serial_close(int file_descriptor); + +/** + * open serial port + * + * @param device_filename device file name, such as "/etc/ttyS0" + * @param baund_rate could be 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300 + * + * @return file descriptor which could be used in read() or write() + * return -1 if failed, and errno is set + */ +int serial_open_file(char *device_filename, int baud_rate); + + +/** + * set serial attributes + * + * @param file_descriptor file descriptor of serial device + * @param flow_ctrl + * @param data_bits how many bits per data, could be 7, 8, 5 + * @param parity which parity method, could be PARITY_NONE, PARITY_ODD, PARITY_EVEN + * @param stop_bits how many stop bits + * + * @return 1 if success. + * return negative error code if fail. + */ +int serial_set_attr(int file_descriptor, int data_bits, char parity, int stop_bits, int flow_ctrl); + + +/** + * open serial port + * + * @param file_descriptor file descriptor of serial device + * @param timeout timeout in second + * + * @return 1 if success + * return negative error code if fail + */ +int serial_set_timeout(int file_descriptor, int timeout); + + +/** + * set baud rate of serial port + * + * @param file_descriptor file descriptor of serial device + * @param baud_rate baud rate + * + * @return 1 if success + * return negative error code if fail + */ +int serial_set_baud_rate(int file_descriptor, int baud_rate) ; + + + + +/** + * The function waits until all queued output to the terminal filedes has been transmitted. + * + * tcdrain() is called. + + * @param file_descriptor file descriptor of serial port device file + * + * @return 0 if success. + * return -1 if fail, and errno is set. + */ +int serial_flush(int file_descriptor); + +/** + * whether data is available + * + * @param file_descriptor file descriptor of serial port device file + * @param timeout_millisec timeout in millisecond + * + * @return 1 if data is available + * return 0 if data is not available + */ +int serial_data_available(int file_descriptor, unsigned int timeout_millisec); + + +/** + * send data + * + * @param file_descriptor file descriptor of serial port device file + * @param buffer buffer of data to send + * @param data_len data length + * + * @return positive integer of bytes sent if success. + * return -1 if failed. + */ +int serial_send(int file_descriptor, char *buffer, size_t data_len); + + + +/** + * receive data + * + * @param file_descriptor file descriptor of serial port device file + * @param buffer buffer to receive data + * @param data_len max data length + * + * @return positive integer of bytes received if success. + * return -1 if failed. + */ +int serial_receive(int file_descriptor, char *buffer,size_t data_len); + + + +#ifdef __cplusplus +} +#endif + + +#endif /* __SERIAL_H__ */ diff --git a/tcpcgi/TcpCgi.cpp b/tcpcgi/TcpCgi.cpp index 510f1f3..a8aefe2 100644 --- a/tcpcgi/TcpCgi.cpp +++ b/tcpcgi/TcpCgi.cpp @@ -53,7 +53,7 @@ void TcpCgi::startCgiServer() std::string recvData = std::string(buff); std::string reqData = cidwServer->HandleCgi_cmd(recvData); - print_info("send cgi : %s\n", reqData.c_str()); + //print_info("send cgi : %s\n length = %d\n", reqData.c_str(),reqData.length()); if( send(connfd, reqData.c_str(), reqData.length(), 0) < 0){ printf("send msg error: %s(errno: %d)\n", strerror(errno), errno); } diff --git a/threadfunc/SH_ThreadFunc.cpp b/threadfunc/SH_ThreadFunc.cpp index 9aac80b..60787e1 100644 --- a/threadfunc/SH_ThreadFunc.cpp +++ b/threadfunc/SH_ThreadFunc.cpp @@ -9,6 +9,10 @@ #include "SH_ThreadFunc.hpp" #include "../API_log/SH_log.h" #include "../uart/SH_Uart.hpp" +#include "../common/SH_CommonFunc.hpp" +#include "../dial5G/Dial.h" +#include "../wifi/wpa_client.h" +#include namespace{ Uart *pUart = Uart::instance(); @@ -20,6 +24,8 @@ static std::string uptime; static long long connect_lost_time = 0; //ms static long long connect_time = 0; //ms +Dial dial; + void CheckThread() { print_info("ENTER CHECK THREAD \n"); @@ -31,27 +37,123 @@ void CheckThread() int reset_flag = 0; int online_check = 0; int HardStatus = 0; + int logClean = 0; + int Battery = 0; + int UpdateZigbee = 0; + int commSignal = 0; + int loose_check = 0; + int mqttresend = 0; + int rebootsystem = 0; + int ModifyAddr = 0; + int wifi_reconnect_count = 0; + int checkNet0 = 0; + int connectCount = 0; while (GlobalConfig::QuitFlag_G) { if (10 == heart_count) { // StatusPub(); if (GlobalConfig::LinkCount > 30) { - exit(0); + //exit(0); } std::string ipTemp = IpAddrInit(); + GlobalConfig::IpAddr_G = ipTemp; if ( 0 != ipTemp.compare(GlobalConfig::IpAddr_G)) { - exit(0); + //exit(0); } heart_count = 0; } - - if (600 == time_check) { +#ifdef G2UL_GATEWAY + if(checkNet0 == 5){ + checkNet0 = 0; + int iStatus = get_netlink_status("eth0"); + if(iStatus == 1 && GlobalConfig::net0Status == 0){ + system("ifconfig eth0:1 192.168.188.188 netmask 255.255.255.0"); + } + GlobalConfig::net0Status = iStatus; + } +#endif + if (300 == time_check) { char buf[256] = {0}; sprintf(buf, "{\"dataNodeGatewayNo\":\"%s\",\"cmd\":\"12\",\"status\":\"REQ\"}", GlobalConfig::MacAddr_G.c_str()); std::string str = std::string(buf); - data_publish(str.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); time_check = 0; + int iRet = data_publish(str.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); + if(iRet != 0 ) + { + LOG_ERROR("MQTT connect failed\n"); + //bool status = Ping( GlobalConfig::ServerIP.c_str(), 10000); +#ifdef NR5G_MODULE +#ifdef IMX6UL_GATEWAY + dial.closePort(); + gpio_set(GlobalConfig::GPIO_G.commRest,0); + LOG_DEBUG("GPIO 8 start\n"); + sleep(2); + gpio_set(GlobalConfig::GPIO_G.commRest,1); + LOG_DEBUG("GPIO 8 End\n"); + sleep(20); + dial.openPort("/dev/ttyUSB2"); + dial.setState(); +#endif +#ifdef G2UL_GATEWAY + dial.closePort(); + gpio_set(GlobalConfig::GPIO_G.commPower,0); + LOG_DEBUG("commPower start\n"); + sleep(2); + gpio_set(GlobalConfig::GPIO_G.commPower,1); + LOG_DEBUG("commPower End\n"); + sleep(20); + connectCount ++; + if(connectCount > 10){ + LOG_ERROR("5G reset error ,reboot!\n"); + system("reboot"); + } +#ifndef NR5G_MEIGE + dial.openPort("/dev/ttyUSB2"); + dial.setState(); +#else + char szquectel[100]={0x00}; + std::string strAPN = ReadStrByOpt(SERVERCONFIG, "Server", "APN"); + sprintf(szquectel,"/opt/quectel-CM/Meig-CM -s %s &",strAPN.c_str()); + system(szquectel); +#endif +#endif +#endif +#ifdef WIFI_MODULE + LOG_ERROR("WiFi reset!\n"); +#ifdef IMX6UL_GATEWAY + gpio_set(GlobalConfig::GPIO_G.wifiReset,0); + sleep(5); + gpio_set(GlobalConfig::GPIO_G.wifiReset,1); + sleep(5); + wifi::WPAClient wpa; + wpa.ReconnectWiFi(); + system("/etc/init.d/wpa_restart"); + system("udhcpc -i wlan2 &"); +#endif +#ifdef G2UL_GATEWAY + system("/etc/init.d/wpa_restart"); + sleep(5); + string strip = GetGwIp_("wlan0"); + print_info("strip = %s\n",strip.c_str()); + if (strip.compare("0.0.0.0") != 0) { + + }else{ + gpio_set(GlobalConfig::GPIO_G.wifiReset,1); + sleep(5); + gpio_set(GlobalConfig::GPIO_G.wifiReset,0); + sleep(30); + wifi::WPAClient wpa; + wpa.ReconnectWiFi(); + system("/etc/init.d/wpa_restart"); + sleep(5); + system("udhcpc -b -i wlan0 &"); + } +#endif +#endif + }else{ + connectCount = 0; + } } if(HardStatus == 3600){//one hour 3600 JsonData jd; @@ -59,26 +161,227 @@ void CheckThread() data_publish(data.c_str(), GlobalConfig::Topic_G.mPubStatus.c_str()); HardStatus = 0; } + if(mqttresend == 1800){ + mqttresend = 0; +#ifdef WIFI_MODULE + bool status = Ping( GlobalConfig::ServerIP.c_str(), 10000); + if(status != 0){ + LOG_INFO("===========net status ========failed \n"); + LOG_ERROR("openSwitch\n"); + sleep(20); + gpio_set(GlobalConfig::GPIO_G.power,1); + } +#endif + LOG_INFO("mqttresend check\n"); + Json::Value jsHeart; + Json::FastWriter fw; + jsHeart["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; + jsHeart["status"] = "online_V" + GlobalConfig::Version; + jsHeart["IP"] = GlobalConfig::IpAddr_G; + std::string strJson = fw.write(jsHeart); + int iRet = data_publish(strJson.c_str(), GlobalConfig::Topic_G.mPubHeart.c_str()); + if(iRet == 0){ + sql_ctl->QueryofflineData(); + } - if (onlineCheck == online_check) { - JsonData jd; - jd.DataNodeStatusCheck(); - LOG_INFO("online_check = %d",online_check); - Param_29 param; - std::string cmd29 = jd.JsonCmd_29(param); - data_publish(cmd29.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); - online_check = 0; } + if (600 == online_check) { + online_check = 0; + int Count = sql_ctl->GetTableRows(T_SENSOR_INFO(TNAME), NULL); + if(Count > 0){ + JsonData jd; + jd.DataNodeStatusCheck(); + Param_29 param; + std::string cmd29 = jd.JsonCmd_29(param); + int iRet = data_publish(cmd29.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); + char localtimestamp[32] = { 0 }; + GetTimeNet(localtimestamp, 1); + std::string nowTimetamp = std::string(localtimestamp); + char selectCon[128] = { 0 }; + sprintf(selectCon, " sendMsg <> '' ORDER BY timeStamp DESC LIMIT 0,1"); + sleep(1); + std::string strTime = sql_ctl->GetData(T_DATASTATIC_INFO(TNAME), "timeStamp", selectCon); + long lTime = atol(nowTimetamp.c_str())-atol(strTime.c_str()); + LOG_INFO("online check = %d\n",lTime); + if(lTime > 1800){ + LOG_ERROR("nowTimetamp = %s,lastTime = %s,lTime = %d\n",nowTimetamp.c_str(),strTime.c_str(),lTime); + } + } + }if(21000 == Battery){ + Battery = 0; + sql_ctl->CalculateBattery(); + } +// if(10800 == UpdateZigbee){ +// UpdateZigbee = 0; +// pUart->UpdateZigbeeInfoCtrl(); +// } + if(21000 == loose_check){ + loose_check = 0; + sql_ctl->CalculateDip(); + } + if(ModifyAddr == 21000 && pUart->bModifyAddr){ +//#ifdef IMX6UL_GATEWAY + LOG_ERROR("ModifyAddr failed \n"); + exit(0); +//#endif + } + if(ModifyAddr == 21000){ + ModifyAddr = 0; + } + + if(18000 == commSignal){ //5h + Json::Value jsBody,jsonVal; + Json::FastWriter showValue; + if(GlobalConfig::NetStatus == "\"NOCONN\"" || GlobalConfig::NetStatus == "\"CONNECT\""){ + if(GlobalConfig::NetSignal == 0){ + jsBody["communicationSignal"] = "未知"; + } + else if(GlobalConfig::NetSignal > -80){ + jsBody["commSignal"] = "优"; + }else if(GlobalConfig::NetSignal > -90 && GlobalConfig::NetSignal < -80){ + jsBody["commSignal"] = "良"; + }else if(GlobalConfig::NetSignal > -105 && GlobalConfig::NetSignal < -90){ + jsBody["commSignal"] = "一般"; + }else if(GlobalConfig::NetSignal < -105){ + jsBody["commSignal"] = "弱"; + }else if(GlobalConfig::NetSignal < -115){ + jsBody["commSignal"] = "不稳定"; + } + + }else if(GlobalConfig::NetStatus == "\"SEARCH\""){ + jsBody["commSignal"] = "搜索网络"; + }else if(GlobalConfig::NetStatus == "\"LIMSRV\""){ + jsBody["commSignal"] = "未插卡"; + }else{ + jsBody["commSignal"] = "未知"; + } + + jsonVal["cmd"] = "53"; + std::string dataBody = showValue.write(jsBody); + jsonVal["cmdBody"] = dataBody; + data_publish(showValue.write(jsonVal).c_str(), GlobalConfig::Topic_G.mPubConfig.c_str()); + } + if(21000 == logClean){ + logClean = 0; + DIR *dp; //创建一个指向root路径下每个文件的指针 + struct dirent *dirp; + string root="/opt/log/"; + if((dp = opendir(root.c_str()))==NULL) + cout << "can't open"<< root << endl; + while((dirp = readdir(dp)) != NULL){ + + if((!strcmp(dirp->d_name,".")||(!strcmp(dirp->d_name,"..")))) + continue; + struct timeval curTime; + gettimeofday(&curTime, NULL); + char buffer[80] = {0}; + char fileMonth[11] = {0}; + char todayMonth[11]={0}; + char fileDay[11] = {0}; + char todayDay[11]={0}; + struct tm nowTime; + localtime_r(&curTime.tv_sec, &nowTime);//把得到的值存入临时分配的内存中,线程安全 + strftime(buffer, sizeof(buffer), "%Y-%m-%d", &nowTime); + memcpy(fileDay,dirp->d_name+8,2); + memcpy(todayDay,buffer+8,2); + memcpy(fileMonth,dirp->d_name+5,2); + memcpy(todayMonth,buffer+5,2); + string filename = root+ string(dirp->d_name); + if(atoi(fileMonth) == atoi(todayMonth) ? abs(atoi(todayDay) - atoi(fileDay)) > 15: abs(abs(30-(atoi(fileDay)) + atoi(todayDay))) > 15){ + LOG_INFO("filename = %s\n",filename.c_str()); + remove(filename.c_str()); + } + + } + + /*staticData = 0; + Json::Value jsHeart; + Json::FastWriter fw; + jsHeart["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; + jsHeart["status"] = "online"; + std::string strJson = fw.write(jsHeart); + int iRet = data_publish(strJson.c_str(), GlobalConfig::Topic_G.mPubHeart.c_str()); + if(iRet == 0){ + JsonData jd; + std::string data = jd.JsonCmd_52(); + } + double freeDisk = GetHardDiskFree(); + if(freeDisk < 90){ + char whereCon[512] = {0x00}; + time_t timestamp; + long timeStamp = time(×tamp) ;//秒级时间戳 + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon,"sendMsg = '0' and timeStamp < '%s'",timeStamp-1); //1 week + sql_ctl->DeleteTableData(T_DATA_INFO(TNAME),whereCon,0); + sql_ctl->DeleteTableData(T_DATASTATIC_INFO(TNAME),whereCon,0); + }*/ + + } +#ifdef WIFI_MODULE + if (wifi_reconnect_count == 600) { // 每 10分钟,重连WiFi网络 + wifi_reconnect_count = 0; + wifi::WPAClient wpa; + std::string netssid = wpa.GetNetSsid(); + std::string currentssid = ""; + if (0 == netssid.compare("")) { + netssid = wpa.GetNetSsid(); + } + + if (netssid.length() > 0) { + currentssid = wpa.GetCurrentSSID(); + if (currentssid.length() > 0) { + char buf[64] = {0}; + std::string rssiSend = ""; +#ifdef G2UL_GATEWAY + rssiSend = "/usr/sbin/wpa_cli signal_poll|grep RSSI | cut -f 2 -d '='"; +#endif + +#ifdef IMX6UL_GATEWAY + rssiSend = "/opt/Cidn/wpa_cli signal_poll|grep RSSI | cut -f 2 -d '='"; +#endif + system_custom(rssiSend.c_str(), buf); + std::string Rssi = std::string(buf); + + memset(buf, 0, 64); + sprintf(buf, "wifi:true Rssi:%s", Rssi.c_str()); + print_info("%s\n", buf); + LOG_INFO("%s\n",buf); + + } else { + std::string runinfo = "wifi:false\n"; + print_info("%s\n", runinfo.c_str()); + } + } + if (wpa.ReconnectWiFi()) { + print_info("wifi reconnect ok\n"); + } + } +#endif + if ( reset_flag > 7200) { reset_flag = 0; //exit(0); } + Battery ++; reset_flag++; time_check++; heart_count++; online_check++; HardStatus ++; + //UpdateZigbee ++; + logClean ++ ; + loose_check ++; + ModifyAddr ++; + mqttresend ++; +#ifdef G2UL_GATEWAY + checkNet0 ++; +#endif +#ifdef WIFI_MODULE + wifi_reconnect_count ++; +#endif + + //rebootsystem ++; if(GlobalConfig::EnterZigBeeWaveTransmittingFlag_G == ENTER_TRANSMITTING_STATUS) { GlobalConfig::EnterZigBeeWaveTransmittingCnt_G ++; if(GlobalConfig::EnterZigBeeWaveTransmittingCnt_G >= 180) { @@ -87,13 +390,17 @@ void CheckThread() LOG_ERROR("[---- ZigBee error--!] ZigBee PanID is 9999 over time for 3 minutes !\n"); // 重新写入 0x8888 unsigned short shortAddr = 0x8888; - pUart->WriteShortAddr2Zigbee(shortAddr); + pUart->modify_LocalAddr(0x8888); + GlobalConfig::Zigbee_G.MyAddr = 0x8888; +// pUart->WriteShortAddr2Zigbee(shortAddr); // 延时1秒 - boost::this_thread::sleep(boost::posix_time::seconds(1)); + sleep(1); // 重新读回 GlobalConfig::ZigbeeInfo_G.PanID pUart->UpdateZigbeeInfoCtrl(); + pUart->bUpdateconfig = false; + pUart->bUpdate = false; // 延时1秒 - boost::this_thread::sleep(boost::posix_time::seconds(1)); + sleep(1); std::string str("8888"); if( GlobalConfig::ZigbeeInfo_G.MyAddr.compare(str) == 0 ){ LOG_INFO("[---- ZigBee INFO ----!] ZigBee PanID come back to be 8888 !\n"); @@ -103,8 +410,7 @@ void CheckThread() } } } - - boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); + sleep(1);; } } @@ -114,40 +420,277 @@ void StartCgiServer() TcpCgi *tcpCgi = TcpCgi::instance(); while (1) { tcpCgi->startCgiServer(); - boost::this_thread::sleep(boost::posix_time::seconds(10)); + sleep(10); } } - +void RunLED() +{ + while(1){ + gpio_set(GlobalConfig::GPIO_G.runLed,1); + sleep(1); + gpio_set(GlobalConfig::GPIO_G.runLed,0); + sleep(1); + } +} void HeartRep() { + int count = 0; while(1) { Json::Value jsHeart; Json::FastWriter fw; jsHeart["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; - jsHeart["status"] = "online"; + jsHeart["status"] = "online_V" + GlobalConfig::Version; + jsHeart["IP"] = GlobalConfig::IpAddr_G; std::string strJson = fw.write(jsHeart); - data_publish(strJson.c_str(), GlobalConfig::Topic_G.mPubHeart.c_str()); - boost::this_thread::sleep(boost::posix_time::seconds(10)); + int iRet = data_publish(strJson.c_str(), GlobalConfig::Topic_G.mPubHeart.c_str()); + print_info("heart = %s,iRet = %d\n",strJson.c_str(),iRet); + if(iRet != 0){ + count ++; + gpio_set(GlobalConfig::GPIO_G.errorLed,1); + sleep(1); + gpio_set(GlobalConfig::GPIO_G.errorLed,0); + sleep(1); + gpio_set(GlobalConfig::GPIO_G.errorLed,1); + sleep(1); + gpio_set(GlobalConfig::GPIO_G.errorLed,0); + sleep(1); + gpio_set(GlobalConfig::GPIO_G.errorLed,1); + sleep(1); + GlobalConfig::serverStatus = 1; + }else{ + GlobalConfig::serverStatus = 0; + count = 0; + gpio_set(GlobalConfig::GPIO_G.errorLed,0); + } + gpio_set(GlobalConfig::GPIO_G.errorLed,0); +// if(count > 0){ +// bool status = Ping( GlobalConfig::ServerIP.c_str(), 10000); +// if(status != 0) +// //LOG_INFO("===========net status ========failed heart count %d\n",count); +// if(status != 0 && count > 30){ +// LOG_ERROR("heart send failed,heart count %d\n",count); +// count = 0; +// sleep(20); +// gpio_set(GlobalConfig::GPIO_G.power,1); +// } +// } +// if(count > 1000){ +// gpio_set(GlobalConfig::GPIO_G.power,1); +// count = 0; +// } +// write_data(fd,"AT+QENG=\"servingcell\"\r\n",27); +// //sleep(1); +// char buff[1024]={0x00}; +// int ret = read_data(fd, buff, 1024, 10); +// print_info("ret = %d,buff = %s\n",ret,buff); +// const char *str2 = "+QENG: "; +// char csq[128] = {0}; +// char *pdata = strstr((char*)buff, str2); +// if(pdata){ +// strncpy(csq, pdata+7, sizeof(csq)); +// } +// else { +// } +// +// //printf("SIM-CSQ: %s\n", csq); +// GlobalConfig::NetStatus = GetOneContent(csq,1,","); +// string signal = GetOneContent(csq,13,","); +// GlobalConfig::NetSignal = atoi(signal.c_str()); +// print_info("NetStatus = %s,NetSignal = %d\n",GlobalConfig::NetStatus.c_str(),GlobalConfig::NetSignal); + + //GlobalConfig::NetSignal = getcsq(); + /*if(GlobalConfig::NetSignal <= -105 ){ + gpio_set(130,1); + }else if(GlobalConfig::NetSignal > -105 ){ + gpio_set(130,0); + }else{ + gpio_set(130,1); + }*/ + sleep(10); + //socketHeart(strJson.c_str()); } } +void GetCSQ() +{ +#ifdef NR5G_MODULE + //5G + int iRet = -1; +open5G: + iRet = dial.openPort("/dev/ttyUSB2"); + if (iRet < 0){ + sleep(5); + goto open5G; + } +#ifdef NR5G_MEIGE + dial.closePort(); + char szquectel[100]={0x00}; + std::string strAPN = ReadStrByOpt(SERVERCONFIG, "Server", "APN"); + sprintf(szquectel,"/opt/quectel-CM/Meig-CM -s %s &",strAPN.c_str()); + system(szquectel); +#else + dial.recvData(); +#endif +#endif +#ifdef Q4G_MODULE + //4G + int fd = -1; +open4G: + fd = config_uart("/dev/ttyUSB2",115200); + if (fd < 0){ + sleep(5); + goto open4G; + } + char szbuffer[200]={0x00}; + int offSize = 0; + int timeoutflag = 0; + write_data(fd,"AT+QENG=\"servingcell\"\r\n",27); + while(1){ + char buff[1024]={0x00}; + int ret = read_data(fd, buff, 1024, 10); + if(ret <= 0){ + timeoutflag ++; + if(timeoutflag > 5){ + print_info("timeoutflag = %d\n",timeoutflag); + timeoutflag = 0; + const char *str2 = "+QENG: "; + char csq[128] = {0}; + char *pdata = strstr((char*)szbuffer, str2); + if(pdata){ + strncpy(csq, pdata+7, sizeof(csq)); + + //printf("SIM-CSQ: %s\n", csq); + GlobalConfig::NetStatus = GetOneContent(csq,1,","); + string signal = GetOneContent(csq,13,","); + GlobalConfig::NetSignal = atoi(signal.c_str()); + GlobalConfig::NetType = GetOneContent(csq,2,","); + print_info("NetStatus = %s,NetSignal = %d\n",GlobalConfig::NetStatus.c_str(),GlobalConfig::NetSignal); + + } + memset(szbuffer,0x00,sizeof(szbuffer)); + offSize = 0; + write_data(fd,"AT+QENG=\"servingcell\"\r\n",27); + } + usleep(10000); + }else if(ret > 0){ + print_info("ret = %d,buff = %s\n",ret,buff); + memcpy(szbuffer + offSize,buff,ret); + offSize = offSize + ret; + print_info("szbuffer = %s\n",szbuffer); + continue; + } + sleep(10); + } +#endif +} +void Dial5G() +{ + sleep(2); +dial5G: + if(dial.m_fd > 0){ + dial.dial5G(); + }else{ + sleep(5); + goto dial5G; + } +} void UartStart() { // onReceiveUart cb = (onReceiveUart)&ProtoConvert::HandleFromUart; // pUart->setCallBack(cb); - pUart->InitUart(); + InitGpio(GlobalConfig::GPIO_G.zigAckrep,0);//ACK + InitGpio(GlobalConfig::GPIO_G.zigAckreset,1);//ACK reset + InitGpio(GlobalConfig::GPIO_G.zigReset,1);//Zigbee reset + gpio_set(GlobalConfig::GPIO_G.zigAckreset,1); + gpio_set(GlobalConfig::GPIO_G.zigReset,1); - while (GlobalConfig::QuitFlag_G) { +#ifdef IMX6UL_GATEWAY + InitGpio(GlobalConfig::GPIO_G.errorLed,1);//指示灯 + gpio_set(GlobalConfig::GPIO_G.errorLed,0); + InitGpio(GlobalConfig::GPIO_G.power,1);//power reset + gpio_set(GlobalConfig::GPIO_G.power,0); +#endif +#ifdef G2UL_GATEWAY + InitGpio(GlobalConfig::GPIO_G.runLed,1); + InitGpio(GlobalConfig::GPIO_G.errorLed,1); + gpio_set(GlobalConfig::GPIO_G.runLed,1); + gpio_set(GlobalConfig::GPIO_G.errorLed,0); + InitGpio(GlobalConfig::GPIO_G.netResetNet0,1); + gpio_set(GlobalConfig::GPIO_G.netResetNet0,0); +#endif + GlobalConfig::Zigbee_G.Serial_Rate = 0x07; + GlobalConfig::Zigbee_G.Serial_DataB = 0x08; + GlobalConfig::Zigbee_G.Serial_StopB = 0x01; + pUart->InitUart(B115200); + char buffer[1100]={0x00}; + + sleep(1); + pUart->UartRecv(pUart->fd,1,buffer); + sleep(1); - pUart->UpdateZigbeeInfoCtrl(); - pUart->ReadFromUart(); - pUart->Run(); -// pUart->Stop(); - boost::this_thread::sleep(boost::posix_time::milliseconds(10)); - } } +void InitModule() +{ +#ifdef NR5G_MODULE +#ifdef G2UL_GATEWAY + InitGpio(GlobalConfig::GPIO_G.commPower,1);//4G,5G模组供电, + gpio_set(GlobalConfig::GPIO_G.commPower,1); + InitGpio(GlobalConfig::GPIO_G.vol3_8,1);//5G 高电平3.8V,低电平3.3V + gpio_set(GlobalConfig::GPIO_G.vol3_8,1); + + InitGpio(GlobalConfig::GPIO_G.commRest,1); + gpio_set(GlobalConfig::GPIO_G.commRest,0);//高电平复位 +#endif +#ifdef IMX6UL_GATEWAY + InitGpio(GlobalConfig::GPIO_G.commRest,1); + gpio_set(GlobalConfig::GPIO_G.commRest,1);// +#endif +#endif +#ifdef Q4G_MODULE +#ifdef G2UL_GATEWAY + InitGpio(GlobalConfig::GPIO_G.commPower,1);//4G,5G模组供电, + gpio_set(GlobalConfig::GPIO_G.commPower,1); + InitGpio(GlobalConfig::GPIO_G.commRest,1); + gpio_set(GlobalConfig::GPIO_G.commRest,0);//高电平复位 + sleep(10); + char szquectel[100]={0x00}; + std::string strAPN = ReadStrByOpt(SERVERCONFIG, "Server", "APN"); + sprintf(szquectel,"/opt/quectel-CM/quectel-CM -s %s &",strAPN.c_str()); + system(szquectel); +#endif +#endif +#ifdef WIFI_MODULE + print_info("Init WiFi!\n"); + +#ifdef IMX6UL_GATEWAY + InitGpio(GlobalConfig::GPIO_G.wifiReset,1);//WiFi模组复位,0复位,1取消复位 + gpio_set(GlobalConfig::GPIO_G.wifiReset,1); + sleep(10); + wifi::WPAClient wpa; + wpa.ReconnectWiFi(); + system("/etc/init.d/wpa_restart"); + system("udhcpc -i wlan2 &"); +#endif +#ifdef G2UL_GATEWAY + InitGpio(GlobalConfig::GPIO_G.wifiReset,1);//WiFi模组复位,1复位,0取消复位 + gpio_set(GlobalConfig::GPIO_G.wifiReset,0); + InitGpio(GlobalConfig::GPIO_G.wifiPower,1);//WiFi模组上电 + gpio_set(GlobalConfig::GPIO_G.wifiPower,1); + sleep(10); + wifi::WPAClient wpa; + wpa.ReconnectWiFi(); + system("/usr/sbin/wpa_supplicant -Dnl80211 -iwlan0 -c/etc/wpa_supplicant.conf &"); + system("udhcpc -b -i wlan0 &"); +#endif +#endif +} +void TestUart() +{ + pUart->InitTestUart(B115200); + pUart->ReadTestUart(); +} void UartStartWave() { pUart->DealWaveThread(); @@ -158,7 +701,15 @@ void StartUdpSys() UdpSys *udpsys = UdpSys::instance(); udpsys->StartConnectSysUdp(); } - +void WatchDog() +{ + int fd = OpenWatchDog(); + while(1){ + WriteWatchDog(fd); + sleep(50); + } + close(fd); +} static const char* LOCAL_WILL_TOPIC = "up/uart/will"; void my_publish_callback(struct mosquitto *mosq, void *obj, int mid) { @@ -185,7 +736,7 @@ void my_connect_callback(struct mosquitto *mosq, void *obj, int result) connect_time = strtoll(gwTime, NULL, 10); print_debug("connect_time:%lld\n", connect_time); long long difftime_ms = connect_time - connect_lost_time; - //if (difftime_ms > 20*1000) { // 超过20秒,判定为连接断开 + if (difftime_ms > 20*1000) { // 超过20秒,判定为连接断开 char reply_string[256] = {0}; std::string startStatus = "0"; if (access(SYSTEMSTART, 0) >= 0) { @@ -199,20 +750,17 @@ void my_connect_callback(struct mosquitto *mosq, void *obj, int result) Json::FastWriter fw; jsData["cmd"] = "15"; jsData["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; - // jsData["cmdBody"] = ""; std::string strCmd15 = fw.write(jsData); - // data_publish(strCmd15.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); std::string instr = std::string(reply_string); std::string topic = "equipment/state/" + GlobalConfig::MacAddr_G; int ret = data_publish(instr.c_str(), topic.c_str()); - system("echo 0 > /CIDW/start"); if (ret != MOSQ_ERR_SUCCESS) { print_debug("Publish failed:%d, %s\n", ret, instr.c_str()); disconnect(); } - //} + } GlobalConfig::LinkStatus_G = 1; print_debug("Connect to server success.\n"); @@ -250,8 +798,8 @@ void my_disconnect_callback(struct mosquitto *mosq, void *obj, int result) { int ret = 0; ret = disconnect(); - // LOG_ERROR("The uart connection lost:%d\n", ret); - print_debug("The uart connection lost\n"); + //LOG_ERROR("The MQTT connection lost:%d\n", ret); + print_debug("The MQTT connection lost\n"); char gwTime[32] = { 0 }; GetTimeNet(gwTime, 0); uptime = std::string(gwTime); @@ -259,6 +807,41 @@ void my_disconnect_callback(struct mosquitto *mosq, void *obj, int result) print_debug("connect_lost_time:%lld\n", connect_lost_time); GlobalConfig::LinkStatus_G = 0; GlobalConfig::LinkCount = GlobalConfig::LinkCount + 1; + +#ifdef WIFI_MODULE + char buf[128] = {0}; + std::string wpa_state = ""; +#ifdef G2UL_GATEWAY + wpa_state = "/usr/sbin/wpa_cli status|grep wpa_state | cut -f 2 -d '='"; +#endif + +#ifdef IMX6UL_GATEWAY + wpa_state = "/opt/Cidn/wpa_cli status|grep wpa_state | cut -f 2 -d '='"; +#endif + system_custom(wpa_state.c_str(), buf); + std::string state = std::string(buf); + std::string RSSI_cmd = ""; +#ifdef G2UL_GATEWAY + RSSI_cmd = "/usr/sbin/wpa_cli signal_poll|grep RSSI | cut -f 2 -d '='"; +#endif +#ifdef IMX6UL_GATEWAY + RSSI_cmd = "/opt/Cidn/wpa_cli signal_poll|grep RSSI | cut -f 2 -d '='"; +#endif + system_custom(RSSI_cmd.c_str(), buf); + std::string RSSI = std::string(buf); + + int iRet = reconnect(); + memset(buf, 0, sizeof(buf)); + sprintf(buf, "wifi RSSI:%s,state:%s,MQTT reconnect :%d\n", RSSI.c_str(),state.c_str(),iRet); + //LOG_WARN(" %s\n",buf); + int status = Ping( GlobalConfig::ServerIP.c_str(), 10000);; + //LOG_WARN(" netStatus %d\n",status); + print_info("%s\n", buf); + +#else + int iRet = reconnect(); +#endif + } void my_message_callback(struct mosquitto *mosq, void *obj, const struct mosquitto_message *message) @@ -337,7 +920,7 @@ void StartMqttClient() register_collback(my_connect_callback, my_message_callback, my_subscribe_callback, my_log_callback, my_disconnect_callback, my_publish_callback); start_client(strEqupNo.c_str(), GlobalConfig::MacAddr_G.c_str(), GlobalConfig::ServerIP.c_str(), strVersion.c_str(), "11111111", salt); } - boost::this_thread::sleep(boost::posix_time::seconds(3)); + sleep(3); } } @@ -348,13 +931,14 @@ void SearchThread() while (GlobalConfig::QuitFlag_G) { if (GlobalConfig::IpAddr_G.length() > 0 && 0 != GlobalConfig::IpAddr_G.compare("0.0.0.0")) { + print_info("%s\n",runinfo.c_str()); boost::asio::io_service io_service; SearchDev *searchDevObj = new SearchDev(io_service); searchDevObj->MultiCastRecv(); io_service.run(); delete searchDevObj; } - boost::this_thread::sleep(boost::posix_time::seconds(5)); + sleep(5); print_error("SearchThred restart.\n"); } } diff --git a/threadfunc/SH_ThreadFunc.hpp b/threadfunc/SH_ThreadFunc.hpp index 38a4e4b..8f35074 100644 --- a/threadfunc/SH_ThreadFunc.hpp +++ b/threadfunc/SH_ThreadFunc.hpp @@ -27,5 +27,11 @@ extern void RecvUpdateFile(); //更新升级包 extern void StartCgiServer(); //启动cgi处理服务端 extern void HeartRep(); extern void UartStart(); // +extern void TestUart(); +extern void WatchDog(); extern void UartStartWave(); extern void StartUdpSys(); //组播通信 +extern void GetCSQ(); +extern void Dial5G(); +extern void InitModule(); +extern void RunLED(); diff --git a/uart/SH_Uart.cpp b/uart/SH_Uart.cpp index 77a95ac..c4adf45 100644 --- a/uart/SH_Uart.cpp +++ b/uart/SH_Uart.cpp @@ -1,4 +1,10 @@ #include +#include +#include +#include +#include +#include +#include #include #include #include @@ -6,12 +12,16 @@ #include #include #include "../uart/SH_Uart.hpp" +#include "../serial/serial.h" + namespace{ Uart *pUart = Uart::instance(); + Calculation *pCalculation = Calculation::instance(); } char g_UartRecvBuf[GENERAL_BUF_SIZE]; int offSize = 0; +pTestRecvCallBack pTestRecv ; // namespace{ // PlatformInit *platform = PlatformInit::instance(); // LocalServer *wlServer = LocalServer::instance(); @@ -21,73 +31,346 @@ using namespace boost::asio; const UINT CharSize = 8; const UINT UartBaud = 115200; +int Uart::UartRecv(int fd, char srcshow,char* buffer) +{ + char buff[BUF_LENGTH]; + int ret = 0; + int maxSize = 0; + int offSize = 0; + int timeoutflag = 0; + char head[] = {0xAA,0x55,0xAA}; + char szbuffer[BUF_LENGTH]={0x00} ; + while(1) + { + + if((unsigned short)GlobalConfig::Zigbee_G.MyAddr == 0x9999){ + memset(buff, 0, sizeof(buff)); + ret = read_data(fd, buff, BUF_LENGTH, 10); + if (ret <= 0 ){ + if(!bUpdate && !bUpdateconfig && GlobalConfig::EnterZigBeeWaveTransmittingCnt_G > 15){ + timeoutflag ++; + if(timeoutflag > 300){ + LOG_DEBUG("===============0x9999 timeout= %d offSize = %d===============\n",timeoutflag,offSize); + print_info("0x9999 timeout %d===============Size = %d\n",timeoutflag,offSize); + FindRecvPackage(offSize, mUartRecvTmpBuf,head); + GlobalConfig::Zigbee_G.MyAddr = 0x8888; + timeoutflag = 0; + offSize = 0; + maxSize = 0; + tcflush(fd,TCIFLUSH); + bModifyAddr = true; + modify_LocalAddr(0x8888); + bSendTimeStamp = false; + usleep(10000); + + GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = NO_ENTER_TRANSMITTING_STATUS; + GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; + DealWave(); + LOG_DEBUG("wave end\n"); + } + usleep(10000); + }else if(bUpdatePre || (bUpdateconfig && GlobalConfig::EnterZigBeeWaveTransmittingCnt_G > 15)){ + timeoutflag ++; + if(timeoutflag > 300){ + print_info("bUpdateconfig %d===============\n",timeoutflag); + GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = NO_ENTER_TRANSMITTING_STATUS; + GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; + timeoutflag = 0; + offSize = 0; + maxSize = 0; + bUpdate = false; + bUpdatePre = false; + bUpdateconfig = false; + bModifyAddr = true; + bSendTimeStamp = false; + modify_LocalAddr(0x8888); + usleep(100000); + GlobalConfig::Zigbee_G.MyAddr = 0x8888; + } + usleep(100000); + } + } + else if(ret > 0){ + maxSize += ret; + //print_debug("0x9999===str_recv===,ret = %d offSize = %d,bUpdatePre = %d,bUpdateconfig = %d\n",ret,maxSize,bUpdatePre,bUpdateconfig); +// for(int i = 0; i < ret;i++){ +// printf("[%02x]", buff[i]&0xff); +// } + //print_debug("maxSize = %d\n",maxSize); + //print_debug("\n"); + timeoutflag = 0; + + if((bUpdatePre || bUpdateconfig)) + { + for(int i = 0; i < ret;i++){ + printf("%02x ", buff[i]&0xff); + } + //print_debug("maxSize111 = %d\n",maxSize); + // string strTime = GetLocalTimeWithMs(); + // LOG_INFO("str_recv strTime1 = %s\n",strTime.c_str()); + FindRecvPackage(ret,buff,head); + // ReadHandle(buff,ret); + // strTime = GetLocalTimeWithMs(); + // LOG_INFO("str_recv strTime2 = %s\n",strTime.c_str()); + }else{ + m_TimeStamp = 0; + memcpy(mUartRecvTmpBuf + offSize,buff,ret); + offSize = offSize + ret; + if(offSize > BUF_LENGTH * 15){ + LOG_INFO("maxSize = %d\n",offSize); + memset(mUartRecvTmpBuf,0,BUF_LENGTH); + timeoutflag = 0; + offSize = 0; + maxSize = 0; + tcflush(fd,TCIOFLUSH); + bModifyAddr = true; + modify_LocalAddr(0x8888); + GlobalConfig::Zigbee_G.MyAddr = 0x8888; + GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = NO_ENTER_TRANSMITTING_STATUS; + GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; + } + print_debug("offSize = %d\n",offSize); + } + } + + }else if((unsigned short)GlobalConfig::Zigbee_G.MyAddr == 0x8888){ +#ifdef IMX6UL_GATEWAY + memset(buff, 0, sizeof(buff)); + ret = read_data(fd, buff, BUF_LENGTH, 50); + if (ret <= 0){ + continue; + } + if (srcshow) { + print_info("0x8888 ===str_recv===,ret = %d\n",ret); + for(int i = 0; i < ret;i++){ + print_debug("[%02x]", buff[i]&0xff); + } + printf("\n"); + FindRecvPackage(ret, buff,head); + + } +#else if G2UL_GATEWAY + memset(buff, 0x00, sizeof(buff)); + ret = read_data(fd, buff, BUF_LENGTH, 50); + if (ret <= 0 ){ + timeoutflag ++; + if(timeoutflag > 5){ + + FindRecvPackage(offSize, szbuffer,(char*)head); + memset(szbuffer,0x00,sizeof(szbuffer)); + timeoutflag = 0; + offSize = 0; + maxSize = 0; + usleep(10000); + } + }else if(ret > 0){ + maxSize += ret; + print_debug("0x8888==str_recv===,ret = %d offSize = %d\n",ret,maxSize); + for(int i = 0; i < ret;i++){ + print_debug("%02x ", buff[i]&0xff); + } + print_debug("\n"); + timeoutflag = 0; + m_TimeStamp = 0; + memcpy(szbuffer + offSize,buff,ret); + offSize = offSize + ret; + } +#endif + } + usleep(50); + } +} + Uart::Uart():mUart(mIoSev),mStrand(mIoSev) { - mRdLength = 0; - memset(mUartRecvBuf,0,BUF_LENGTH); + mRdLength = 0; + m_TimeStamp = 0; + mlastSize = 0; + fd = 0; + waittime = 0; + mPackgeIndex = -1; + bUpdate = false; + m_strDestShortAddr = ""; + memset(mUartRecvBuf,0,BUF_LENGTH); + memset(mUartRecvTmpBuf,0,BUF_LENGTH); + bTest = false; + TestFd = 0; + DataNodeUpdateFile = ""; + strTimetamp = ""; + bZigbeeSinal = false; + bModifyAddr = false; + bUpdatePre = false; + bSendTimeStamp = false; } - -void Uart::InitUart() -{ - //*.reset()作用重置对象,为run()的调用做准备 - mUart.get_io_service().reset(); - mStrand.get_io_service().reset(); - // ThreadInit(); - mRdLength = 0; - //errcode用来接收错误类型 - boost::system::error_code errcode; - //打开/dev/ttymxc4串口文件 - mUart.open(GlobalConfig::UartName_G,errcode); - if ( errcode) { - print_error("Fail To Open Uart!\n"); - // LOG_ERROR("Fail To Open Uart!\n"); - return ; - } else { - if (mUart.is_open()) { - print_info("Success To Open Uart!\n"); - } - } - //设置串口的波特率 数据位 流控 奇偶校验位 停止位 - mUart.set_option( serial_port::baud_rate(UartBaud), errcode); - mUart.set_option( serial_port::flow_control(serial_port::flow_control::none),errcode ); - mUart.set_option( serial_port::parity(serial_port::parity::none),errcode ); - mUart.set_option( serial_port::stop_bits(serial_port::stop_bits::one),errcode ); - mUart.set_option( serial_port::character_size(CharSize),errcode ); - - - // WriteToUart(); - // mUart.set_option( serial_port::baud_rate(UartBaud), errcode); - -} - Uart::~Uart() { + close(fd); + close(TestFd); if (mUart.is_open()) mUart.close(); } +void Uart::openSwitch() +{ + char buffer[100]={0x00}; + int len; + int fdSwitch = config_uart("/dev/ttymxc1",B38400); + char strSend[8]={0x01,0x06,0x00,0x00,0x00,0x00,0x89,0xCA}; + len = write_data(fdSwitch,(char*)strSend,8); + sleep(1); + len = read_data(fdSwitch,(char*)buffer,100,10); + for ( int i = 0; i < len; i++) + print_debug("%02X ",buffer[i]&0xFF); + char strSend2[8]={0x01,0x06,0x00,0x00,0x00,0x01,0x48,0x0A}; + len = write_data(fdSwitch,(char*)strSend2,8); + sleep(1); + len = read_data(fdSwitch,(char*)buffer,100,10); + for ( int i = 0; i < len; i++) + print_debug("%02X ",buffer[i]&0xFF); + close(fdSwitch); +} +void Uart::InitUart(speed_t speed) +{ + +#ifdef G2UL_GATEWAY + fd = config_uart("/dev/ttySC2",speed); +#endif +#ifdef IMX6UL_GATEWAY + fd = config_uart("/dev/ttymxc4",speed); +#endif + print_info("InitUart fd = %d\n",fd); + if(fd < 0){ + printf("config_uart error\n"); + } + +} +void Uart::Close() +{ + close(fd); + fd = 0; +} +void Uart::InitZigbee() +{ + + InitUart(B115200); + UpdateZigbeeInfoCtrl(); + sleep(2); + int iRet = ReadFromUart(); + if(iRet <= 0) + { + Close(); + sleep(2); + print_info("Speed error\n"); + InitUart(B57600); + UpdateZigbeeInfoCtrl(); + sleep(2); + ReadFromUart(); + print_info("modify speed\n"); + WriteSpeed2Zigbee(); + ReadFromUart(); + } + Close(); + sleep(1); +} +void TestRecv(int status) +{ + char szStatus[10]={0x00}; + sprintf(szStatus,"%d",status); + write_data(pUart->TestFd,(char*)szStatus,strlen(szStatus)); +} +void Regist(pTestRecvCallBack pTestRecv1){ + pTestRecv = pTestRecv1; +} +void Uart::InitTestUart(speed_t speed) +{ + print_info("InitTestUart\n"); + TestFd = config_uart("/dev/ttymxc2",speed);//Test + if(TestFd < 0){ + printf("Test config_uart error\n"); + } + Regist(TestRecv); +} + +void Uart::ReadTestUart() +{ + char buff[BUF_LENGTH] = {0x00}; + print_info("ReadTestUart\n"); + while(1){ + int ret = read_data(TestFd, buff, BUF_LENGTH, 10); + if(ret > 0){ + print_info("buff = %s\n",buff); + if(!strcmp(buff,"0")){ + + char buf[256] = {0}; + sprintf(buf, "{\"dataNodeGatewayNo\":\"%s\",\"cmd\":\"12\",\"status\":\"REQ\"}", + GlobalConfig::MacAddr_G.c_str()); + std::string str = std::string(buf); + int iRet = data_publish(str.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); + if(iRet < 0){ + pTestRecv(1); + }else{ + pTestRecv(0); + } + iRet = ZigbeeTest(); + }else if(!strcmp(buff,"1")){ + string IP = GetGwIp_("eth0"); + write_data(TestFd,(char*)IP.c_str(),IP.size()); + IP = GetGwIp_("eth1"); + write_data(TestFd,(char*)"|",1); + write_data(TestFd,(char*)IP.c_str(),IP.size()); + write_data(TestFd,(char*)"|",1); + }else{ + ModifyMac(buff); + pTestRecv(0); + } + } + usleep(20000); + } +} + +int Uart::ZigbeeTest() +{ + char buff[BUF_LENGTH] = {0x00}; + modify_Localchannel(22); + usleep(100000); + + modify_LocalPanID(2222); + + usleep(100000); + modify_LocalAddr(6666); + + usleep(100000); + return 0; +} + void Uart::WriteToUart(const char *strSend,int pLen) { //#ifdef ZIGBEE_TEST - print_debug("Write To Uart Start:\n"); - for(int i=0; i 0){ + ReadHandle(buffer,len); + }*/ } void Uart::Run() @@ -110,21 +407,336 @@ void Uart::Stop() mUart.close(); mIoSev.stop(); } - -void Uart::ReadHandle(const boost::system::error_code &ec,size_t bytesRead) +int Uart::FindRecvPackage(int bytesRead, char* mUartRecvBuf,char* head) { -try{ + string strTime = GetLocalTimeWithMs(); + char head1[] = {0xAB,0xBC,0xCD}; + char head2[] = {0xDE,0xDF,0xEF}; + + //LOG_INFO("m_VecWaveData= %d\n",m_VecWaveData.size()); + int lastSize = 0; + char UartRecvBuf[BUF_LENGTH*15]={0x00}; + char RecvBuf[200] = {0x00}; + if(mlastSize > 0){ + print_info("mlastSize = %d\n",mlastSize); + memcpy(UartRecvBuf,mUartRecvTmpBuf,mlastSize); + for(int i = 0; i < mlastSize;i++){ + print_info("%02x ",UartRecvBuf[i]); + } + print_info("\n "); + memset(mUartRecvTmpBuf,0x00,sizeof(mUartRecvTmpBuf)); + } + memcpy(UartRecvBuf + mlastSize,mUartRecvBuf,bytesRead); + // for(int i = 0 ; i < bytesRead;i++){ + // if(!(i % 100)) + // printf("\n"); + // printf("%02x ",mUartRecvBuf[i]); + // } + bytesRead = bytesRead + mlastSize; + for(int i = 0; i < bytesRead;i++){ + if(UartRecvBuf[i] == head[0]){ + char buf[6]={0x00}; + char ShortAddr[8]={0x00}; + sprintf(&buf[0], "%02X", UartRecvBuf[i]&0xFF); + sprintf(&buf[2], "%02X", UartRecvBuf[i+1]&0xFF); + sprintf(&buf[4], "%02X", UartRecvBuf[i+2]&0xFF); + sprintf(ShortAddr, "%02x%02x", UartRecvBuf[i+3]&0xFF, UartRecvBuf[i+4]&0xFF); + std::string strShortAddr(ShortAddr); + std::string strHeadFlag(buf); + if ( 0 == strHeadFlag.compare("AA55AA")) { + char buf[8]={0x00}; + sprintf(buf, "%02d", UartRecvBuf[i+5]&0xFF); + int command = atoi(buf); + //print_info("command = %d\n",command); + //print_info("index = %d\n",UartRecvBuf[i+6]&0xFF); + //print_info("mPackgeIndex1 = %d\n",mPackgeIndex); + if((mPackgeIndex == -1 || (unsigned int)UartRecvBuf[i+6] == 0) && (!bUpdatePre && !bUpdateconfig)){ + //print_info("mPackgeIndex2 = %d\n",mPackgeIndex); + mPackgeIndex = UartRecvBuf[i+6]&0xFF; + }else if((unsigned int)mPackgeIndex == (unsigned int)UartRecvBuf[i+6] && + mPackgeIndex != -1 && (!bUpdatePre && !bUpdateconfig) && command != 2){ + LOG_ERROR("mPackgeIndex same index1:%d,index2:%02d ShortAddr :%s \n",\ + mPackgeIndex,UartRecvBuf[i+6]&0xff,strShortAddr.c_str()); + continue; + + }else if((unsigned int)mPackgeIndex + 1 != (unsigned int)UartRecvBuf[i+6] && + mPackgeIndex != -1 && (!bUpdatePre && !bUpdateconfig) && command != 2){ + m_TimeStamp = 0; + //print_info("mPackgeIndex3 = %d\n",mPackgeIndex); + LOG_ERROR("mPackgeIndex error index1:%d,index2:%02d ShortAddr :%s \n",\ + mPackgeIndex,UartRecvBuf[i+6]&0xff,strShortAddr.c_str()); + mPackgeIndex = -1; + print_error("mPackgeIndex error ShortAddr :%s \n",strShortAddr.c_str()); + + char tmp[10]={0x00}; + char tmp2[10]={0x00}; + for(int j = 0; j < 100;j++){ + sprintf(tmp,"%02x ",UartRecvBuf[i + j] & 0xff); + strcat(tmp2,tmp); + } + LOG_ERROR("error str = %s\n",tmp2); + + tcflush(fd,TCIOFLUSH); + sleep(1); + modify_LocalAddr(0x8888); + sleep(1); + tcflush(fd,TCIOFLUSH); + bModifyAddr = true; + GlobalConfig::Zigbee_G.MyAddr = 0x8888; + GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = NO_ENTER_TRANSMITTING_STATUS; + GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; + std::vector().swap(m_VecWaveData); + break; + } + + if(command == 32){ + LOG_INFO("bUpdateconfig command = %d ShortAddr :%s\n",command,strShortAddr.c_str()); + memcpy(RecvBuf,(char*)&UartRecvBuf[i],12); + //for(int j = i; j < i+12;j++){ + // print_info("%02X ",UartRecvBuf[j]&0xFF); + //} + + if(!CheckCrc(RecvBuf,11)){ + LOG_INFO("CheckCrc error command 20 \n"); + mPackgeIndex = -1; + tcflush(fd,TCIOFLUSH); + sleep(1); + modify_LocalAddr(0x8888); + sleep(1); + tcflush(fd,TCIOFLUSH); + bModifyAddr = true; + GlobalConfig::Zigbee_G.MyAddr = 0x8888; + GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = NO_ENTER_TRANSMITTING_STATUS; + GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; + break; + } + bUpdate = true; + m_TimeStamp = 0; + DealRecvData(RecvBuf); + break; + }else if(!bUpdatePre && !bUpdateconfig && (command == 3 || command == 4 || command == 5)){ + if(!CheckCrc(&UartRecvBuf[i],99)){ + m_TimeStamp = 0; + mPackgeIndex = -1; + LOG_INFO("CheckCrc error ShortAddr :%s command = %d\n",strShortAddr.c_str(),command); + print_error("CheckCrc error ShortAddr :%s \n",strShortAddr.c_str()); + char tmp[10]={0x00}; + char tmp2[10]={0x00}; + for(int j = 0; j < 100;j++){ + sprintf(tmp,"%02x ",UartRecvBuf[i + j] & 0xff); + strcat(tmp2,tmp); + } + LOG_ERROR("error str = %s\n",tmp2); + print_info("\n"); + tcflush(fd,TCIOFLUSH); + sleep(1); + modify_LocalAddr(0x8888); + bModifyAddr = true; + sleep(1); + tcflush(fd,TCIOFLUSH); + GlobalConfig::Zigbee_G.MyAddr = 0x8888; + GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = NO_ENTER_TRANSMITTING_STATUS; + GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; + std::vector().swap(m_VecWaveData); + break; + } + mlastSize = 0; + lastSize = bytesRead - i; + //print_info("laseSize = %d , i = %d\n",lastSize,i); + if(lastSize < 100 && lastSize > 0){ + memcpy(mUartRecvTmpBuf,(char*)&UartRecvBuf[bytesRead-lastSize],lastSize); + mlastSize = lastSize; + break; + } + memcpy(RecvBuf,(char*)&UartRecvBuf[i],100); + DealDataNodeWave(RecvBuf); + }else if(!bUpdate && !bUpdateconfig && (command == 1 || command == 2 || command == 6 || command == 7)){ + char RecvBuf[100] = {0x00}; + memcpy(RecvBuf,&UartRecvBuf[i],100); + if(!CheckCrc(RecvBuf,99)){ + LOG_INFO("CheckCrc error ShortAddr :%s command = %d \n",strShortAddr.c_str(),command); + break; + } + DealRecvData(RecvBuf); + + }else if(bUpdate && !bUpdateconfig && (command == 1 || command == 2 || command == 6 || command == 7)){ + + print_info("m_strDestShortAddr = %s,strShortAddr = %s,waittime = %d\n",\ + m_strDestShortAddr.c_str(),strShortAddr.c_str(),waittime); + //if(waittime >= 2 || m_strDestShortAddr == strShortAddr) + { + char RecvBuf[100] = {0x00}; + memcpy(RecvBuf,&UartRecvBuf[i],100); + DealRecvData(RecvBuf); + LOG_INFO("Online = %s,command = %d\n",strShortAddr.c_str(),command); + waittime = 0; + bUpdate = false; + bUpdatePre = false; + m_strDestShortAddr = ""; + GlobalConfig::Zigbee_G.MyAddr = 0x8888; + GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = NO_ENTER_TRANSMITTING_STATUS; + GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; + //break; + }/*else if(m_strDestShortAddr != strShortAddr){ + usleep(100000); + waittime ++; + }*/ + + }else if(command == 34 && bUpdateconfig){ + LOG_INFO("bUpdateconfig command = %d ShortAddr :%s\n",command,strShortAddr.c_str()); + memset(RecvBuf,0x00,sizeof(RecvBuf)); + print_info("bUpdateconfig ShortAddr :%s\n",strShortAddr.c_str()); + //memcpy(RecvBuf,(char*)&UartRecvBuf[i],100); + /*for(int j = i; j < i+100;j++){ + print_info("%02X ",UartRecvBuf[j]&0xFF); + }*/ + m_TimeStamp = 0; + //if(!CheckCrc((char*)&UartRecvBuf[i],99)) + { + char whereCon[1024] = {0}; + char updateSql[1024] = { 0 }; + char buf[20]={0x00}; + sprintf(buf, "%02x%02x", UartRecvBuf[i+3]&0xFF, UartRecvBuf[i+4]&0xFF);//Zigbee 本地地址 2 byte + sprintf(updateSql, "UpdateFlag = 1"); + sprintf(whereCon, "zigbeeShortAddr='%s'", buf); + sql_ctl->UpdateTableData(T_SENSOR_INFO(TNAME), updateSql, whereCon); + //string strData = sql_ctl->GetNodeConfigureInfor(whereCon); + //data_publish(strData.c_str(), GlobalConfig::Topic_G.mPubConfig.c_str()); + bUpdateconfig = false; + mPackgeIndex = -1; + tcflush(fd,TCIOFLUSH); + sleep(1); + modify_LocalAddr(0x8888); + bModifyAddr = true; + sleep(1); + tcflush(fd,TCIFLUSH); + GlobalConfig::Zigbee_G.MyAddr = 0x8888; + GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = NO_ENTER_TRANSMITTING_STATUS; + GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; + break; + } + break; + }else if(command == 35){ + LOG_INFO("command = %d ShortAddr :%s\n",command,strShortAddr.c_str()); + for(int j = i; j < i+100;j++){ + printf("%02X ",UartRecvBuf[j]&0xFF); + } + char whereCon[1024] = {0}; + char updateSql[1024] = { 0 }; + char tableName[100]={0x00}; + sprintf(whereCon, "zigbeeShortAddr='%s'", strShortAddr.c_str()); + vec_t vecDataNodeNo = sql_ctl->GetDataSingleLine(T_SENSOR_INFO(TNAME), " dataNodeNo,LooseValue ", whereCon); + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(updateSql, "zigbeeSignal = '%02d' ",UartRecvBuf[i+14]&0xFF);//zigbeeRSSIType = 0 传感器获取网关信号强度 + sprintf(whereCon, "dataNodeNo='%s' and timeStamp = '%s'", (char*)vecDataNodeNo[0].c_str(),strTimetamp.c_str()); + sprintf(tableName,"t_dataStatic_%s",(char*)vecDataNodeNo[0].c_str()); + sql_ctl->UpdateTableData(tableName, updateSql, whereCon); + } + mPackgeIndex = (unsigned int)UartRecvBuf[i+6]; + + } + else{ + continue; + } + }else if(UartRecvBuf[i] == head1[0]){ + char buf[6]={0x00}; + sprintf(&buf[0], "%02X", UartRecvBuf[i]&0xFF); + sprintf(&buf[2], "%02X", UartRecvBuf[i+1]&0xFF); + sprintf(&buf[4], "%02X", UartRecvBuf[i+2]&0xFF); + std::string strHeadFlag(buf); + if ( 0 == strHeadFlag.compare("ABBCCD")) { + char buf[8]={0x00}; + sprintf(buf, "%02d", UartRecvBuf[i+3]&0xFF); + int command = atoi(buf); + print_info("command = %d\n",command); + if(command == 209){ + UpdateZigbeeInfo(&UartRecvBuf[i]); + }else if(command == 220){//DC + bModifyAddr = false; + LOG_INFO("zigbeeShortAddr = %s , ret = %02d\n",m_strDestShortAddr.c_str(),UartRecvBuf[i+6]&0xFF); + if(UartRecvBuf[i+6]&0xFF != 00){ + modify_LocalAddr(0x8888); + } + } + } + }else if(UartRecvBuf[i] == head2[0]){ + char buf[6]={0x00}; + sprintf(&buf[0], "%02X", UartRecvBuf[i]&0xFF); + sprintf(&buf[2], "%02X", UartRecvBuf[i+1]&0xFF); + sprintf(&buf[4], "%02X", UartRecvBuf[i+2]&0xFF); + std::string strHeadFlag(buf); + if ( 0 == strHeadFlag.compare("DEDFEF")) { + char buf[8]={0x00}; + sprintf(buf, "%02d", UartRecvBuf[i+3]&0xFF); + int command = atoi(buf); + print_info("command = %d\n",command); + char tmp[16] = {0x00}; + if(command == 209){//D1 + pTestRecv(command); + }else if(command == 219){//DB + pTestRecv(command); + }else if(command == 220){//DC + bModifyAddr = false; + print_info("%02x,%02x,%02x,%02x,%02x \n",UartRecvBuf[i],UartRecvBuf[i+1],UartRecvBuf[i+2],UartRecvBuf[i+3],UartRecvBuf[i+4]); + LOG_INFO("zigbeeShortAddr = %s , ret = %02d\n",m_strDestShortAddr.c_str(),UartRecvBuf[i+4]&0xFF); + + //pTestRecv(command); + }else if(command == 218){//DA + LOG_INFO("zigbeeShortAddr = %s , signal = %02d\n",m_strDestShortAddr.c_str(),UartRecvBuf[i+6]&0xFF); + char whereCon[1024] = {0}; + char updateSql[1024] = { 0 }; + char tableName[100]={0x00}; + bZigbeeSinal = false; + sprintf(whereCon, "zigbeeShortAddr='%s'", m_strDestShortAddr.c_str()); + vec_t vecDataNodeNo = sql_ctl->GetDataSingleLine(T_SENSOR_INFO(TNAME), " dataNodeNo,LooseValue ", whereCon); + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(updateSql, "zigbeeSignal = '%02d' ",UartRecvBuf[i+6]&0xFF);//zigbeeRSSIType = 1 网关获取传感器信号强度 + sprintf(whereCon, "dataNodeNo='%s' and timeStamp = '%s'", (char*)vecDataNodeNo[0].c_str(),strTimetamp.c_str()); + sprintf(tableName,"t_dataStatic_%s",(char*)vecDataNodeNo[0].c_str()); + sql_ctl->UpdateTableData(tableName, updateSql, whereCon); + Json::Value jsBody,jsonVal; + Json::FastWriter showValue; + char looseValue[10]={0x00}; + readStringValue("config", "loose",looseValue,(char*)GlobalConfig::Config_G.c_str()); + if(atof(looseValue) < atof(vecDataNodeNo[1].c_str())){ + jsBody["looseStatus"] = "1"; + }else{ + jsBody["looseStatus"] = "0"; + } + + jsonVal["cmd"] = "52"; + jsBody["timeStamp"] = strTimetamp; + jsBody["dataNodeNo"] = vecDataNodeNo[0]; + jsBody["zigbeeSignal"] = UartRecvBuf[i+6]&0xFF; + std::string dataBody = showValue.write(jsBody); + jsonVal["cmdBody"] = dataBody; + data_publish(showValue.write(jsonVal).c_str(), GlobalConfig::Topic_G.mPubConfig.c_str()); + + //pTestRecv(command); + } + } + } + + } + strTime = GetLocalTimeWithMs(); +// LOG_INFO("findRecvPackage strTime2 = %s\n",strTime.c_str()); +} +void Uart::ReadHandle(char* pUartRecvBuf,size_t bytesRead) +{ +/*try{ if (ec) { mRdLength = 0; -// ReadFromUart(); + ReadFromUart(); return ; } - else + else*/ { //长度检测 - printf("recv uart len in ZigBee short address %4x : %d\n recv uart data:", + char UartRecvBuf[BUF_LENGTH]={0x00}; + memcpy(UartRecvBuf,pUartRecvBuf,bytesRead); + print_info("recv uart len in ZigBee short address %4x : %d\n recv uart data:", (unsigned short)GlobalConfig::Zigbee_G.MyAddr, bytesRead); - for ( int i = 0; i < bytesRead; i++) - print_debug("%02X ",mUartRecvBuf[i]&0xFF); + // for ( int i = 0; i < bytesRead; i++) +// print_debug("%02X ",mUartRecvBuf[i]&0xFF); int iPackageSize = bytesRead / 100; if (0 == iPackageSize) { @@ -139,42 +751,39 @@ try{ if((unsigned short)GlobalConfig::Zigbee_G.MyAddr == (unsigned short)0x9999){ - for (int j = 0; j < iPackageSize; j++) { - char buf[6]; - char mUartRecvPackage[100] = {0}; - - memcpy(mUartRecvPackage, mUartRecvBuf+7-offSize, 100); - Count = Count - 100; - sprintf(&buf[0], "%02X", mUartRecvPackage[0]&0xFF); - sprintf(&buf[2], "%02X", mUartRecvPackage[1]&0xFF); - sprintf(&buf[4], "%02X", mUartRecvPackage[2]&0xFF); - std::string strHeadFlag(buf); - print_info("data package head command type:%s,Size = %d\n", strHeadFlag.c_str(),offSize); - if ( 0 == strHeadFlag.compare("AA55AA") ) { - DealRecvData(mUartRecvPackage); - } - } - offSize = 7; }else{ for (int j = 0; j < iPackageSize; j++) { - char buf[6]; - char mUartRecvPackage[100] = {0}; - // 多包分包,解包, - if (Count < 100) { - memcpy(mUartRecvPackage, &mUartRecvBuf[j * 100], Count); - } else { - memcpy(mUartRecvPackage, &mUartRecvBuf[j * 100], 100); - Count = Count - 100; - } + char buf[6]; + char mUartRecvPackage[100] = {0}; + char ShortAddr[8]; - sprintf(&buf[0], "%02X", mUartRecvPackage[0]&0xFF); - sprintf(&buf[2], "%02X", mUartRecvPackage[1]&0xFF); - sprintf(&buf[4], "%02X", mUartRecvPackage[2]&0xFF); + // 多包分包,解包, + if (Count < 100) { + memcpy(mUartRecvPackage, &UartRecvBuf[j * 100], Count); + } else { + memcpy(mUartRecvPackage, &UartRecvBuf[j * 100], 100); + Count = Count - 100; + } - //sprintf(&buf1[0], "%02X", mUartRecvPackage[3]&0xFF); + sprintf(&buf[0], "%02X", mUartRecvPackage[0]&0xFF); + sprintf(&buf[2], "%02X", mUartRecvPackage[1]&0xFF); + sprintf(&buf[4], "%02X", mUartRecvPackage[2]&0xFF); + sprintf(ShortAddr, "%02x%02x", mUartRecvPackage[3]&0xFF, mUartRecvPackage[4]&0xFF); + if(bUpdate){//waitting for the upated node 4s + std::string strShortAddr(ShortAddr); + print_info("m_strDestShortAddr = %s,strShortAddr = %s,waittime = %d\n",m_strDestShortAddr.c_str(),strShortAddr.c_str(),waittime); + if(waittime >= 40 || m_strDestShortAddr == strShortAddr){ + LOG_INFO("Online = %s\n",strShortAddr.c_str()); + waittime = 0; + bUpdate = false; + m_strDestShortAddr = ""; + }else if(m_strDestShortAddr != strShortAddr){ + usleep(100000); + waittime ++; + return ; + } + } std::string strHeadFlag(buf); - //std::string strType(buf1); - print_info("data package head command type:%s\n", strHeadFlag.c_str()); if ( 0 == strHeadFlag.compare("ABBCCD") && (0xD1 == (mUartRecvPackage[3]&0xFF))) { @@ -191,12 +800,12 @@ try{ }} } - //读串口循环 +/* //读串口循环 ReadFromUart(); } catch(...) { print_error("PlatFormInit exception happend.\n"); // LOG_ERROR("%s,%d\n", __FUNCTION__, __LINE__); -} +}*/ } void Uart::setCallBack(onReceiveUart _callback) @@ -236,9 +845,36 @@ void Uart::DataAnalysis_W(DevData &pData,bool pFlag) void Uart::UpdateZigbeeInfoCtrl() { - char buf[5] = {0xAB, 0xBC, 0xCD, 0xD1, 0x05}; + /* char buf[5] = {0xAB, 0xBC, 0xCD, 0xD1, 0x05}; WriteToUart(buf, 5); - boost::this_thread::sleep(boost::posix_time::seconds(1)); + sleep(1);*/ +// ReadFromUart(); + char command[5]={0x00}; + unsigned char command1[100]={0x00}; + command[0] = 0xab; + command[1] = 0xbc; + command[2] = 0xcd; + command[3] = 0xd1; + command[4] = 0xaa; + WriteToUart(command,5); + LOG_INFO("UpdateZigbeeInfoCtrl \n"); + /*for ( int i = 0; i < 20; i++) + print_info("%02X ",command[i]); + print_info("\n");*/ + /*int ret = write_data(fd, (char*)command, 5); + if (ret < 0) { + perror("write"); + return ; + } + // sleep(1); + + /*ret = read_data(fd, (char *)command1, 100, 10); + printf("ret = %d\n",ret); + if (ret <= 4) { + printf("info get error!\n"); + return ; + } + UpdateZigbeeInfo((char*)command1);*/ } void Uart::UpdateZigbeeInfo(const char *pData) @@ -248,11 +884,11 @@ void Uart::UpdateZigbeeInfo(const char *pData) GlobalConfig::Zigbee_G = *((ZIGBEE *)pData); char buff[8]; sprintf(buff, "%02d", pData[36]&0xFF); - GlobalConfig::ZigbeeInfo_G.DevMode = boost::lexical_cast(buff); + GlobalConfig::ZigbeeInfo_G.DevMode = atoi(buff); memset(buff, 0, 8); sprintf(buff, "%02d", pData[37]&0xFF); - GlobalConfig::ZigbeeInfo_G.Channel = boost::lexical_cast(buff); + GlobalConfig::ZigbeeInfo_G.Channel = atoi(buff); memset(buff, 0, 8); sprintf(buff, "%02x%02x", pData[38]&0xFF, pData[39]&0xFF); @@ -265,10 +901,59 @@ void Uart::UpdateZigbeeInfo(const char *pData) memset(buff, 0, 8); sprintf(buff, "%02x%02x", pData[50]&0xFF, pData[51]&0xFF); - GlobalConfig::ZigbeeInfo_G.DstAddr = std::string(buff); + GlobalConfig::ZigbeeInfo_G.DstAddr = std::string(buff); - print_info("local zigbee module info Mode : %d Chan : %d PanID : %s MyAddr : %s DstAddr : %s\n", GlobalConfig::ZigbeeInfo_G.DevMode, GlobalConfig::ZigbeeInfo_G.Channel, - GlobalConfig::ZigbeeInfo_G.PanID.c_str(),GlobalConfig::ZigbeeInfo_G.MyAddr.c_str(), GlobalConfig::ZigbeeInfo_G.DstAddr.c_str()); + memset(buff, 0, 8); + sprintf(buff, "%d", pData[62]); + GlobalConfig::ZigbeeInfo_G.RetryNum = std::string(buff); + + memset(buff, 0, 8); + sprintf(buff, "%d", pData[63]); + GlobalConfig::ZigbeeInfo_G.TranTimeout = std::string(buff); + + LOG_INFO("local zigbee module info Mode : %d Chan : %d PanID : %s MyAddr : %s DstAddr : %s,RetryNum:%s,TranTimeout:%s\n", GlobalConfig::ZigbeeInfo_G.DevMode, GlobalConfig::ZigbeeInfo_G.Channel, + GlobalConfig::ZigbeeInfo_G.PanID.c_str(),GlobalConfig::ZigbeeInfo_G.MyAddr.c_str(), GlobalConfig::ZigbeeInfo_G.DstAddr.c_str(),GlobalConfig::ZigbeeInfo_G.RetryNum.c_str(),GlobalConfig::ZigbeeInfo_G.TranTimeout.c_str()); +// if(GlobalConfig::ZigbeeInfo_G.MyAddr != "8888"){ +// modify_LocalAddr(0x8888); +// +// LOG_INFO("zigbee Update \n"); +// GlobalConfig::ZigbeeInfo_G.MyAddr = "8888"; +// } + LOG_INFO("PanID = %s,MacAddr_G= %s\n",GlobalConfig::ZigbeeInfo_G.PanID.c_str(),GlobalConfig::MacAddr_G.c_str()); +// if(GlobalConfig::ZigbeeInfo_G.PanID != GlobalConfig::MacAddr_G.substr(8)){ +// string strPanId = GlobalConfig::MacAddr_G.substr(8); +// long lShortAddr = strtol(strPanId.c_str(), NULL, 16); +// unsigned short panid = lShortAddr & 0xffff; +// //modify_LocalPanID(panid); +// WritePanId2Zigbee(panid); +// usleep(100000); +// LOG_ERROR("PanID error"); +// } + + + std::string strchan = ReadStrByOpt(ZIGBEECONFIG, "Zigbee", "channel"); + LOG_INFO("Channel = %d,strchan = %s\n",GlobalConfig::ZigbeeInfo_G.Channel,strchan.c_str()); +// if(GlobalConfig::ZigbeeInfo_G.Channel != atoi(strchan.c_str())){ +// unsigned short Chan = (unsigned short)strtol(strchan.c_str(), NULL, 10); +// if(Chan > 10 && Chan < 27) +// { +// //modify_Localchannel(Chan); +// WriteChanl2Zigbee(Chan); +// usleep(100000); +// } +// LOG_ERROR("channel error"); +// } + + std::string strType = ReadStrByOpt(SYSTEMINFOFILE, "ZigbeeType", "type"); + print_info("TranTimeout = %02x,strType = %s \n",GlobalConfig::Zigbee_G.TranTimeout,strType.c_str()); + if(strType == "aw21"){ + unsigned short TranTimeout = 0x0A; + WriteTranTimeout2Zigbee(TranTimeout); + } + if( strType == "zm5161"){ + unsigned short TranTimeout = 0x03; + WriteTranTimeout2Zigbee(TranTimeout); + } // LOG_INFO("[UpdateZigbeeInfo---] ZigBee PanID: %s ; Channel: %d ; MyAddr : %s ",GlobalConfig::ZigbeeInfo_G.PanID.c_str(),GlobalConfig::ZigbeeInfo_G.Channel,GlobalConfig::ZigbeeInfo_G.MyAddr.c_str()); } @@ -284,26 +969,53 @@ bool Uart::ReadUpdatePackge(unsigned char* pDestShortAddr) { //compare hardversion in update list std::vector strHWversion; - std::string strFileName = ""; - strHWversion = ReadStrByOpt("/opt/update/DataNode/config.json",strFileName); + std::string strFileName = "",strSoftVersion = ""; + std::vector vecDataNodeUpdate; + vecDataNodeUpdate = ReadStrUpdate("/opt/DataNode/config.json"); char gethardVersion_sql[32] = { 0 }; + char selectsql[1024]={ 0 }; sprintf(gethardVersion_sql, "zigbeeShortAddr='%02x%02x'", pDestShortAddr[0],pDestShortAddr[1]); - std::string hardVersion = sql_ctl->GetData(T_SENSOR_INFO(TNAME), T_SENSOR_INFO(HARDVERSION), gethardVersion_sql); - int thisindex = -1; - for(int i = 0; i < strHWversion.size();i++){ - if(hardVersion == strHWversion[i]){ - thisindex = i; - break; - } + sprintf(selectsql,"%s,%s",T_SENSOR_INFO(HARDVERSION),T_SENSOR_INFO(SOFTVERSION)); + vec_t vecResult = sql_ctl->GetDataSingleLine(T_SENSOR_INFO(TNAME), selectsql, gethardVersion_sql); + if(vecResult.size() < 1){ + return false; } - printf("thisindex = %d\n",thisindex); + print_info("hardversion %s,softversion %s\n",vecResult[0].c_str(),vecResult[1].c_str()); + int thisindex = -1; + int flag = -1; + for(int j = 0; j < vecDataNodeUpdate.size();j++){ + for(int i = 0; i < vecDataNodeUpdate[j].hwVersion.size();i++){ + if(vecResult[0] == vecDataNodeUpdate[j].hwVersion[i]){ + if(vecResult[1] == vecDataNodeUpdate[j].strSoftVersion){ + flag = 0; + break; + }else{ + thisindex = i; + strFileName = vecDataNodeUpdate[j].strUpdataFileName; + break; + } + } + } + if(thisindex >= 0 || flag == 0) + break; + } + if(thisindex < 0) return false; + +// if(!strncmp(vecResult[0].c_str(),"3",1)){ +// WriteTranTimeout2Zigbee(0x03); +// }else if(!strncmp(vecResult[0].c_str(),"4",1)){ +// WriteTranTimeout2Zigbee(0x0A); +// } + + print_info("thisindex = %d\n",thisindex); + FILE * pFile=NULL; int thisSize = 0; - strFileName = "/opt/update/DataNode/" + strFileName; - printf("strFileName = %s\n",strFileName.c_str()); - pFile = fopen (strFileName.c_str(),"rb"); + DataNodeUpdateFile = "/opt/DataNode/" + strFileName; + print_info("strFileName = %s\n",DataNodeUpdateFile.c_str()); + pFile = fopen (DataNodeUpdateFile.c_str(),"rb"); if (pFile==NULL){ return false; } @@ -315,18 +1027,24 @@ bool Uart::ReadUpdatePackge(unsigned char* pDestShortAddr) fclose (pFile); } - unsigned short localAddr = 0x9999; - WriteShortAddr_DistAddr2Zigbee(localAddr,pDestShortAddr); +// WriteShortAddr_DistAddr2Zigbee(localAddr,pDestShortAddr);//永久参数配置 +/* char tmpbuf[8] = {0x00}; + * unsigned short localAddr = 0x9999; + sprintf(tmpbuf,"%02x%02x",pDestShortAddr[0],pDestShortAddr[1]); + m_strDestShortAddr = std::string(tmpbuf); + modify_distaddr_info(localAddr,"",pDestShortAddr);//临时参数配置 + GlobalConfig::Zigbee_G.MyAddr = 0x9999;*/ + unsigned char Data[12]={0x00}; unsigned char size[4]={0x00}; - printf("thisSize = %d\n",thisSize); + print_info("thisSize = %d\n",thisSize); //帧头[3byte] 节点地址[2byte] 数据类型[1byte] 序号[1byte] 升级包大小[4byte] CRC校验[1byte] Data[0]=0xAA; Data[1]=0x55; Data[2]=0xAA; Data[3]=pDestShortAddr[0]; Data[4]=pDestShortAddr[1]; - Data[5]=0x07; + Data[5]=0x20; Data[6]=0x00; int2bytes(thisSize,size,4); Data[7]=size[3]; @@ -338,81 +1056,356 @@ bool Uart::ReadUpdatePackge(unsigned char* pDestShortAddr) tmp +=Data[i]; } Data[11]=tmp; + sleep(1); WriteToUart((const char*)Data,12); - boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); - ReadFromUart(); + string strTime = GetLocalTimeWithMs(); + LOG_INFO("ReadUpdatePackge strTime = %s\n",strTime.c_str()); return true; } void Uart::UpdateWirelessNode(unsigned short shortAdd) { - LOG_INFO("UpdateWirelessNode id = %02x %02x\n",UINT16_HIGH(shortAdd),UINT16_LOW(shortAdd)); + string strTime = GetLocalTimeWithMs(); + LOG_INFO("UpdateWirelessNode start = %s UpdateWirelessNode id = %02x %02x\n",strTime.c_str(),UINT16_HIGH(shortAdd),UINT16_LOW(shortAdd)); + /*std::string strFileName = "",strSoftVersion = ""; + std::vector vecDataNodeUpdate; + vecDataNodeUpdate = ReadStrUpdate("/opt/DataNode/config.json"); - std::string strFileName = ""; - ReadStrByOpt("/opt/update/DataNode/config.json",strFileName); - FILE * pFile=NULL; - int thisSize = 0; - char *buffer=NULL; - strFileName = "/opt/update/DataNode/" + strFileName; - pFile = fopen (strFileName.c_str(),"rb"); - if (pFile==NULL) perror ("Error opening file"); - else - { - while (fgetc(pFile) != EOF) { - ++thisSize; + char gethardVersion_sql[32] = { 0 }; + sprintf(gethardVersion_sql, "zigbeeShortAddr='%02x%02x'", UINT16_HIGH(shortAdd),UINT16_LOW(shortAdd)); + std::string SoftVersion = sql_ctl->GetData(T_SENSOR_INFO(TNAME), "softVersion", gethardVersion_sql); + + print_info("SoftVersion = %s\n",SoftVersion.c_str()); + LOG_INFO(" NOW SoftVersion = %s\n",SoftVersion.c_str());*/ + ////// + ////// + //strFileName = "/opt/DataNode/" + strFileName; + FILE * pFile=NULL; + int thisSize = 0; + char *buffer=NULL; + int resendCount = 0; + pFile = fopen (DataNodeUpdateFile.c_str(),"rb"); + if (pFile==NULL) perror ("Error opening file"); + else + { + while (fgetc(pFile) != EOF) { + ++thisSize; + } + rewind(pFile); + buffer = (char*)malloc(thisSize);// + fread (buffer, sizeof (char), thisSize, pFile); + fclose (pFile); + + int Count = thisSize / 92; + int lastSize = thisSize % 92; + unsigned char UpdateData[100]={0x00}; + //帧头[3byte] 节点地址[2byte] 数据类型[1byte] 序号[1byte] 数据包[92byte] CRC校验[1byte] + print_info("Start Update!!! file Size = %d\n",thisSize); + unsigned char tmp = 0x00; + gpio_set(GlobalConfig::GPIO_G.zigAckreset,0); + //boost::this_thread::sleep(boost::posix_time::milliseconds(1)); + usleep(1000); + gpio_set(GlobalConfig::GPIO_G.zigAckreset,1); + for(int j = 0; j < Count;j++){ + int time ,value; + UpdateData[0]=0xAA; + UpdateData[1]=0x55; + UpdateData[2]=0xAA; + UpdateData[3]=UINT16_HIGH(shortAdd); + UpdateData[4]=UINT16_LOW(shortAdd); + UpdateData[5]=0x21; + UpdateData[6]=0xff & j; + memcpy(&UpdateData[7],buffer+92*j,92); + tmp = 0x00; + for(int k = 0; k < 99;k++){ + tmp +=UpdateData[k]; + } + UpdateData[99] = tmp; +// RESEND: + WriteToUart((const char*)UpdateData,100); + if(gpio_read(GlobalConfig::GPIO_G.zigAckrep) == 48) + gpio_set(GlobalConfig::GPIO_G.zigAckreset,1); + time = 0; + do{ + value = gpio_read(GlobalConfig::GPIO_G.zigAckrep); + if(value == 49) + break; + usleep(10000); + time += 1; + }while(time < 250); + if(time >= 250){ +// resendCount++; +// if(resendCount < 3){ +// LOG_INFO(" RESEND gpio_read failed shortAdd %x %x,error index %d\n",UINT16_HIGH(shortAdd),UINT16_LOW(shortAdd),j); +// goto RESEND; +// } + LOG_INFO("gpio_read failed shortAdd %x %x,error index %d\n",UINT16_HIGH(shortAdd),UINT16_LOW(shortAdd),j); + print_red("gpio_read failed \n"); + GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = NO_ENTER_TRANSMITTING_STATUS; + GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; + bUpdate = false; + goto endUpdate; + } + gpio_set(GlobalConfig::GPIO_G.zigAckreset,0); + usleep(2000); +// if(gpio_read(GlobalConfig::GPIO_G.zigAckrep) == 48) +// gpio_set(GlobalConfig::GPIO_G.zigAckreset,1); + memset(UpdateData,0x00,sizeof(UpdateData)); + //boost::this_thread::sleep(boost::posix_time::milliseconds(5)); + usleep(5000); + } + if(gpio_read(GlobalConfig::GPIO_G.zigAckrep) == 48) + gpio_set(GlobalConfig::GPIO_G.zigAckreset,1); + // printf("Count =%d,lastSize = %d\n",Count,lastSize); + if(lastSize > 0){ + UpdateData[0]=0xAA; + UpdateData[1]=0x55; + UpdateData[2]=0xAA; + UpdateData[3]=UINT16_HIGH(shortAdd); + UpdateData[4]=UINT16_LOW(shortAdd); + UpdateData[5]=0x21; + UpdateData[6]=0xff & Count; + memcpy(&UpdateData[7],buffer+92*Count,lastSize); + tmp = 0x00; + for(int k = 0; k < 99;k++){ + tmp +=UpdateData[k]; + } + UpdateData[99] = tmp; + WriteToUart((const char*)UpdateData,100); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); +// if(gpio_read(GlobalConfig::GPIO_G.zigAckrep) == 49){ +// gpio_set(GlobalConfig::GPIO_G.zigAckreset,0); +// boost::this_thread::sleep(boost::posix_time::milliseconds(1)); +// if(gpio_read(GlobalConfig::GPIO_G.zigAckrep) == 48)gpio_set(GlobalConfig::GPIO_G.zigAckreset,1); +// } + int time = 0; + do{ + int value = gpio_read(GlobalConfig::GPIO_G.zigAckrep); + if(value == 49){ + gpio_set(GlobalConfig::GPIO_G.zigAckreset,0); + usleep(10000); + if(gpio_read(GlobalConfig::GPIO_G.zigAckrep) == 48) + gpio_set(GlobalConfig::GPIO_G.zigAckreset,1); + break; + } + usleep(100); + time += 1; + }while(time < 2500); + if(time >= 2500){ + LOG_INFO("gpio_read failed shortAdd %x %x\n",UINT16_HIGH(shortAdd),UINT16_LOW(shortAdd)); + print_info("gpio_read failed \n"); + GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = NO_ENTER_TRANSMITTING_STATUS; + GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; + bUpdate = false; + goto endUpdate; + } + memset(UpdateData,0x00,sizeof(UpdateData)); + } + print_info("Update END!!! file Size = %d\n",thisSize); + } + endUpdate: + free(buffer); + tcflush(fd,TCIFLUSH); + boost::this_thread::sleep(boost::posix_time::seconds(1)); + bUpdate = false; + bSendTimeStamp = false; + modify_LocalAddr(0x8888); + bModifyAddr = true; + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + GlobalConfig::Zigbee_G.MyAddr = 0x8888; + DataNodeUpdateFile = ""; + std::vector().swap(m_VecWaveData); + // WriteShortAddr2Zigbee(shortAddr); + // UpdateZigbeeInfoCtrl(); + GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = NO_ENTER_TRANSMITTING_STATUS; + GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; + LOG_INFO("UpdateWirelessNode end"); +} +int Uart::UpdateConfig(unsigned char* pDestShortAddr) +{ + char whereCon[64] = { 0 }; + char selCon[100]={0x00}; + sprintf(whereCon, "zigbeeShortAddr='%02x%02x'", pDestShortAddr[0],pDestShortAddr[1]); + //std::string strUpdate = sql_ctl->GetData(T_SENSOR_INFO(TNAME), "UpdateFlag", whereCon); + vec_t vecResultNode = sql_ctl->GetDataSingleLine(T_SENSOR_INFO(TNAME), "*", whereCon); + if(vecResultNode.size() <= 0) + return -1; + if(vecResultNode[41] == "0") + { +// if(!strncmp(vecResult[1].c_str(),"3",1)){//zm5161 +// WriteTranTimeout2Zigbee(0x03); +// }else if(!strncmp(vecResult[1].c_str(),"4",1)){//aw21 +// WriteTranTimeout2Zigbee(0x0A); +// } + print_info("UpdateConfig\n"); + bUpdateconfig = true; + unsigned short localAddr = 0x9999; + // WriteShortAddr_DistAddr2Zigbee(localAddr,pDestShortAddr);//永久参数配置 + char tmpbuf[8] = {0x00}; + sprintf(tmpbuf,"%02x%02x",pDestShortAddr[0],pDestShortAddr[1]); + m_strDestShortAddr = std::string(tmpbuf); + modify_distaddr_info(localAddr,"",pDestShortAddr);//临时参数配置 + GlobalConfig::Zigbee_G.MyAddr = 0x9999; + boost::this_thread::sleep(boost::posix_time::milliseconds(500)); + vec_t vecResult; + sprintf(selCon,"featureInterVal,waveInterVal,range,samplingRate,ACCSampleTime,startBrands,stopBrands,\ + envelopeBandPass,faultFrequency,timeStamp,viff"); + vecResult = sql_ctl->GetDataSingleLine(T_SENSOR_INFO(TNAME),selCon,whereCon); + print_info("vecResult size = %d\n",vecResult.size()); + if(vecResult.size() < 1){ + return -1; } - rewind(pFile); - buffer = (char*)malloc(thisSize);// - fread (buffer, sizeof (char), thisSize, pFile); - fclose (pFile); - - int Count = thisSize / 92; - int lastSize = thisSize % 92; unsigned char UpdateData[100]={0x00}; //帧头[3byte] 节点地址[2byte] 数据类型[1byte] 序号[1byte] 数据包[92byte] CRC校验[1byte] - print_info("Start Update!!! file Size = %d\n",thisSize); + UpdateData[0]=0xAA; + UpdateData[1]=0x55; + UpdateData[2]=0xAA; + UpdateData[3]=pDestShortAddr[0]; + UpdateData[4]=pDestShortAddr[1]; + UpdateData[5]=0x22; + UpdateData[6]=0x00; + UpdateData[7]=0xAA; + UpdateData[8]=UINT16_LOW(atoi(vecResult[0].c_str())); + UpdateData[9]=UINT16_HIGH(atoi(vecResult[1].c_str())); + UpdateData[10]=UINT16_LOW(atoi(vecResult[1].c_str())); + int y = 0; + if(vecResultNode[17] == "01"){ + if(vecResult[3]=="3200"){ + y = 0; + }else if(vecResult[3]=="6400"){ + y = 1; + }else if(vecResult[3]=="12800"){ + y = 2; + }else if(vecResult[3]=="25600"){ + y = 3; + } + }else if(vecResultNode[17] == "02"){ + if(vecResult[3]=="8000"){ + y = 0; + }else if(vecResult[3]=="16000"){ + y = 1; + }else if(vecResult[3]=="24000"){ + y = 2; + }else if(vecResult[3]=="32000"){ + y = 3; + }else if(vecResult[3]=="48000"){ + y = 4; + }else if(vecResult[3]=="96000"){ + y = 5; + }else if(vecResult[3]=="192000"){ + y = 6; + } + } + int x = atoi(vecResult[2].c_str()); + UpdateData[21] = BUILD_UINT2(x,y); + UpdateData[22] = atoi(vecResult[4].c_str()) & 0xFF; + print_info("vecResult size = %s==%s==%s==%s\n",vecResult[5].c_str(),vecResult[6].c_str(),vecResult[7].c_str(),vecResult[8].c_str()); + vector vStart,vStop,vEnvelopeBandPass,vfaultFrequency; + boost::split( vStart, vecResult[5], boost::is_any_of( "," ), boost::token_compress_on ); + boost::split( vStop, vecResult[6], boost::is_any_of( "," ), boost::token_compress_on ); + boost::split( vEnvelopeBandPass, vecResult[7], boost::is_any_of( "," ), boost::token_compress_on ); + boost::split( vfaultFrequency, vecResult[8], boost::is_any_of( "," ), boost::token_compress_on ); + + UpdateData[23] = UINT16_HIGH(atoi(vStart[0].c_str())); + UpdateData[24] = UINT16_LOW(atoi(vStart[0].c_str())); + UpdateData[25] = UINT16_HIGH(atoi(vStop[0].c_str())); + UpdateData[26] = UINT16_LOW(atoi(vStop[0].c_str())); + + UpdateData[27] = UINT16_HIGH(atoi(vStart[1].c_str())); + UpdateData[28] = UINT16_LOW(atoi(vStart[1].c_str())); + UpdateData[29] = UINT16_HIGH(atoi(vStop[1].c_str())); + UpdateData[30] = UINT16_LOW(atoi(vStop[1].c_str())); + + UpdateData[31] = UINT16_HIGH(atoi(vStart[2].c_str())); + UpdateData[32] = UINT16_LOW(atoi(vStart[2].c_str())); + UpdateData[33] = UINT16_HIGH(atoi(vStop[2].c_str())); + UpdateData[34] = UINT16_LOW(atoi(vStop[2].c_str())); + + UpdateData[35] = UINT16_HIGH(atoi(vStart[3].c_str())); + UpdateData[36] = UINT16_LOW(atoi(vStart[3].c_str())); + UpdateData[37] = UINT16_HIGH(atoi(vStop[3].c_str())); + UpdateData[38] = UINT16_LOW(atoi(vStop[3].c_str())); + + UpdateData[39] = UINT16_HIGH(atoi(vStart[4].c_str())); + UpdateData[40] = UINT16_LOW(atoi(vStart[4].c_str())); + UpdateData[41] = UINT16_HIGH(atoi(vStop[4].c_str())); + UpdateData[42] = UINT16_LOW(atoi(vStop[4].c_str())); + + UpdateData[43] = UINT16_HIGH(atoi(vEnvelopeBandPass[0].c_str())); + UpdateData[44] = UINT16_LOW(atoi(vEnvelopeBandPass[0].c_str())); + UpdateData[45] = UINT16_HIGH(atoi(vEnvelopeBandPass[1].c_str())); + UpdateData[46] = UINT16_LOW(atoi(vEnvelopeBandPass[1].c_str())); + + UpdateData[47] = UINT16_HIGH(atoi(vfaultFrequency[0].c_str())); + UpdateData[48] = UINT16_LOW(atoi(vfaultFrequency[0].c_str())); + UpdateData[49] = UINT16_HIGH(atoi(vfaultFrequency[1].c_str())); + UpdateData[50] = UINT16_LOW(atoi(vfaultFrequency[1].c_str())); + + UpdateData[51] = UINT16_HIGH(atoi(vfaultFrequency[2].c_str())); + UpdateData[52] = UINT16_LOW(atoi(vfaultFrequency[2].c_str())); + UpdateData[53] = UINT16_HIGH(atoi(vfaultFrequency[3].c_str())); + UpdateData[54] = UINT16_LOW(atoi(vfaultFrequency[3].c_str())); + + UpdateData[55] = UINT32_HIGH_1(atoi(vecResult[9].c_str())); + UpdateData[56] = UINT32_HIGH_2(atoi(vecResult[9].c_str())); + UpdateData[57] = UINT32_LOW_1(atoi(vecResult[9].c_str())); + UpdateData[58] = UINT32_LOW_2(atoi(vecResult[9].c_str())); + + UpdateData[59] = (atoi(vecResult[10].c_str())) & 0xFF; unsigned char tmp = 0x00; - for(int j = 0; j < Count;j++){ - UpdateData[0]=0xAA; - UpdateData[1]=0x55; - UpdateData[2]=0xAA; - UpdateData[3]=UINT16_HIGH(shortAdd); - UpdateData[4]=UINT16_LOW(shortAdd); - UpdateData[5]=0x08; - UpdateData[6]=0xff & j; - memcpy(&UpdateData[7],buffer+92*j,92); - tmp = 0x00; - for(int k = 0; k < 99;k++){ - tmp +=UpdateData[k]; - } - UpdateData[99] = tmp; - WriteToUart((const char*)UpdateData,100); - boost::this_thread::sleep(boost::posix_time::milliseconds(200)); - memset(UpdateData,0x00,sizeof(UpdateData)); + for(int k = 0; k < 99;k++){ + tmp +=UpdateData[k]; } - printf("Count =%d,lastSize = %d\n",Count,lastSize); - if(lastSize > 0){ - UpdateData[0]=0xAA; - UpdateData[1]=0x55; - UpdateData[2]=0xAA; - UpdateData[3]=UINT16_HIGH(shortAdd); - UpdateData[4]=UINT16_LOW(shortAdd); - UpdateData[5]=0x08; - UpdateData[6]=0xff & Count; - memcpy(&UpdateData[7],buffer+92*Count,lastSize); - tmp = 0x00; - for(int k = 0; k < 99;k++){ - tmp +=UpdateData[k]; - } - UpdateData[99] = tmp; - WriteToUart((const char*)UpdateData,100); - memset(UpdateData,0x00,sizeof(UpdateData)); - } - print_info("Update END!!! file Size = %d\n",thisSize); + UpdateData[99] = tmp; + tcflush(fd,TCIFLUSH); + WriteToUart((const char*)UpdateData,100); + return 0; + }else{ + return -1; } - free(buffer); - ZigbeeInit(); - offSize = 0; - LOG_INFO("UpdateWirelessNode success"); + +} +void Uart::UpdateWirelessNodeTime(unsigned char* pDestShortAddr,int modifyaddr/*,int nodewaveindex,int nodetime,int nodeindex*/) +{ + if(modifyaddr) + modify_DistAddr(pDestShortAddr); + usleep(10000); + //print_info("nodewaveindex = %d,nodetime = %d,nodeindex = %d\n",nodewaveindex,nodetime,nodeindex); + char localtimestamp[32]={0x00}; + int millisecond = 0; + + string rtcTime = GetRTC(localtimestamp,millisecond); + LOG_INFO("ShortAddr = %02x%02x,rtcTime = %s,localtimestamp = %s,millisecond = %d,bSendTimeStamp = %d \n",pDestShortAddr[0],pDestShortAddr[1],rtcTime.c_str(),localtimestamp,millisecond,bSendTimeStamp); + // struct timeval tv; + // gettimeofday(&tv, NULL); + // int millisecond = tv.tv_usec / 1000; + + // sprintf(localtimestamp, "%ld", tv.tv_sec); + + unsigned char UpdateData[100]={0x00}; + UpdateData[0]=0xAA; + UpdateData[1]=0x55; + UpdateData[2]=0xAA; + UpdateData[3]=pDestShortAddr[0]; + UpdateData[4]=pDestShortAddr[1]; + UpdateData[5]=0x23; + UpdateData[6]=0x00; + UpdateData[7]=0x00; + UpdateData[8]=UINT32_LOW_2(atol(localtimestamp)); + UpdateData[9]=UINT32_LOW_1(atol(localtimestamp)); + UpdateData[10]=UINT32_HIGH_2(atol(localtimestamp)); + UpdateData[11]=UINT32_HIGH_1(atol(localtimestamp)); + UpdateData[12]=UINT16_LOW(millisecond); + UpdateData[13]=UINT16_HIGH(millisecond); + //UpdateData[13]=UINT16_HIGH(nodetime); + //UpdateData[14]=UINT16_LOW(nodetime); + //UpdateData[15]=UINT16_LOW(nodewaveindex); + //UpdateData[16]=UINT16_LOW(nodeindex); + unsigned char tmp = 0x00; + for(int k = 0; k < 99;k++){ + tmp += UpdateData[k]; + } + UpdateData[99] = tmp; + WriteToUart((const char*)UpdateData,100); } void Uart::DealRecvData(const char *pData) { @@ -421,7 +1414,7 @@ void Uart::DealRecvData(const char *pData) sprintf(buf, "%02d", pData[5]&0xFF); sprintf(shortAdd, "%02x%02x", pData[3]&0xFF,pData[4]&0xFF); unsigned short ushortAdd = BUILD_UINT16(pData[3]&0xFF,pData[4]&0xFF); - int flag = boost::lexical_cast(buf); + int flag = atoi(buf); print_info("the data package type(1,2,3,4,5,6) is %s,%x\n",buf,pData[5]&0xFF); switch (flag) @@ -434,7 +1427,7 @@ void Uart::DealRecvData(const char *pData) DealDataNodeFeature(pData, 0); } break; - case 3:{//0x03:长波形X轴 +/* case 3:{//0x03:长波形X轴 DealDataNodeWave(pData); } break; @@ -445,22 +1438,63 @@ void Uart::DealRecvData(const char *pData) case 5:{//0x05:长波形Z轴 DealDataNodeWave(pData); } - break; + break;*/ case 6:{//0x06:特征值+长波形 + //LOG_INFO("DealDataNodeFeature 06"); DealDataNodeFeature(pData, 1); } break; - case 7:{//0x07:升级 + case 32:{//升级 UpdateWirelessNode(ushortAdd); } break; + case 7:{ + DealDataNodeName(pData); + } + break; default: break; } } +void Uart::DealDataNodeName(const char* pData) +{ + bSendTimeStamp = false; + string strTime = GetLocalTimeWithMs(); + //LOG_INFO("DealDataNodeName Time = %s\n",strTime.c_str()); + unsigned char shortAdd[8]={0x00}; + char NodeName[64]={0x00}; + memcpy(shortAdd,&pData[3],2); + memcpy(NodeName,&pData[7],64); + //DealNodeSendTime((unsigned char*)shortAdd); + UpdateWirelessNodeTime((unsigned char*)shortAdd,1); + + for(int i = 0; i < 64;i++){ + sprintf(&NodeName[i * 2], "%02X", pData[7 + i]&0xFF); + } + + char gbkNodeName[128]={0x00}; + std::string strNodeName(NodeName); + print_info("strNodeName = %s\n",strNodeName.c_str()); + solve(gbkNodeName,NodeName); + print_info("gbkNodeName = %s\n",gbkNodeName); + string utfNodeName = GBKToUTF8(gbkNodeName); + print_info("utfNodeName = %s\n",utfNodeName.c_str()); + //LOG_INFO("gbkNodeName:%s \n",gbkNodeName); + //LOG_INFO("utfNodeName:%s \n",utfNodeName.c_str()); + unsigned short ushortAdd = BUILD_UINT16(pData[3]&0xFF,pData[4]&0xFF); + char whereCon[64] = { 0 }; + char uplCon[200]={0x00}; + sprintf(whereCon, "zigbeeShortAddr='%02x%02x'", shortAdd[0],shortAdd[1]); + print_info("whereCon = %s\n",whereCon); + sprintf(uplCon,"dataNodeName = '%s'",gbkNodeName); + int iRet = sql_ctl->UpdateTableData(T_SENSOR_INFO(TNAME),uplCon,whereCon,0); + string strData = sql_ctl->GetNodeConfigureInfor(whereCon); + iRet = data_publish(strData.c_str(), GlobalConfig::Topic_G.mPubConfig.c_str()); + +} void Uart::DealDataNodeInfo(const char *pData) { print_info("recv remote zigbee module info\n"); @@ -468,12 +1502,12 @@ void Uart::DealDataNodeInfo(const char *pData) char buf[32] = {0}; char chTemp = pRecvData->Data[0];//设备状态标志 1 byte DataNodeInfo dataNodeInfo; - dataNodeInfo.EquipSta = boost::lexical_cast(chTemp >> 2 & 0x1); - dataNodeInfo.TemTopFlag = boost::lexical_cast(chTemp >> 3 & 0x1); - dataNodeInfo.TemBotFlag = boost::lexical_cast(chTemp >> 4 & 0x1); - dataNodeInfo.ZigbeeFlag = boost::lexical_cast(chTemp >> 5 & 0x1); - dataNodeInfo.AccFlag = boost::lexical_cast(chTemp >> 6 & 0x1); - dataNodeInfo.InitFlag = boost::lexical_cast(chTemp >> 7 & 0x1); + dataNodeInfo.EquipSta = GET_BIT(chTemp, 2 ); + dataNodeInfo.TemTopFlag = GET_BIT(chTemp, 3 ); + dataNodeInfo.TemBotFlag = GET_BIT(chTemp , 4); + dataNodeInfo.ZigbeeFlag = GET_BIT(chTemp , 5); + dataNodeInfo.AccFlag = GET_BIT(chTemp ,6); + dataNodeInfo.InitFlag = GET_BIT(chTemp ,7); sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x", pRecvData->Data[1], pRecvData->Data[2], pRecvData->Data[3], pRecvData->Data[4], pRecvData->Data[5], pRecvData->Data[6], pRecvData->Data[7],pRecvData->Data[8]); @@ -481,10 +1515,9 @@ void Uart::DealDataNodeInfo(const char *pData) chTemp = pRecvData->Data[9];//硬件版本 1 byte memset(buf, 0, 32); - sprintf(buf, "%02x", chTemp); + sprintf(buf, "%.1f", 0.1*chTemp); dataNodeInfo.HardVersion = std::string(buf); - chTemp = pRecvData->Data[10];//软件版本 1 byte memset(buf, 0, 32); //sprintf(buf, "%02x", chTemp); @@ -507,17 +1540,17 @@ void Uart::DealDataNodeInfo(const char *pData) memset(buf, 0, 32); sprintf(buf, "%d", BUILD_UINT32(pRecvData->Data[23], pRecvData->Data[24], pRecvData->Data[25], pRecvData->Data[26])); - dataNodeInfo.WakeupTime = boost::lexical_cast(buf);//唤醒次数 4 byte + dataNodeInfo.WakeupTime = atoi(buf);//唤醒次数 4 byte printf("WakeupTime = %d\n",dataNodeInfo.WakeupTime); memset(buf, 0, 32); sprintf(buf, "%d", BUILD_UINT32(pRecvData->Data[27], pRecvData->Data[28], pRecvData->Data[29], pRecvData->Data[30])); - dataNodeInfo.StaticTime = boost::lexical_cast(buf);//特征值发送次数 4 byte + dataNodeInfo.StaticTime = atoi(buf);//特征值发送次数 4 byte printf("StaticTime = %d\n",dataNodeInfo.StaticTime); memset(buf, 0, 32); // sprintf(buf, "%d", BUILD_UINT32(pRecvData->Data[31], pRecvData->Data[32], pRecvData->Data[33], pRecvData->Data[34])); dataNodeInfo.WaveTime = BUILD_UINT32(pRecvData->Data[31], pRecvData->Data[32], pRecvData->Data[33], pRecvData->Data[34]);//原始波形发送次数 4 byte - printf("dataNodeInfo.WaveTime = %d\n",dataNodeInfo.WaveTime); + memset(buf, 0, 32); // sprintf(buf, "%02x%02x", pRecvData->Data[35], pRecvData->Data[36]); dataNodeInfo.BateryV = BUILD_UINT16(pRecvData->Data[35],pRecvData->Data[36]);//电池电压 2 byte @@ -530,23 +1563,21 @@ void Uart::DealDataNodeInfo(const char *pData) chTemp = pRecvData->Data[38]; memset(buf, 0, 32); sprintf(buf, "%d", chTemp); - dataNodeInfo.RSSI = boost::lexical_cast(buf); //无线信号强度 1 byte + dataNodeInfo.RSSI = atoi(buf); //无线信号强度 1 byte chTemp = pRecvData->Data[39]; memset(buf, 0, 32); sprintf(buf, "%02x", chTemp); dataNodeInfo.ConfigFlag = ((0 == std::string(buf).compare("aa")) ? 1 : 0); //配置标志 1 byte - memset(buf, 0, 32); - sprintf(buf, "%u%u", pRecvData->Data[40], pRecvData->Data[41]); - dataNodeInfo.FeatureInterVal = boost::lexical_cast(buf); //唤醒周期 2 byte - - chTemp = pRecvData->Data[42]; + chTemp = pRecvData->Data[40]; memset(buf, 0, 32); - // sprintf(buf, "%02x", chTemp); - sprintf(buf, "%d",(unsigned int)chTemp); // yxq - dataNodeInfo.WaveInterVal = boost::lexical_cast(buf);//原始波形发送周期 2 byte - printf("====WaveInterVal = %s\n",buf); + sprintf(buf, "%d", chTemp); + dataNodeInfo.FeatureInterVal = atoi(buf); //唤醒周期 1 byte + memset(buf, 0, 32); + // yxq + sprintf(buf, "%u%u", pRecvData->Data[41],pRecvData->Data[42]); + dataNodeInfo.WaveInterVal = atoi(buf);//原始波形发送周期 2 byte memset(buf, 0, 32); sprintf(buf, "%02x%02x", pRecvData->Data[43], pRecvData->Data[44]); //Zigbee PID 2 byte dataNodeInfo.ZigbeePanId = std::string(buf); @@ -554,36 +1585,82 @@ void Uart::DealDataNodeInfo(const char *pData) chTemp = pRecvData->Data[45]; memset(buf, 0, 32); sprintf(buf, "%d", chTemp); - dataNodeInfo.ZigbeeChannel = boost::lexical_cast(buf);//Zigbee 信道 1 byte + dataNodeInfo.ZigbeeChannel = atoi(buf);//Zigbee 信道 1 byte memset(buf, 0, 32); sprintf(buf, "%02x%02x", pRecvData->Data[46], pRecvData->Data[47]);//Zigbee 本地地址 2 byte - dataNodeInfo.ZigbeeShortAddr = std::string(buf); + dataNodeInfo.ZigbeeShortAddr = std::string(buf); + unsigned char shortAddr[2] = {0x00}; + memcpy(shortAddr,(unsigned char*)&pRecvData->Data[46],2); + modify_DistAddr(shortAddr);//修改目标地址 + string strTime = GetLocalTimeWithMs(); + //LOG_INFO("DealDataNodeInfo modify_DistAddr Time = %s\n",strTime.c_str()); + + //LOG_INFO("ZigbeeShortAddr = %s,SoftVersion = %s\n",dataNodeInfo.ZigbeeShortAddr.c_str(),dataNodeInfo.SoftVersion.c_str()); memset(buf, 0, 32); sprintf(buf, "%02x%02x", pRecvData->Data[48], pRecvData->Data[49]);//Zigbee 目标地址 2 byte dataNodeInfo.ZigbeeDesAddr = std::string(buf); + //print_info("ZigbeeDesAddr = %s\n",buf); //50 51 52=》序号23 zigbee重试间隔 memset(buf, 0, 32); sprintf(buf, "%02x", pRecvData->Data[50]);//Zigbee 发射功率 1 byte - dataNodeInfo.ZigbeePower = boost::lexical_cast(buf); + dataNodeInfo.ZigbeePower = atoi(buf); + //print_info("ZigbeePower = %s\n",buf); memset(buf, 0, 32); sprintf(buf, "%d", BUILD_UINT16(00,pRecvData->Data[51]));//Zigbee 重试次数 1 byte - dataNodeInfo.ZigbeeRetry = boost::lexical_cast(buf); + dataNodeInfo.ZigbeeRetry = atoi(buf); + //print_info("ZigbeeRetry = %s\n",buf); memset(buf, 0, 32); - sprintf(buf, "%02x", pRecvData->Data[52]);//Zigbee 重试间隔 1 byte - dataNodeInfo.ZigbeeRetryGap = boost::lexical_cast(buf); + sprintf(buf, "%d", BUILD_UINT16(00,pRecvData->Data[52]));//Zigbee 重试间隔 1 byte + dataNodeInfo.ZigbeeRetryGap = atoi(buf); + //print_info("ZigbeeRetryGap = %s\n",buf); - chTemp = pRecvData->Data[53]; - dataNodeInfo.Range = boost::lexical_cast(chTemp >> 2 & 0x3); - dataNodeInfo.SamplingRate = boost::lexical_cast(chTemp & 0x3); + + if(dataNodeInfo.ProductNo == "01"){ + chTemp = pRecvData->Data[53]; + unsigned char range = (chTemp >> 2) & 0x3; + dataNodeInfo.Range = range; + int SamplingRate = (chTemp & 0x3); + print_info("SamplingRate = %d\n",SamplingRate); + if(SamplingRate == 0){ + dataNodeInfo.SamplingRate = 3200; + }else if(SamplingRate == 1){ + dataNodeInfo.SamplingRate = 6400; + }else if(SamplingRate == 2){ + dataNodeInfo.SamplingRate = 12800; + }else if(SamplingRate == 3){ + dataNodeInfo.SamplingRate = 25600; + } + }else if(dataNodeInfo.ProductNo == "02"){ + chTemp = pRecvData->Data[53]; + unsigned char range = (chTemp >> 3) & 0x7; + dataNodeInfo.Range = range; + int SamplingRate = (chTemp & 0x7); + print_info("SamplingRate = %d\n",SamplingRate); + if(SamplingRate == 0){ + dataNodeInfo.SamplingRate = 8000; + }else if(SamplingRate == 1){ + dataNodeInfo.SamplingRate = 16000; + }else if(SamplingRate == 2){ + dataNodeInfo.SamplingRate = 24000; + }else if(SamplingRate == 3){ + dataNodeInfo.SamplingRate = 32000; + }else if(SamplingRate == 4){ + dataNodeInfo.SamplingRate = 48000; + }else if(SamplingRate == 5){ + dataNodeInfo.SamplingRate = 96000; + }else if(SamplingRate == 6){ + dataNodeInfo.SamplingRate = 192000; + } + } // 54=》序号25 ACC采样时间 memset(buf, 0, 32); - sprintf(buf, "%02x", pRecvData->Data[54]);//ACC 采样时间 1 byte - dataNodeInfo.ACCSampleTime = boost::lexical_cast(buf); + sprintf(buf, "%u", pRecvData->Data[54]);//ACC 采样时间 1 byte + dataNodeInfo.ACCSampleTime = atoi(buf); int iTemp = 0; //使用了55 56 59 60 63 64 67 68 71 72 @@ -593,9 +1670,9 @@ void Uart::DealDataNodeInfo(const char *pData) iTemp = (int)strtol(buf, NULL, 16); if (0 == i) { - dataNodeInfo.StartBrands = boost::lexical_cast(iTemp); + dataNodeInfo.StartBrands = to_string(iTemp); } else { - dataNodeInfo.StartBrands += ("," + boost::lexical_cast(iTemp)); + dataNodeInfo.StartBrands += ("," + to_string(iTemp)); } } //使用了57 58 61 62 65 66 69 70 73 74 @@ -604,9 +1681,9 @@ void Uart::DealDataNodeInfo(const char *pData) sprintf(buf, "%02x%02x", pRecvData->Data[57 + j * 4], pRecvData->Data[57 + j * 4 + 1]); iTemp = (int)strtol(buf, NULL, 16); if (0 == j) { - dataNodeInfo.StopBrands = boost::lexical_cast(iTemp); + dataNodeInfo.StopBrands = to_string(iTemp); } else { - dataNodeInfo.StopBrands += ("," + boost::lexical_cast(iTemp)); + dataNodeInfo.StopBrands += ("," + to_string(iTemp)); } } @@ -614,13 +1691,13 @@ void Uart::DealDataNodeInfo(const char *pData) memset(buf, 0, 32); sprintf(buf, "%02x%02x", pRecvData->Data[75], pRecvData->Data[76]); iTemp = (int)strtol(buf, NULL, 16); - dataNodeInfo.EnvelopeBandPass = boost::lexical_cast(iTemp); + dataNodeInfo.EnvelopeBandPass = to_string(iTemp); memset(buf, 0, 32); sprintf(buf, "%02x%02x", pRecvData->Data[77], pRecvData->Data[78]); iTemp = (int)strtol(buf, NULL, 16); - dataNodeInfo.EnvelopeBandPass += ("," + boost::lexical_cast(iTemp)); + dataNodeInfo.EnvelopeBandPass += ("," + to_string(iTemp)); //使用了79 80 81 82 83 84 85 86 for (int j = 0; j < 4; j++) { memset(buf, 0, 32); @@ -628,43 +1705,63 @@ void Uart::DealDataNodeInfo(const char *pData) iTemp = (int)strtol(buf, NULL, 16); if (0 == j) { - dataNodeInfo.FaultFrequency = boost::lexical_cast(iTemp); + dataNodeInfo.FaultFrequency = to_string(iTemp); } else { - dataNodeInfo.FaultFrequency += ("," + boost::lexical_cast(iTemp)); + dataNodeInfo.FaultFrequency += ("," + to_string(iTemp)); } } memset(buf, 0, 32); sprintf(buf, "%02x%02x%02x%02x", pRecvData->Data[87], pRecvData->Data[88], pRecvData->Data[89],pRecvData->Data[90]); long lTimeStamp = strtol(buf, NULL, 16); - dataNodeInfo.ConfigDate = boost::lexical_cast(lTimeStamp); + dataNodeInfo.ConfigDate = to_string(lTimeStamp); chTemp = pRecvData->Data[91]; memset(buf, 0, 32); sprintf(buf, "%d", chTemp); - dataNodeInfo.VIntegralFilterFrequency = boost::lexical_cast(buf); + dataNodeInfo.VIntegralFilterFrequency = atoi(buf); char whereCon[64] = {0}; sprintf(whereCon, "dataNodeNo='%s'", dataNodeInfo.ZigbeeLongAddr.c_str()); if (sql_ctl->GetTableRows(T_SENSOR_INFO(TNAME), whereCon) > 0) { - sql_ctl->DeleteTableData(T_SENSOR_INFO(TNAME), whereCon); - } - char insertSql[1024] = { 0 }; - sprintf(insertSql, "'%s','%s','%d','%d','%d','%d','%d','%d',\ - '%s','%s','%s','%s','%s','%d',\ - '%d','%d','%d','%s','%d','%s',\ - '%s','%u','%d','%d','%s','%d','%s','%s',\ - '%s','%d','%s','%s','%s',\ - '%d','%d','%d','%d','%s','%s','%d','%d'", - dataNodeInfo.ZigbeeLongAddr.c_str(), " ", dataNodeInfo.InitFlag, dataNodeInfo.AccFlag, dataNodeInfo.ZigbeeFlag, dataNodeInfo.TemTopFlag, dataNodeInfo.TemBotFlag,dataNodeInfo.EquipSta,\ - dataNodeInfo.HardVersion.c_str(), dataNodeInfo.SoftVersion.c_str(), dataNodeInfo.BpNo.c_str(), dataNodeInfo.SerialNo.c_str(), dataNodeInfo.FirstPowerTime.c_str(), dataNodeInfo.WakeupTime,\ - dataNodeInfo.StaticTime,dataNodeInfo.WaveTime,dataNodeInfo.BateryV,dataNodeInfo.ProductNo.c_str(),dataNodeInfo.ConfigFlag, dataNodeInfo.StartBrands.c_str(), \ - dataNodeInfo.StopBrands.c_str(), dataNodeInfo.FeatureInterVal, dataNodeInfo.WaveInterVal, dataNodeInfo.SamplingRate,"",dataNodeInfo.Range, dataNodeInfo.EnvelopeBandPass.c_str(), dataNodeInfo.FaultFrequency.c_str(),\ - dataNodeInfo.ZigbeePanId.c_str(), dataNodeInfo.ZigbeeChannel, dataNodeInfo.ZigbeeShortAddr.c_str(), dataNodeInfo.ZigbeeLongAddr.c_str(), dataNodeInfo.ZigbeeDesAddr.c_str(), \ - dataNodeInfo.ZigbeePower,dataNodeInfo.ZigbeeRetry,dataNodeInfo.ZigbeeRetryGap,dataNodeInfo.ACCSampleTime,"1", dataNodeInfo.ConfigDate.c_str(),dataNodeInfo.VIntegralFilterFrequency,dataNodeInfo.RSSI); - sql_ctl->InsertData(T_SENSOR_INFO(TNAME), insertSql); - printf("=======insertSql======== %s\n",insertSql); + char updateSql[1024] = { 0 }; + sprintf(updateSql, " initFlag = '%d',accFlag = '%d',zigbeeFlag = '%d',temTopFlag = '%d',temBotFlag = '%d',equipSta = '%d',\ + hardVersion = '%s',softVersion = '%s',bpNo = '%s',serialNo = '%s',firstPowerTime = '%s',WakeupTime = '%d',\ + StaticTime = '%d',WaveTime = '%d',BateryV = '%d',ProductNo = '%s',configFlag = '%d',startBrands = '%s',\ + stopBrands = '%s',featureInterVal = '%u',waveInterVal = '%d',samplingRate = '%d',scope = '%s',range = '%d',envelopeBandPass = '%s',faultFrequency = '%s',\ + zigbeePanId = '%s',zigbeeChannel = '%d',zigbeeShortAddr = '%s',zigbeeLongAddr = '%s',zigbeeDesAddr = '%s',\ + ZigbeePower = '%d',ZigbeeRetry = '%d',ZigbeeRetryGap = '%d',ACCSampleTime = '%d',status = '%s',timeStamp = '%s',viff = '%d',RSSI = '%d',UpdateFlag = 1", + dataNodeInfo.InitFlag, dataNodeInfo.AccFlag, dataNodeInfo.ZigbeeFlag, dataNodeInfo.TemTopFlag, dataNodeInfo.TemBotFlag,dataNodeInfo.EquipSta,\ + dataNodeInfo.HardVersion.c_str(), dataNodeInfo.SoftVersion.c_str(), dataNodeInfo.BpNo.c_str(), dataNodeInfo.SerialNo.c_str(), dataNodeInfo.FirstPowerTime.c_str(), dataNodeInfo.WakeupTime,\ + dataNodeInfo.StaticTime,dataNodeInfo.WaveTime,dataNodeInfo.BateryV,dataNodeInfo.ProductNo.c_str(),dataNodeInfo.ConfigFlag, dataNodeInfo.StartBrands.c_str(), \ + dataNodeInfo.StopBrands.c_str(), dataNodeInfo.FeatureInterVal, dataNodeInfo.WaveInterVal, dataNodeInfo.SamplingRate,"",dataNodeInfo.Range, dataNodeInfo.EnvelopeBandPass.c_str(), dataNodeInfo.FaultFrequency.c_str(),\ + dataNodeInfo.ZigbeePanId.c_str(), dataNodeInfo.ZigbeeChannel, dataNodeInfo.ZigbeeShortAddr.c_str(), dataNodeInfo.ZigbeeLongAddr.c_str(), dataNodeInfo.ZigbeeDesAddr.c_str(), \ + dataNodeInfo.ZigbeePower,dataNodeInfo.ZigbeeRetry,dataNodeInfo.ZigbeeRetryGap,dataNodeInfo.ACCSampleTime,"1", dataNodeInfo.ConfigDate.c_str(),dataNodeInfo.VIntegralFilterFrequency,dataNodeInfo.RSSI); + sprintf(whereCon,"dataNodeNo = '%s'",dataNodeInfo.ZigbeeLongAddr.c_str()); + sql_ctl->UpdateTableData(T_SENSOR_INFO(TNAME), updateSql, whereCon); + }else{ + char insertSql[1024] = { 0 }; + sprintf(insertSql, " '%s','%s','%d','%d','%d','%d','%d','%d',\ + '%s','%s','%s','%s','%s','%d',\ + '%d','%d','%d','%s','%d','%s',\ + '%s','%u','%d','%d','%s','%d', '%s', '%s',\ + '%s','%d','%s','%s','%s',\ + '%d','%d','%d','%d','%s','%s', '%d', '%d','1','0',''", + dataNodeInfo.ZigbeeLongAddr.c_str(), " ", dataNodeInfo.InitFlag, dataNodeInfo.AccFlag, dataNodeInfo.ZigbeeFlag, dataNodeInfo.TemTopFlag, dataNodeInfo.TemBotFlag,dataNodeInfo.EquipSta,\ + dataNodeInfo.HardVersion.c_str(), dataNodeInfo.SoftVersion.c_str(), dataNodeInfo.BpNo.c_str(), dataNodeInfo.SerialNo.c_str(), dataNodeInfo.FirstPowerTime.c_str(), dataNodeInfo.WakeupTime,\ + dataNodeInfo.StaticTime,dataNodeInfo.WaveTime,dataNodeInfo.BateryV,dataNodeInfo.ProductNo.c_str(),dataNodeInfo.ConfigFlag, dataNodeInfo.StartBrands.c_str(), \ + dataNodeInfo.StopBrands.c_str(), dataNodeInfo.FeatureInterVal, dataNodeInfo.WaveInterVal, dataNodeInfo.SamplingRate,"",dataNodeInfo.Range, dataNodeInfo.EnvelopeBandPass.c_str(), dataNodeInfo.FaultFrequency.c_str(),\ + dataNodeInfo.ZigbeePanId.c_str(), dataNodeInfo.ZigbeeChannel, dataNodeInfo.ZigbeeShortAddr.c_str(), dataNodeInfo.ZigbeeLongAddr.c_str(), dataNodeInfo.ZigbeeDesAddr.c_str(), \ + dataNodeInfo.ZigbeePower,dataNodeInfo.ZigbeeRetry,dataNodeInfo.ZigbeeRetryGap,dataNodeInfo.ACCSampleTime,"1", dataNodeInfo.ConfigDate.c_str(),dataNodeInfo.VIntegralFilterFrequency,dataNodeInfo.RSSI); + sql_ctl->InsertData(T_SENSOR_INFO(TNAME), insertSql); + } + char szTableName[50]={0x00}; + sprintf(szTableName,"t_data_%s",dataNodeInfo.ZigbeeLongAddr.c_str()); + sql_ctl->Createtable(szTableName); + memset(szTableName,0x00,sizeof(szTableName)); + sprintf(szTableName,"t_dataStatic_%s",dataNodeInfo.ZigbeeLongAddr.c_str()); + sql_ctl->CreatedataStatictable(szTableName); Json::Value jsonVal; jsonVal.clear(); jsonVal["cmd"] = "26"; @@ -711,9 +1808,9 @@ void Uart::DealDataNodeInfo(const char *pData) Json::FastWriter showValue; std::string dataBody = showValue.write(jsBody); jsonVal["cmdBody"] = dataBody; - std::string strCmd27 = showValue.write(jsonVal); + std::string strCmd26 = showValue.write(jsonVal); //传感器发来的数据包中的表示设备信息的数据转化为json格式后,通过调用data_publish将数据传给mqttclient : Topic:wireless/cmd/60294D203717 - data_publish(strCmd27.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); + data_publish(strCmd26.c_str(), GlobalConfig::Topic_G.mPubCmd.c_str()); print_info("remote wireless sensor device info AccFlag : %d EquipSta : %d BpNo : %s ConfigFlag : %d EnvelopeBandPass : %s FaultFrequency : %s FeatureInterVal : %u FirstPowerTime : %s HardVersion : %s InitFlag : %d SamplingRate : %d range : %d SerialNo : %s\ SoftVersion : %s StartBrands : %s StopBrands : %s TemBotFlag : %d TemTopFlag : %d WaveInterVal : %d ZigbeeChannel : %d ZigbeeDesAddr : %s ZigbeeFlag : %d ZigbeeLongAddr : %s panid : %s ZigbeeShortAddr : %s Configdate : %s vintegralfilterfrequency : %d RSSI : %d \n", \ @@ -722,6 +1819,7 @@ void Uart::DealDataNodeInfo(const char *pData) dataNodeInfo.SoftVersion.c_str(), dataNodeInfo.StartBrands.c_str(), dataNodeInfo.StopBrands.c_str(), dataNodeInfo.TemBotFlag, dataNodeInfo.TemTopFlag, dataNodeInfo.WaveInterVal,\ dataNodeInfo.ZigbeeChannel, dataNodeInfo.ZigbeeDesAddr.c_str(), dataNodeInfo.ZigbeeFlag, dataNodeInfo.ZigbeeLongAddr.c_str(), dataNodeInfo.ZigbeePanId.c_str(), dataNodeInfo.ZigbeeShortAddr.c_str(), dataNodeInfo.ConfigDate.c_str(), dataNodeInfo.VIntegralFilterFrequency, dataNodeInfo.RSSI); + } @@ -729,50 +1827,91 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) { print_info("recv feature\n"); RecvData * pRecvData = (RecvData *)pData; - - char buf[8]; + char whereCon[1024] = {0}; + char updateSql[1024] = { 0 }; + char buf[20] = {0x00}; + int nodeResend = 0; sprintf(buf, "%02x%02x", pRecvData->ShortAddr[0], pRecvData->ShortAddr[1]); - LOG_INFO("DealDataNodeFeature %02x%02x\n",pRecvData->ShortAddr[0], pRecvData->ShortAddr[1]); + //LOG_INFO("DealDataNodeFeature %02x%02x\n",pRecvData->ShortAddr[0], pRecvData->ShortAddr[1]); std::string strShortAddr = std::string(buf); print_info("zigbeeShortAddr='%s'\n", strShortAddr.c_str()); - if (1 == flag) { - print_info("recv wave minute\n"); - unsigned short localAddr = 0x9999; - bool bUpdate = ReadUpdatePackge(pRecvData->ShortAddr); - if(!bUpdate){ - GlobalConfig::ZigbeeInfo_G.MyAddr = "9999"; - WriteShortAddr2Zigbee(localAddr); - } -/* bool bUpdate = ReadUpdatePackge(pRecvData->ShortAddr,buf); - if(bUpdate){ - WriteShortAddr_DistAddr2Zigbee(shortAddr,buf); - }else{ - WriteShortAddr2Zigbee(shortAddr); - }*/ -// LOG_INFO("[DealDataNodeFeature] ZigBee PanID: %s ; Channel: %d ; MyAddr : %4x ",GlobalConfig::ZigbeeInfo_G.PanID.c_str(),GlobalConfig::ZigbeeInfo_G.Channel, -// (unsigned short)GlobalConfig::Zigbee_G.MyAddr); - - // 进入传输原始数据状态,启动计数 60秒 - GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = ENTER_TRANSMITTING_STATUS; - GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; - } - - - char getLongAddr_sql[32] = { 0 }; + char getLongAddr_sql[32] = { 0 }; //根据数据包中的传感器的短地址获取数据库中长地址(MAC),在下面判断该传感器是否存在,如果不存在则把数据包丢弃 - sprintf(getLongAddr_sql, "zigbeeShortAddr='%s'", strShortAddr.c_str()); - std::string strLongAddr = sql_ctl->GetData(T_SENSOR_INFO(TNAME), T_SENSOR_INFO(ZIGBEELONGADDR), getLongAddr_sql); - print_info("--------->the remote sensor short addr:%s strLongAddr=%s\n",buf,strLongAddr.c_str()); + sprintf(getLongAddr_sql, "zigbeeShortAddr='%s'", strShortAddr.c_str()); + //std::string strLongAddr = sql_ctl->GetData(T_SENSOR_INFO(TNAME), T_SENSOR_INFO(ZIGBEELONGADDR), getLongAddr_sql); + vec_t vecResult = sql_ctl->GetDataSingleLine(T_SENSOR_INFO(TNAME)," softVersion,zigbeeLongAddr ",getLongAddr_sql); - if (0 == strLongAddr.length()) { - print_error("device info not found\n"); - return; + if (vecResult.size() < 1) { + LOG_ERROR("device info not found %02x%02x\n",pRecvData->ShortAddr[0], pRecvData->ShortAddr[1]); + print_error("device info not found\n"); + return; + } + print_info("--------->the remote sensor short addr:%s strLongAddr=%s,softVersion = %s\n",buf,vecResult[1].c_str(),vecResult[0].c_str()); + + std::string strLongAddr = vecResult[1]; + if (1 == flag) { + + tcflush(fd,TCIOFLUSH); + + if (!bSendTimeStamp) + { + bSendTimeStamp = true; + modify_distaddr_info(0x9999,"",pRecvData->ShortAddr);//临时参数配置 + usleep(10000); + UpdateWirelessNodeTime((unsigned char*)pRecvData->ShortAddr,0); + }else + { + return; + } + + //modify_distaddr_info(0x9999,"",pRecvData->ShortAddr);//临时参数配置 + + GlobalConfig::ZigbeeInfo_G.MyAddr = "9999"; + GlobalConfig::Zigbee_G.MyAddr = 0x9999; + string strTime = GetLocalTimeWithMs(); + + m_strDestShortAddr = std::string(buf); + + bool isUpdate = ReadUpdatePackge(pRecvData->ShortAddr); + bUpdatePre = isUpdate; + if(!isUpdate){ + int iRet = UpdateConfig(pRecvData->ShortAddr); + } + if(isUpdate || bUpdateconfig){ + + }else{ + LOG_DEBUG("DealDataNodeFeature %02x%02x,localaddr %02x%02x \n",pRecvData->ShortAddr[0], pRecvData->ShortAddr[1],\ + UINT16_HIGH(GlobalConfig::Zigbee_G.MyAddr),UINT16_LOW(GlobalConfig::Zigbee_G.MyAddr)); + // 进入传输原始数据状态,启动计数 60秒 + GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = ENTER_TRANSMITTING_STATUS; + GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; + } + + }else{ + memset(whereCon,0x00,sizeof(whereCon)); + memset(updateSql,0x00,sizeof(updateSql)); + sprintf(whereCon, "zigbeeShortAddr='%s'", strShortAddr.c_str()); + sprintf(updateSql, " StaticTime = StaticTime + 1"); + sql_ctl->UpdateTableData(T_SENSOR_INFO(TNAME), updateSql, whereCon); + //string strData = sql_ctl->GetNodeConfigureInfor(whereCon); + //data_publish(strData.c_str(), GlobalConfig::Topic_G.mPubConfig.c_str()); } - + + if (vecResult[0] == "3.0" || vecResult[0] == "4.0"){ + return; + } + long staticIndex = BUILD_UINT32(pRecvData->Data[29], pRecvData->Data[28],pRecvData->Data[27], pRecvData->Data[26]); + + print_info("staticIndex = %d\n",staticIndex); + + + //LOG_INFO("staticIndex = %d\n",staticIndex); + char localtimestamp[32] = { 0 }; GetTimeNet(localtimestamp, 1); - std::string nowTimetamp = std::string(localtimestamp); + std::string nowTimetamp = std::string(localtimestamp); + strTimetamp = nowTimetamp; int iTemp = 0; unsigned char highbit = 0; @@ -780,49 +1919,165 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) float n = 0; DataRecvStatic dataStatic; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[5], pRecvData->Data[4]); print_blue("!!!!!!!!!!!!!!!!!!!!!!%s\n",buf); iTemp = (int)strtol(buf, NULL, 16); dataStatic.Dip = iTemp; - memset(buf, 0, 8); + int fTemp = 0; + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[1], pRecvData->Data[0]); print_blue("@@@@@@@@@@@@@@@@@%s\n",buf); iTemp = (int)strtol(buf, NULL, 16); - dataStatic.TemBot = iTemp * 0.0625;//设备温度 + if (iTemp < 0x8000) { + fTemp = iTemp ; + } else { + fTemp = (((~iTemp)&0xffff) + 1)* (-1); + } + dataStatic.TemBot = fTemp * 0.0625;//设备温度 - memset(buf, 0, 8); + fTemp = 0; + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[3], pRecvData->Data[2]); iTemp = (int)strtol(buf, NULL, 16); - dataStatic.TemTop = iTemp * 0.0625;//环境温度 + if (iTemp < 0x8000) { + fTemp = iTemp ; + } else { + fTemp = (((~iTemp)&0xffff) + 1) * (-1); + } + dataStatic.TemTop = fTemp * 0.0625;//环境温度 - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[7], pRecvData->Data[6]); iTemp = (int)strtol(buf, NULL, 16); dataStatic.Voltage = iTemp; + char szTableName[50]={0x00},szTableNameStatic[50]={0x00},szTableNameData[50]={0x00}; + sprintf(szTableName,"t_dataStatic_%s",strLongAddr.c_str()); + memcpy(szTableNameStatic,szTableName,sizeof(szTableNameStatic)); + memset(whereCon,0x00,sizeof(whereCon)); + + sprintf(whereCon,"StaticIndex = %d",staticIndex); + int count = sql_ctl->GetTableRows(szTableNameStatic, whereCon);//避免重复数据 + + sprintf(szTableNameData,"t_data_%s",strLongAddr.c_str()); + + int count2 = sql_ctl->GetTableRows(szTableNameData, whereCon); + if(count > 0 || count2 > 0){ + char logInfo[20]={0x00}; + sprintf(logInfo,"ShortAddr = %s,staticIndex = %d,staticData = %d, data = %d",strShortAddr.c_str(),staticIndex,count,count2); + LOG_DEBUG(logInfo); + return; + } + memset(whereCon,0x00,sizeof(whereCon)); + + ///////////////////////////////////////////////////////////// for V2.0.3 upgrade to V3.0 + std::string strTmp = ""; + char sztmp[100]={0x00}; + strTmp = "name = '" + string(szTableNameStatic)+ "' and sql LIKE '%nodeResend%' "; + + int row = sql_ctl->GetTableRows(" sqlite_master ",strTmp.c_str()); + print_info("row1 = %d\n",row); + if(row == 0){ + memset(sztmp,0x00,sizeof(sztmp)); + sprintf(sztmp,"ALTER TABLE %s ADD COLUMN 'nodeResend'",szTableNameStatic); + sql_ctl->CreateTable(sztmp); + } + // strTmp = "name = '" + string(szTableNameStatic)+ "' and sql LIKE '%zigbeeRSSIType%' "; + // row = sql_ctl->GetTableRows(" sqlite_master ",strTmp.c_str()); + // print_info("row2 = %d\n",row); + // if(row == 0){ + // memset(sztmp,0x00,sizeof(sztmp)); + // sprintf(sztmp,"ALTER TABLE %s ADD COLUMN 'zigbeeRSSIType'",szTableNameStatic); + // sql_ctl->CreateTable(sztmp); + // } + strTmp = "name = '" + string(szTableNameData)+ "' and sql LIKE '%nodeResend%' "; + row = sql_ctl->GetTableRows(" sqlite_master ",strTmp.c_str()); + print_info("row2 = %d\n",row); + if(row == 0){ + memset(sztmp,0x00,sizeof(sztmp)); + sprintf(sztmp,"ALTER TABLE %s ADD COLUMN 'nodeResend'",szTableNameData); + sql_ctl->CreateTable(sztmp); + } + + //////////////////////////////////////////////////////////// + std::string strStaticIndex = sql_ctl->GetData(szTableNameStatic, "StaticIndex", "StaticIndex > 0 order by StaticIndex desc LIMIT 0 , 1"); + // if(abs(atol(strStaticIndex.c_str()) - staticIndex) > 100){ + // sql_ctl->Deletetable(szTableNameStatic); + // sql_ctl->Deletetable(szTableNameData); + // LOG_INFO("staticIndexNOW = %d,strStaticIndexLast = %s\n",staticIndex,strStaticIndex.c_str()); + // } + + if(staticIndex != atol(strStaticIndex.c_str() + 1) && + strStaticIndex != "" && + staticIndex < atol(strStaticIndex.c_str())) + { + sprintf(whereCon,"StaticIndex = %d order by StaticIndex desc LIMIT 0 , 1",atol(strStaticIndex.c_str())); + vec_t vecResult = sql_ctl->GetDataSingleLine(szTableNameStatic, "timeStamp,StaticIndex", whereCon); + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon,"dataNodeNo = '%s'",strLongAddr.c_str()); + string staticInterval = sql_ctl->GetData(T_SENSOR_INFO(TNAME), "featureInterval", whereCon); + //LOG_INFO("vecResult0 = %s,vecResult1 = %s\n",vecResult[0].c_str(),vecResult[1].c_str()); + long nNowTimetamp = atol(vecResult[0].c_str()) - (atol(staticInterval.c_str()) * \ + (atol(vecResult[1].c_str()) - staticIndex)) * 60; + char tmp[10]={0x00}; + sprintf(tmp,"%ld",nNowTimetamp); + nowTimetamp = string(tmp); + nodeResend = 1; + //LOG_INFO("nowTimetamp = %s,strOldTime = %s\n",nowTimetamp.c_str(),vecResult[0].c_str()); + } + print_info("nowTimetamp = %s",nowTimetamp.c_str()); + // save dataStatic of 7 days + char selectCon[128] = { 0 }; + sprintf(selectCon, "channelID='%s' and sendMsg = '1' ORDER BY timeStamp ASC LIMIT 0,1",(strLongAddr + "-S").c_str()); + std::string strTime = sql_ctl->GetData(szTableName, "timeStamp", selectCon); + int Count = sql_ctl->GetTableRows(szTableName, NULL); + if(Count == -1){ + sql_ctl->CreatedataStatictable(szTableName); + } + print_info("strLongAddr = %s,strTime = %s\n",strLongAddr.c_str(),strTime.c_str()); + long lTime = atol(nowTimetamp.c_str())-atol(strTime.c_str()); + print_info("lTime = %d,OneWeek = %d\n",lTime,OneWeek); print_info("dataStatic.TemTop : %f dataStatic.TemBot : %f dataStatic.Dip :%d dataStatic.Voltage : %d\n", dataStatic.TemTop\ , dataStatic.TemBot, dataStatic.Dip, dataStatic.Voltage); - char whereCon[64] = {0}; - sprintf(whereCon, "channelID='%s'", (strLongAddr + "-S").c_str()); -// if ( 0 == sql_ctl->GetTableRows(T_DATASTATIC_INFO(TNAME), whereCon) ) { + + sprintf(updateSql, "temTop='%f',temBot='%f',dip='%d',voltage='%d',timeStamp='%s',StaticIndex = %d, nodeResend = %d",\ + dataStatic.TemTop, dataStatic.TemBot, dataStatic.Dip, dataStatic.Voltage, nowTimetamp.c_str(),staticIndex,nodeResend); + sprintf(whereCon, "channelID='%s' and sendMsg = '1'", (strLongAddr + "-S").c_str()); + if ( /*0 == sql_ctl->GetTableRows(T_DATASTATIC_INFO(TNAME), whereCon)*/ (Count * 3 < SAVE_COUNT && lTime < OneWeek ) || strTime.size() == 0 ) { print_info("insert static data to sql\n"); char insertSql[1024] = { 0 }; - sprintf(insertSql, "'%s','%s','%f','%f','%d','%d','%s'", - strLongAddr.c_str(), (strLongAddr + "-S").c_str(), dataStatic.TemTop, dataStatic.TemBot, dataStatic.Dip, dataStatic.Voltage, nowTimetamp.c_str()); - sql_ctl->InsertData(T_DATASTATIC_INFO(TNAME), insertSql); - // } else { -/* print_info("update static data to sql\n"); - char updateSql[1024] = { 0 }; - sprintf(updateSql, "temTop='%f',temBot='%f',dip='%d',voltage='%d',timeStamp='%s'",\ - dataStatic.TemTop, dataStatic.TemBot, dataStatic.Dip, dataStatic.Voltage, nowTimetamp.c_str()); - sql_ctl->UpdateTableData(T_DATASTATIC_INFO(TNAME), updateSql, whereCon); - }*/ + sprintf(insertSql, "'%s','%s','%f','%f','%d','%d','',%d,'%s','1',%d", + strLongAddr.c_str(), (strLongAddr + "-S").c_str(), dataStatic.TemTop, dataStatic.TemBot, dataStatic.Dip, dataStatic.Voltage, staticIndex,nowTimetamp.c_str(),nodeResend); + sql_ctl->InsertData(szTableName, insertSql); + if(0 == sql_ctl->GetTableRows(T_DATASTATIC_INFO(TNAME), whereCon)){ // First Connect + char insertSql[1024] = { 0 }; + sprintf(insertSql, "'%s','%s','%f','%f','%d','%d','',%d,'%s','1',%d", + strLongAddr.c_str(), (strLongAddr + "-S").c_str(), dataStatic.TemTop, dataStatic.TemBot, dataStatic.Dip, dataStatic.Voltage, staticIndex,nowTimetamp.c_str(),nodeResend); + sql_ctl->InsertData(T_DATASTATIC_INFO(TNAME), insertSql); + sql_ctl->CalculateBattery(); + } + else + sql_ctl->UpdateTableData(T_DATASTATIC_INFO(TNAME), updateSql, whereCon); + } else { + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon, "channelID='%s' and sendMsg = '1' and timeStamp = '%s'", (strLongAddr + "-S").c_str(),strTime.c_str()); + print_info("update static data to sql\n"); + sql_ctl->UpdateTableData(szTableName, updateSql, whereCon); + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon, "channelID='%s' ", (strLongAddr + "-S").c_str()); + sql_ctl->UpdateTableData(T_DATASTATIC_INFO(TNAME), updateSql, whereCon); + } + memset(szTableName,0x00,sizeof(szTableName)); + sprintf(szTableName,"t_data_%s",strLongAddr.c_str()); + if(Count == -1){ + sql_ctl->Createtable(szTableName); + } DataRecvDym dataDymX; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[9], pRecvData->Data[8]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -844,7 +2099,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymX.DiagnosisPk = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[11], pRecvData->Data[10]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -866,7 +2121,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymX.RmsValues = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[13], pRecvData->Data[12]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -888,7 +2143,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymX.IntegratPk = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[15], pRecvData->Data[14]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -910,7 +2165,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymX.IntegratRMS = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[17], pRecvData->Data[16]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -932,7 +2187,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymX.Amp1 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[19], pRecvData->Data[18]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -954,7 +2209,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymX.Amp2 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[21], pRecvData->Data[20]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -976,7 +2231,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymX.Amp3 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[23], pRecvData->Data[22]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -998,7 +2253,8 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymX.Amp4 = lowbit * n; - memset(buf, 0, 8); + + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[25], pRecvData->Data[24]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1020,133 +2276,150 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymX.Amp5 = lowbit * n; - memset(buf, 0, 8); - sprintf(buf, "%02x%02x", pRecvData->Data[27], pRecvData->Data[26]); - iTemp = (unsigned int)strtol(buf, NULL, 16); - highbit = iTemp >> 14 & 0x3; - lowbit = iTemp & 0x3fff; - switch (highbit) - { - case 0: - n = 0.0001; - break; - case 1: - n = 0.01; - break; - case 2: - n = 1; - break; - case 3: - n = 100; - break; - } - dataDymX.EnvelopEnergy = lowbit * n; + memset(buf, 0, sizeof(buf)); +// sprintf(buf, "%02x%02x", pRecvData->Data[27], pRecvData->Data[26]); +// iTemp = (unsigned int)strtol(buf, NULL, 16); +// highbit = iTemp >> 14 & 0x3; +// lowbit = iTemp & 0x3fff; +// switch (highbit) +// { +// case 0: +// n = 0.0001; +// break; +// case 1: +// n = 0.01; +// break; +// case 2: +// n = 1; +// break; +// case 3: +// n = 100; +// break; +// } +// dataDymX.EnvelopEnergy = lowbit * n; + + dataDymX.EnvelopEnergy = 0; + + memset(buf, 0, sizeof(buf)); +// sprintf(buf, "%02x%02x", pRecvData->Data[29], pRecvData->Data[28]); +// iTemp = (unsigned int)strtol(buf, NULL, 16); +// highbit = iTemp >> 14 & 0x3; +// lowbit = iTemp & 0x3fff; +// switch (highbit) +// { +// case 0: +// n = 0.0001; +// break; +// case 1: +// n = 0.01; +// break; +// case 2: +// n = 1; +// break; +// case 3: +// n = 100; +// break; +// } +// dataDymX.Phase1 = lowbit * n; + + dataDymX.Phase1 = 0; + + memset(buf, 0, sizeof(buf)); +// sprintf(buf, "%02x%02x", pRecvData->Data[31], pRecvData->Data[30]); +// iTemp = (unsigned int)strtol(buf, NULL, 16); +// highbit = iTemp >> 14 & 0x3; +// lowbit = iTemp & 0x3fff; +// switch (highbit) +// { +// case 0: +// n = 0.0001; +// break; +// case 1: +// n = 0.01; +// break; +// case 2: +// n = 1; +// break; +// case 3: +// n = 100; +// break; +// } + dataDymX.Phase2 = 0; + + memset(buf, 0, sizeof(buf)); memset(buf, 0, 8); - sprintf(buf, "%02x%02x", pRecvData->Data[29], pRecvData->Data[28]); - iTemp = (unsigned int)strtol(buf, NULL, 16); - highbit = iTemp >> 14 & 0x3; - lowbit = iTemp & 0x3fff; - switch (highbit) - { - case 0: - n = 0.0001; - break; - case 1: - n = 0.01; - break; - case 2: - n = 1; - break; - case 3: - n = 100; - break; - } - dataDymX.Phase1 = lowbit * n; +// sprintf(buf, "%02x%02x", pRecvData->Data[33], pRecvData->Data[32]); +// iTemp = (unsigned int)strtol(buf, NULL, 16); +// highbit = iTemp >> 14 & 0x3; +// lowbit = iTemp & 0x3fff; +// switch (highbit) +// { +// case 0: +// n = 0.0001; +// break; +// case 1: +// n = 0.01; +// break; +// case 2: +// n = 1; +// break; +// case 3: +// n = 100; +// break; +// } + dataDymX.Phase3 = 0; - memset(buf, 0, 8); - sprintf(buf, "%02x%02x", pRecvData->Data[31], pRecvData->Data[30]); - iTemp = (unsigned int)strtol(buf, NULL, 16); - highbit = iTemp >> 14 & 0x3; - lowbit = iTemp & 0x3fff; - switch (highbit) - { - case 0: - n = 0.0001; - break; - case 1: - n = 0.01; - break; - case 2: - n = 1; - break; - case 3: - n = 100; - break; - } - dataDymX.Phase2 = lowbit * n; - - memset(buf, 0, 8); - sprintf(buf, "%02x%02x", pRecvData->Data[33], pRecvData->Data[32]); - iTemp = (unsigned int)strtol(buf, NULL, 16); - highbit = iTemp >> 14 & 0x3; - lowbit = iTemp & 0x3fff; - switch (highbit) - { - case 0: - n = 0.0001; - break; - case 1: - n = 0.01; - break; - case 2: - n = 1; - break; - case 3: - n = 100; - break; - } - dataDymX.Phase3 = lowbit * n; + memset(buf, 0, sizeof(buf)); + sprintf(buf, "%02x%02x", pRecvData->Data[35], pRecvData->Data[34]); +// iTemp = (unsigned int)strtol(buf, NULL, 16); +// highbit = iTemp >> 14 & 0x3; +// lowbit = iTemp & 0x3fff; +// switch (highbit) +// { +// case 0: +// n = 0.0001; +// break; +// case 1: +// n = 0.01; +// break; +// case 2: +// n = 1; +// break; +// case 3: +// n = 100; +// break; +// } + dataDymX.Phase4 = 0; - memset(buf, 0, 8); - sprintf(buf, "%02x%02x", pRecvData->Data[35], pRecvData->Data[34]); - iTemp = (unsigned int)strtol(buf, NULL, 16); - highbit = iTemp >> 14 & 0x3; - lowbit = iTemp & 0x3fff; - switch (highbit) - { - case 0: - n = 0.0001; - break; - case 1: - n = 0.01; - break; - case 2: - n = 1; - break; - case 3: - n = 100; - break; - } - dataDymX.Phase4 = lowbit * n; - - memset(whereCon, 0, 64); - sprintf(whereCon, "channelID='%s'", (strLongAddr + "-X").c_str()); - // if ( 0 == sql_ctl->GetTableRows(T_DATA_INFO(TNAME), whereCon) ) { -// char insertSql[1024] = { 0 }; - memset(insertSql,0x00,sizeof(insertSql)); - sprintf(insertSql, "'%s','%s','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%s'", + memset(whereCon, 0, 1024); + sprintf(whereCon, "channelID='%s' and sendMsg = '1'", (strLongAddr + "-X").c_str()); + memset(updateSql, 0, 1024); + sprintf(updateSql, "diagnosisPk='%f',integratPk='%f',integratRMS='%f',rmsValues='%f',envelopEnergy='%f',\ + Amp1='%f',Amp2='%f',Amp3='%f',Amp4='%f',Amp5='%f',Phase1='%f',Phase2='%f',Phase3='%f',Phase4='%f',timeStamp='%s',StaticIndex = %d,nodeResend = %d ",\ + dataDymX.DiagnosisPk, dataDymX.IntegratPk, dataDymX.IntegratRMS, dataDymX.RmsValues, dataDymX.EnvelopEnergy,\ + dataDymX.Amp1, dataDymX.Amp2, dataDymX.Amp3, dataDymX.Amp4, dataDymX.Amp5,dataDymX.Phase1, dataDymX.Phase2, dataDymX.Phase3, dataDymX.Phase4, nowTimetamp.c_str(),staticIndex,nodeResend); + if ( /*0 == sql_ctl->GetTableRows(T_DATA_INFO(TNAME), whereCon)*/(Count * 3 < SAVE_COUNT && lTime < OneWeek ) || strTime.size() == 0) {//1 week + char insertSql[1024] = { 0 }; + memset(insertSql,0x00,sizeof(insertSql)); + sprintf(insertSql, "'%s','%s','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f',%d,'%s','1',%d", strLongAddr.c_str(), (strLongAddr + "-X").c_str(), dataDymX.DiagnosisPk, dataDymX.IntegratPk, dataDymX.IntegratRMS, dataDymX.RmsValues, dataDymX.EnvelopEnergy,\ - dataDymX.Amp1, dataDymX.Amp2, dataDymX.Amp3, dataDymX.Amp4, dataDymX.Amp5,dataDymX.Phase1, dataDymX.Phase2, dataDymX.Phase3, dataDymX.Phase4, nowTimetamp.c_str()); - sql_ctl->InsertData(T_DATA_INFO(TNAME), insertSql); -// } else { -/* char updateSql[1024] = { 0 }; - sprintf(updateSql, "diagnosisPk='%f',integratPk='%f',integratRMS='%f',rmsValues='%f',envelopEnergy='%f',\ - Amp1='%f',Amp2='%f',Amp3='%f',Amp4='%f',Amp5='%f',Phase1='%f',Phase2='%f',Phase3='%f',Phase4='%f',timeStamp='%s'",\ - dataDymX.DiagnosisPk, dataDymX.IntegratPk, dataDymX.IntegratRMS, dataDymX.RmsValues, dataDymX.EnvelopEnergy,\ - dataDymX.Amp1, dataDymX.Amp2, dataDymX.Amp3, dataDymX.Amp4, dataDymX.Amp5,dataDymX.Phase1, dataDymX.Phase2, dataDymX.Phase3, dataDymX.Phase4, nowTimetamp.c_str()); - sql_ctl->UpdateTableData(T_DATA_INFO(TNAME), updateSql, whereCon); - } */ + dataDymX.Amp1, dataDymX.Amp2, dataDymX.Amp3, dataDymX.Amp4, dataDymX.Amp5,dataDymX.Phase1, dataDymX.Phase2, dataDymX.Phase3, dataDymX.Phase4, staticIndex,nowTimetamp.c_str(),nodeResend); + sql_ctl->InsertData(szTableName, insertSql); + + if(0 == sql_ctl->GetTableRows(T_DATA_INFO(TNAME), whereCon)) + sql_ctl->InsertData(T_DATA_INFO(TNAME), insertSql); + else + sql_ctl->UpdateTableData(T_DATA_INFO(TNAME), updateSql, whereCon); + } else { + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon, "channelID='%s' and sendMsg = '1' and timeStamp = '%s'", (strLongAddr + "-X").c_str(),strTime.c_str()); +// sprintf(whereCon, "channelID='%s' and sendMsg = '1' ", (strLongAddr + "-X").c_str()); + sql_ctl->UpdateTableData(szTableName, updateSql, whereCon); + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon, "channelID='%s' ", (strLongAddr + "-X").c_str()); + sql_ctl->UpdateTableData(T_DATA_INFO(TNAME), updateSql, whereCon); + } print_info("x:%s,%s,diagnosisPk=%f,integratPk=%f,integratRMS=%f,rmsValues=%f,envelopEnergy=%f,Amp1=%f,Amp2=%f,Amp3=%f,Amp4=%f,Amp5=%f,Phase1=%f,Phase2=%f,Phase3=%f,Phase4=%f,timeStamp=%s\n",\ strLongAddr.c_str(), (strLongAddr + "-X").c_str(), dataDymX.DiagnosisPk, dataDymX.IntegratPk, dataDymX.IntegratRMS, dataDymX.RmsValues, dataDymX.EnvelopEnergy,\ dataDymX.Amp1, dataDymX.Amp2, dataDymX.Amp3, dataDymX.Amp4, dataDymX.Amp5,dataDymX.Phase1, dataDymX.Phase2, dataDymX.Phase3, dataDymX.Phase4, nowTimetamp.c_str()); @@ -1172,7 +2445,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) valNodeFeature["timeStamp"] = nowTimetamp; valNodeData.append(valNodeFeature); DataRecvDym dataDymY; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[37], pRecvData->Data[36]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1194,7 +2467,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymY.DiagnosisPk = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[39], pRecvData->Data[38]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1216,7 +2489,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymY.RmsValues = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[41], pRecvData->Data[40]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1238,7 +2511,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymY.IntegratPk = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[43], pRecvData->Data[42]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1260,7 +2533,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymY.IntegratRMS = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[45], pRecvData->Data[44]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1282,7 +2555,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymY.Amp1 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[47], pRecvData->Data[46]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1304,7 +2577,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymY.Amp2 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[49], pRecvData->Data[48]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1326,7 +2599,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymY.Amp3 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[51], pRecvData->Data[50]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1348,7 +2621,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymY.Amp4 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[53], pRecvData->Data[52]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1370,133 +2643,147 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymY.Amp5 = lowbit * n; - memset(buf, 0, 8); - sprintf(buf, "%02x%02x", pRecvData->Data[55], pRecvData->Data[54]); - iTemp = (unsigned int)strtol(buf, NULL, 16); - highbit = iTemp >> 14 & 0x3; - lowbit = iTemp & 0x3fff; - switch (highbit) - { - case 0: - n = 0.0001; - break; - case 1: - n = 0.01; - break; - case 2: - n = 1; - break; - case 3: - n = 100; - break; - } - dataDymY.EnvelopEnergy = lowbit * n; + memset(buf, 0, sizeof(buf)); +// sprintf(buf, "%02x%02x", pRecvData->Data[55], pRecvData->Data[54]); +// iTemp = (unsigned int)strtol(buf, NULL, 16); +// highbit = iTemp >> 14 & 0x3; +// lowbit = iTemp & 0x3fff; +// switch (highbit) +// { +// case 0: +// n = 0.0001; +// break; +// case 1: +// n = 0.01; +// break; +// case 2: +// n = 1; +// break; +// case 3: +// n = 100; +// break; +// } +// dataDymY.EnvelopEnergy = lowbit * n; - memset(buf, 0, 8); - sprintf(buf, "%02x%02x", pRecvData->Data[57], pRecvData->Data[56]); - iTemp = (unsigned int)strtol(buf, NULL, 16); - highbit = iTemp >> 14 & 0x3; - lowbit = iTemp & 0x3fff; - switch (highbit) - { - case 0: - n = 0.0001; - break; - case 1: - n = 0.01; - break; - case 2: - n = 1; - break; - case 3: - n = 100; - break; - } - dataDymY.Phase1 = lowbit * n; + dataDymY.EnvelopEnergy = 0; - memset(buf, 0, 8); - sprintf(buf, "%02x%02x", pRecvData->Data[59], pRecvData->Data[58]); - iTemp = (unsigned int)strtol(buf, NULL, 16); - highbit = iTemp >> 14 & 0x3; - lowbit = iTemp & 0x3fff; - switch (highbit) - { - case 0: - n = 0.0001; - break; - case 1: - n = 0.01; - break; - case 2: - n = 1; - break; - case 3: - n = 100; - break; - } - dataDymY.Phase2 = lowbit * n; + memset(buf, 0, sizeof(buf)); +// sprintf(buf, "%02x%02x", pRecvData->Data[57], pRecvData->Data[56]); +// iTemp = (unsigned int)strtol(buf, NULL, 16); +// highbit = iTemp >> 14 & 0x3; +// lowbit = iTemp & 0x3fff; +// switch (highbit) +// { +// case 0: +// n = 0.0001; +// break; +// case 1: +// n = 0.01; +// break; +// case 2: +// n = 1; +// break; +// case 3: +// n = 100; +// break; +// } + dataDymY.Phase1 = 0; - memset(buf, 0, 8); - sprintf(buf, "%02x%02x", pRecvData->Data[61], pRecvData->Data[60]); - iTemp = (unsigned int)strtol(buf, NULL, 16); - highbit = iTemp >> 14 & 0x3; - lowbit = iTemp & 0x3fff; - switch (highbit) - { - case 0: - n = 0.0001; - break; - case 1: - n = 0.01; - break; - case 2: - n = 1; - break; - case 3: - n = 100; - break; - } - dataDymY.Phase3 = lowbit * n; + memset(buf, 0, sizeof(buf)); +// sprintf(buf, "%02x%02x", pRecvData->Data[59], pRecvData->Data[58]); +// iTemp = (unsigned int)strtol(buf, NULL, 16); +// highbit = iTemp >> 14 & 0x3; +// lowbit = iTemp & 0x3fff; +// switch (highbit) +// { +// case 0: +// n = 0.0001; +// break; +// case 1: +// n = 0.01; +// break; +// case 2: +// n = 1; +// break; +// case 3: +// n = 100; +// break; +// } + dataDymY.Phase2 = 0; - memset(buf, 0, 8); - sprintf(buf, "%02x%02x", pRecvData->Data[63], pRecvData->Data[62]); - iTemp = (unsigned int)strtol(buf, NULL, 16); - highbit = iTemp >> 14 & 0x3; - lowbit = iTemp & 0x3fff; - switch (highbit) - { - case 0: - n = 0.0001; - break; - case 1: - n = 0.01; - break; - case 2: - n = 1; - break; - case 3: - n = 100; - break; - } - dataDymY.Phase4 = lowbit * n; + memset(buf, 0, sizeof(buf)); +// sprintf(buf, "%02x%02x", pRecvData->Data[61], pRecvData->Data[60]); +// iTemp = (unsigned int)strtol(buf, NULL, 16); +// highbit = iTemp >> 14 & 0x3; +// lowbit = iTemp & 0x3fff; +// switch (highbit) +// { +// case 0: +// n = 0.0001; +// break; +// case 1: +// n = 0.01; +// break; +// case 2: +// n = 1; +// break; +// case 3: +// n = 100; +// break; +// } + dataDymY.Phase3 = 0; - memset(whereCon, 0, 64); - sprintf(whereCon, "channelID='%s'", (strLongAddr + "-Y").c_str()); -// if ( 0 == sql_ctl->GetTableRows(T_DATA_INFO(TNAME), whereCon) ) { - // char insertSql[1024] = { 0 }; - memset(insertSql,0x00,sizeof(insertSql)); - sprintf(insertSql, "'%s','%s','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%s'", + memset(buf, 0, sizeof(buf)); +// sprintf(buf, "%02x%02x", pRecvData->Data[63], pRecvData->Data[62]); +// iTemp = (unsigned int)strtol(buf, NULL, 16); +// highbit = iTemp >> 14 & 0x3; +// lowbit = iTemp & 0x3fff; +// switch (highbit) +// { +// case 0: +// n = 0.0001; +// break; +// case 1: +// n = 0.01; +// break; +// case 2: +// n = 1; +// break; +// case 3: +// n = 100; +// break; +// } + dataDymY.Phase4 = 0; + + memset(whereCon, 0, 1024); + sprintf(whereCon, "channelID='%s' and sendMsg = '1'", (strLongAddr + "-Y").c_str()); + memset(updateSql, 0, 1024); + sprintf(updateSql, "diagnosisPk='%f',integratPk='%f',integratRMS='%f',rmsValues='%f',envelopEnergy='%f',\ + Amp1='%f',Amp2='%f',Amp3='%f',Amp4='%f',Amp5='%f',Phase1='%f',Phase2='%f',Phase3='%f',Phase4='%f',timeStamp='%s',StaticIndex = %d,nodeResend = %d ",\ + dataDymY.DiagnosisPk, dataDymY.IntegratPk, dataDymY.IntegratRMS, dataDymY.RmsValues, dataDymY.EnvelopEnergy,\ + dataDymY.Amp1, dataDymY.Amp2, dataDymY.Amp3, dataDymY.Amp4, dataDymY.Amp5,dataDymY.Phase1, dataDymY.Phase2, dataDymY.Phase3, dataDymY.Phase4, nowTimetamp.c_str(),staticIndex,nodeResend); + if ( /*0 == sql_ctl->GetTableRows(T_DATA_INFO(TNAME), whereCon)*/ (Count * 3 < SAVE_COUNT && lTime < OneWeek ) || strTime.size() == 0) { + char insertSql[1024] = { 0 }; + memset(insertSql,0x00,sizeof(insertSql)); + sprintf(insertSql, "'%s','%s','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f',%d,'%s','1',%d", strLongAddr.c_str(), (strLongAddr + "-Y").c_str(), dataDymY.DiagnosisPk, dataDymY.IntegratPk, dataDymY.IntegratRMS, dataDymY.RmsValues, dataDymY.EnvelopEnergy,\ - dataDymY.Amp1, dataDymY.Amp2, dataDymY.Amp3, dataDymY.Amp4, dataDymY.Amp5,dataDymY.Phase1, dataDymY.Phase2, dataDymY.Phase3, dataDymY.Phase4, nowTimetamp.c_str()); - sql_ctl->InsertData(T_DATA_INFO(TNAME), insertSql); - // } else { -/* char updateSql[1024] = { 0 }; - sprintf(updateSql, "diagnosisPk='%f',integratPk='%f',integratRMS='%f',rmsValues='%f',envelopEnergy='%f',\ - Amp1='%f',Amp2='%f',Amp3='%f',Amp4='%f',Amp5='%f',Phase1='%f',Phase2='%f',Phase3='%f',Phase4='%f',timeStamp='%s'",\ - dataDymY.DiagnosisPk, dataDymY.IntegratPk, dataDymY.IntegratRMS, dataDymY.RmsValues, dataDymY.EnvelopEnergy,\ - dataDymY.Amp1, dataDymY.Amp2, dataDymY.Amp3, dataDymY.Amp4, dataDymY.Amp5,dataDymY.Phase1, dataDymY.Phase2, dataDymY.Phase3, dataDymY.Phase4, nowTimetamp.c_str()); + dataDymY.Amp1, dataDymY.Amp2, dataDymY.Amp3, dataDymY.Amp4, dataDymY.Amp5,dataDymY.Phase1, dataDymY.Phase2, dataDymY.Phase3, dataDymY.Phase4,staticIndex, nowTimetamp.c_str(),nodeResend); + sql_ctl->InsertData(szTableName, insertSql); + + if(0 == sql_ctl->GetTableRows(T_DATA_INFO(TNAME), whereCon)) + sql_ctl->InsertData(T_DATA_INFO(TNAME), insertSql); + else + sql_ctl->UpdateTableData(T_DATA_INFO(TNAME), updateSql, whereCon); + } else { + + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon, "channelID='%s' and sendMsg = '1' and timeStamp = '%s'", (strLongAddr + "-Y").c_str(),strTime.c_str()); +// sprintf(whereCon, "channelID='%s' and sendMsg = '1' ", (strLongAddr + "-Y").c_str()); + sql_ctl->UpdateTableData(szTableName, updateSql, whereCon); + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon, "channelID='%s' ", (strLongAddr + "-Y").c_str()); sql_ctl->UpdateTableData(T_DATA_INFO(TNAME), updateSql, whereCon); - }*/ + } print_info("y: %s,%s,diagnosisPk=%f,integratPk=%f,integratRMS=%f,rmsValues=%f,envelopEnergy=%f,Amp1=%f,Amp2=%f,Amp3=%f,Amp4=%f,Amp5=%f,Phase1=%f,Phase2=%f,Phase3=%f,Phase4=%f,timeStamp=%s\n",\ strLongAddr.c_str(), (strLongAddr + "-Y").c_str(), dataDymY.DiagnosisPk, dataDymY.IntegratPk, dataDymY.IntegratRMS, dataDymY.RmsValues, dataDymY.EnvelopEnergy,\ dataDymY.Amp1, dataDymY.Amp2, dataDymY.Amp3, dataDymY.Amp4, dataDymY.Amp5,dataDymY.Phase1, dataDymY.Phase2, dataDymY.Phase3, dataDymY.Phase4, nowTimetamp.c_str()); @@ -1522,7 +2809,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) valNodeData.append(valNodeFeature); DataRecvDym dataDymZ; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[65], pRecvData->Data[64]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1544,7 +2831,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.DiagnosisPk = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[67], pRecvData->Data[66]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1566,7 +2853,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.RmsValues = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[69], pRecvData->Data[68]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1588,7 +2875,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.IntegratPk = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[71], pRecvData->Data[70]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1610,7 +2897,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.IntegratRMS = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[73], pRecvData->Data[72]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1632,7 +2919,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.Amp1 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[75], pRecvData->Data[74]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1654,7 +2941,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.Amp2 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[77], pRecvData->Data[76]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1676,7 +2963,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.Amp3 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[79], pRecvData->Data[78]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1698,7 +2985,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.Amp4 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[81], pRecvData->Data[80]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1720,7 +3007,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.Amp5 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[83], pRecvData->Data[82]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1742,7 +3029,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.EnvelopEnergy = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[85], pRecvData->Data[84]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1764,7 +3051,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.Phase1 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[87], pRecvData->Data[86]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1786,7 +3073,7 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.Phase2 = lowbit * n; - memset(buf, 0, 8); + memset(buf, 0, sizeof(buf)); sprintf(buf, "%02x%02x", pRecvData->Data[89], pRecvData->Data[88]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1808,7 +3095,6 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.Phase3 = lowbit * n; - memset(buf, 0, 8); sprintf(buf, "%02x%02x", pRecvData->Data[91], pRecvData->Data[90]); iTemp = (unsigned int)strtol(buf, NULL, 16); highbit = iTemp >> 14 & 0x3; @@ -1830,27 +3116,45 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) } dataDymZ.Phase4 = lowbit * n; - memset(whereCon, 0, 64); - sprintf(whereCon, "channelID='%s'", (strLongAddr + "-Z").c_str()); -// if ( 0 == sql_ctl->GetTableRows(T_DATA_INFO(TNAME), whereCon) ) { -// char insertSql[1024] = { 0 }; - memset(insertSql,0x00,sizeof(insertSql)); - sprintf(insertSql, "'%s','%s','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%s'", + memset(whereCon, 0, 1024); + sprintf(whereCon, "channelID='%s' and sendMsg = '1'", (strLongAddr + "-Z").c_str()); + memset(updateSql, 0, 1024); + + sprintf(updateSql, "diagnosisPk='%f',integratPk='%f',integratRMS='%f',rmsValues='%f',envelopEnergy='%f',\ + Amp1='%f',Amp2='%f',Amp3='%f',Amp4='%f',Amp5='%f',Phase1='%f',Phase2='%f',Phase3='%f',Phase4='%f',timeStamp='%s',StaticIndex = %d,nodeResend = %d ",\ + dataDymZ.DiagnosisPk, dataDymZ.IntegratPk, dataDymZ.IntegratRMS, dataDymZ.RmsValues, dataDymZ.EnvelopEnergy,\ + dataDymZ.Amp1, dataDymZ.Amp2, dataDymZ.Amp3, dataDymZ.Amp4, dataDymZ.Amp5,dataDymZ.Phase1, dataDymZ.Phase2, dataDymZ.Phase3, dataDymZ.Phase4, nowTimetamp.c_str(),staticIndex,nodeResend); + if ( /*0 == sql_ctl->GetTableRows(T_DATA_INFO(TNAME), whereCon)*/ Count *3 < SAVE_COUNT && (lTime < OneWeek || strTime.size() == 0)) { + char insertSql[1024] = { 0 }; + memset(insertSql,0x00,sizeof(insertSql)); + sprintf(insertSql, "'%s','%s','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f','%f',%d,'%s','1',%d", strLongAddr.c_str(), (strLongAddr + "-Z").c_str(), dataDymZ.DiagnosisPk, dataDymZ.IntegratPk, dataDymZ.IntegratRMS, dataDymZ.RmsValues, dataDymZ.EnvelopEnergy,\ - dataDymZ.Amp1, dataDymZ.Amp2, dataDymZ.Amp3, dataDymZ.Amp4, dataDymZ.Amp5,dataDymZ.Phase1, dataDymZ.Phase2, dataDymZ.Phase3, dataDymZ.Phase4, nowTimetamp.c_str()); - sql_ctl->InsertData(T_DATA_INFO(TNAME), insertSql); - /* } else { - char updateSql[1024] = { 0 }; - sprintf(updateSql, "diagnosisPk='%f',integratPk='%f',integratRMS='%f',rmsValues='%f',envelopEnergy='%f',\ - Amp1='%f',Amp2='%f',Amp3='%f',Amp4='%f',Amp5='%f',Phase1='%f',Phase2='%f',Phase3='%f',Phase4='%f',timeStamp='%s'",\ - dataDymZ.DiagnosisPk, dataDymZ.IntegratPk, dataDymZ.IntegratRMS, dataDymZ.RmsValues, dataDymZ.EnvelopEnergy,\ - dataDymZ.Amp1, dataDymZ.Amp2, dataDymZ.Amp3, dataDymZ.Amp4, dataDymZ.Amp5,dataDymZ.Phase1, dataDymZ.Phase2, dataDymZ.Phase3, dataDymZ.Phase4, nowTimetamp.c_str()); + dataDymZ.Amp1, dataDymZ.Amp2, dataDymZ.Amp3, dataDymZ.Amp4, dataDymZ.Amp5,dataDymZ.Phase1, dataDymZ.Phase2, dataDymZ.Phase3, dataDymZ.Phase4, staticIndex,nowTimetamp.c_str(),nodeResend); + sql_ctl->InsertData(szTableName, insertSql); + + if(0 == sql_ctl->GetTableRows(T_DATA_INFO(TNAME), whereCon)) + sql_ctl->InsertData(T_DATA_INFO(TNAME), insertSql); + else + sql_ctl->UpdateTableData(T_DATA_INFO(TNAME), updateSql, whereCon); + } else { + + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon, "channelID='%s' and sendMsg = '1' and timeStamp = '%s'", (strLongAddr + "-Z").c_str(),strTime.c_str()); +// sprintf(whereCon, "channelID='%s' and sendMsg = '1'", (strLongAddr + "-Z").c_str()); + sql_ctl->UpdateTableData(szTableName, updateSql, whereCon); + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon, "channelID='%s' ", (strLongAddr + "-Z").c_str()); sql_ctl->UpdateTableData(T_DATA_INFO(TNAME), updateSql, whereCon); - } */ + } print_info("Z: %s,%s,diagnosisPk=%f,integratPk=%f,integratRMS=%f,rmsValues=%f,envelopEnergy=%f,Amp1=%f,Amp2=%f,Amp3=%f,Amp4=%f,Amp5=%f,Phase1=%f,Phase2=%f,Phase3=%f,Phase4=%f,timeStamp=%s\n",\ strLongAddr.c_str(), (strLongAddr + "-Z").c_str(), dataDymZ.DiagnosisPk, dataDymZ.IntegratPk, dataDymZ.IntegratRMS, dataDymZ.RmsValues, dataDymZ.EnvelopEnergy,\ dataDymZ.Amp1, dataDymZ.Amp2, dataDymZ.Amp3, dataDymZ.Amp4, dataDymZ.Amp5,dataDymZ.Phase1, dataDymZ.Phase2, dataDymZ.Phase3, dataDymZ.Phase4, nowTimetamp.c_str()); + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon, "dataNodeNo='%s'", strLongAddr.c_str()); + sql_ctl->UpdateTableData(T_SENSOR_INFO(TNAME), "status='1'", whereCon); + //string strData = sql_ctl->GetNodeConfigureInfor(whereCon); + //data_publish(strData.c_str(), GlobalConfig::Topic_G.mPubConfig.c_str()); //无线传感器Z信息 valNodeFeature["dataNodeNo"] = strLongAddr; valNodeFeature["ChannelId"] = strLongAddr + "-Z"; @@ -1871,6 +3175,18 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) valNodeFeature["timeStamp"] = nowTimetamp; valNodeData.append(valNodeFeature); + memset(whereCon, 0, 1024); + sprintf(whereCon, "dataNodeNo='%s'", strLongAddr.c_str()); + + string strBattery = sql_ctl->GetData(T_SENSOR_INFO(TNAME),"batteryPower",whereCon); + vector vBattery; + vBattery.push_back("0"); + vBattery.push_back("0"); + if(strBattery.length() > 0){ + + boost::split( vBattery, strBattery, boost::is_any_of( "," ), boost::token_compress_on ); + } + //无线传感器信息 Json::Value root; Json::Value valdatastatic; @@ -1881,6 +3197,8 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) valdatastatic["ChannelType"] = "STATUS"; valdatastatic["ChannelId"] = strLongAddr + "-S"; valdatastatic["TimeStamp"] = nowTimetamp; + valdatastatic["bateryProportion"] = atof(vBattery[0].c_str()); + valdatastatic["batteryRemainDay"] = atof(vBattery[1].c_str()); valdatastatic["dataNodeNo"] = strLongAddr; valNodeData.append(valdatastatic); @@ -1891,18 +3209,46 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) Json::FastWriter featureValue; std::string strstatisticData = featureValue.write(root); //传感器发来的数据包中的表示设备信息的数据转化为json格式后,通过调用data_publish将数据传给mqttclient : Topic:wireless/cmd/60294D203717 - data_publish(strstatisticData.c_str(), GlobalConfig::Topic_G.mPubData.c_str()); + int iRet = data_publish(strstatisticData.c_str(), GlobalConfig::Topic_G.mPubData.c_str()); + print_info("dataNodeNo = '%s' and TimeStamp = '%s',MQTT ret = %d\n",strLongAddr.c_str(),nowTimetamp.c_str(),iRet); + if(iRet != 0){ + char updateSql[1024] = { 0 }; + memset(whereCon, 0, 64); + sprintf(whereCon, "dataNodeNo = '%s' and TimeStamp = '%s'", strLongAddr.c_str(),nowTimetamp.c_str()); + memcpy(updateSql, "sendMsg='0'",sizeof(updateSql)); + sql_ctl->UpdateTableData(szTableNameStatic, updateSql, whereCon); + sql_ctl->UpdateTableData(szTableNameData, updateSql, whereCon); + } //综上代码,把静态数据,x y z轴的特征值存放到sql数据库中(如果数据原来不存在,则插入新数据;如果存在,则更新数据) + print_info("Dip : %d TemBot : %f TemBot : %f Voltage : %d\n", dataStatic.Dip, dataStatic.TemBot, dataStatic.TemTop, dataStatic.Voltage); + memset(selectCon,0x00,sizeof(selectCon)); + sprintf(selectCon, "zigbeeSignal <> '' ORDER BY timeStamp desc LIMIT 0,1"); + strTime = sql_ctl->GetData(szTableNameStatic, "timeStamp", selectCon); + if((atol(nowTimetamp.c_str()) - atol(strTime.c_str()) > 3600) && + (unsigned short)GlobalConfig::Zigbee_G.MyAddr == 0x9999)// 24h = 86400s ; 8h = 36000 ; 16h = 72000 + { + LOG_DEBUG("Zigbee Signal !\n"); + int Times = 0; + bZigbeeSinal = true; + usleep(20000); + while(Times < 3 && bZigbeeSinal){ + getZigbeeSignal(pRecvData->ShortAddr); + Times ++ ; + usleep(20000);; + } + bZigbeeSinal = false; + } + } void Uart::DealDataNodeWave(const char *pData) { - print_info("recv wave\n"); + //print_info("recv wave\n"); RecvData * pRecvData = (RecvData *)pData; m_VecWaveData.push_back(*pRecvData); - print_blue("wave data size is(m_VecWaveData.size) : %d\n",m_VecWaveData.size()); + //print_blue("wave data size is(m_VecWaveData.size) : %d\n",m_VecWaveData.size()); char localtimestamp[32] = { 0 }; GetTimeNet(localtimestamp, 1); // 接收到原始数据信息,则更新时间戳,如果三秒种未收到原始数据,则重新从短地址 9999 切换回 短地址 8888 @@ -1920,7 +3266,7 @@ void Uart::DealWaveThread() //连续三秒没有原始数据,则处理缓存 // 接收到原始波形,则 m_TimeStamp 不为零 // 如果当前时间与记录时间超过3秒,要求,m_TimeStamp不变化,而数据在传输,则一定小于3秒 if (0 == m_TimeStamp) { - boost::this_thread::sleep(boost::posix_time::seconds(1)); + sleep(1); continue; } char localtimestamp[32] = { 0 }; @@ -1935,25 +3281,31 @@ void Uart::DealWaveThread() //连续三秒没有原始数据,则处理缓存 } //if ((nowTimeStamp - m_TimeStamp) > 3) { 时间戳需要修改为绝对值,可能丢失时钟,或工作一会儿,才同步时钟,可能减出异常值 if (tmpTimeStamp > 3 ) { // TODO: 时间戳需要修改为绝对值,可能丢失时钟,或工作一会儿,才同步时钟,可能减出异常值 print_info("yes!The time difference is more than 3,nowTimeStamp : %ld m_TimeStamp : %ld\n", nowTimeStamp, m_TimeStamp); - DealWave(); + //DealWave(); m_TimeStamp = 0; offSize = 0; GlobalConfig::EnterZigBeeWaveTransmittingFlag_G = NO_ENTER_TRANSMITTING_STATUS; GlobalConfig::EnterZigBeeWaveTransmittingCnt_G = 0; // 准备重新恢复到 8888 PanID,正常接收特征数据 - ZigbeeInit(); - pUart->UpdateZigbeeInfoCtrl(); + mPackgeIndex = -1; + //WriteLocalAddr(0x8888); + //GlobalConfig::Zigbee_G.MyAddr = 0x8888; + +// WriteShortAddr2Zigbee(0x8888); +// UpdateZigbeeInfoCtrl(); + } else { print_info("NO! The time difference is less than 3,nowTimeStamp : %ld m_TimeStamp : %ld\n", nowTimeStamp, m_TimeStamp); - } + } - boost::this_thread::sleep(boost::posix_time::seconds(1)); + sleep(1); } } void Uart::DealWave() { - print_info("begin deal Wave data !\n"); + LOG_DEBUG("begin deal Wave data !\n"); + print_blue("wave data size is(m_VecWaveData.size) : %d\n",m_VecWaveData.size()); std::string strShortAddr = ""; std::string strShortAddrTemp; std::string strLongAddr = ""; @@ -1965,7 +3317,8 @@ void Uart::DealWave() char buf[8]; RecvData recvTemp; - print_info("all wave data size is(m_VecWaveData.size) : %d\n", m_VecWaveData.size()); + LOG_INFO("all wave data size is(m_VecWaveData.size) : %d \n",\ + m_VecWaveData.size()); while (m_VecWaveData.size() > 0) { //对每个传感器的每个通道进行遍历然后处理数据,例如:传感器1x轴的数据处理完后,再去处理y轴的。传感器1的所有数据处理完后,再处理传感器2的 std::vector::iterator iter = m_VecWaveData.begin(); recvTemp = *iter; @@ -1975,14 +3328,16 @@ void Uart::DealWave() memset(buf, 0, 8); sprintf(buf, "%02d", recvTemp.Type&0xFF); - iChannel = boost::lexical_cast(buf); + iChannel = atoi(buf); char getLongAddr_sql[32] = { 0 }; sprintf(getLongAddr_sql, "zigbeeShortAddr='%s'", strShortAddr.c_str()); - strLongAddr = sql_ctl->GetData(T_SENSOR_INFO(TNAME), T_SENSOR_INFO(ZIGBEELONGADDR), getLongAddr_sql); + //strLongAddr = sql_ctl->GetData(T_SENSOR_INFO(TNAME), T_SENSOR_INFO(ZIGBEELONGADDR), getLongAddr_sql); + vec_t res = sql_ctl->GetDataSingleLine(T_SENSOR_INFO(TNAME)," * ",getLongAddr_sql); + strLongAddr = res[0]; //print_info("3.1.2.3--->strLongAddr : %s\n", strLongAddr.c_str()); if ( 0 == strLongAddr.length() ) { - boost::this_thread::sleep(boost::posix_time::seconds(1)); + sleep(1); continue; } @@ -1990,16 +3345,21 @@ void Uart::DealWave() int n = 0; int range = 0; float coe = 0; + int sampleRate = 0,ACCSampleTime = 0; char getrange[32] = {0}; std::string str = "range"; - sprintf(getrange, "scope='%s'", str.c_str()); - ran = sql_ctl->GetData(T_SENSOR_INFO(TNAME), T_SENSOR_INFO(RANGE), getrange); - //print_info("@@@@@@@@@@@@@@@@@@@@@@ran=%s\n",ran.c_str()); + sprintf(getrange, "zigbeeShortAddr='%s'", strShortAddr.c_str()); + //ran = sql_ctl->GetData(T_SENSOR_INFO(TNAME), T_SENSOR_INFO(RANGE), getrange); + ran = res[25]; + sampleRate = atoi(res[23].c_str()); + ACCSampleTime = atoi(res[36].c_str()); +// print_info("@@@@@@@@@@@@@@@@@@@@@@ran=%s\n",ran.c_str()); memset(getrange, 0, 32); sprintf(getrange, "%s", ran.c_str()); n = (int)strtol(getrange, NULL, 32); - //print_light_purple("!!!!!!!!!!!!!n=%d\n",n); - switch (n) +// print_light_purple("!!!!!!!!!!!!!n=%d\n",n); + if(res[17] == "01"){ + switch (n) { case 0:{ range = 8; @@ -2022,6 +3382,18 @@ void Uart::DealWave() } break; } + }else if(res[17] == "02"){ + if(iChannel == 3 || iChannel == 4){ + coe = 0.00048828125; + } + if(iChannel == 5){ + if(res[8] == "0.1"){ + coe = 0.0034521484375;//0.03265968810083316; + }else{ + coe = 0.00172607421875; + } + } + } //print_blue("##############range = %d,%f\n",range,coe); for(; iter != m_VecWaveData.end();) { @@ -2032,23 +3404,52 @@ void Uart::DealWave() memset(buf, 0, 8); sprintf(buf, "%02d", recvTemp.Type & 0xFF); - iChannelTemp = boost::lexical_cast(buf); + iChannelTemp = atoi(buf); if( 0 == strShortAddr.compare(strShortAddrTemp) && (iChannel == iChannelTemp) ) { float fTemp; - for (int i = 0; i < 46; i++) { - memset(buf, 0, 8); - sprintf(buf, "%02x%02x", recvTemp.Data[2*i+1],recvTemp.Data[i*2]); - iTemp = strtol(buf, NULL, 16); - if (iTemp < 0x8000) { - fTemp = iTemp * coe; - } else { - fTemp = (((~iTemp)&0xffff) + 1) * -coe; - } - //print_blue("wave data is %u,%f\n",iTemp,fTemp); - vecData.push_back(fTemp); + { + for (int i = 0; i < 46; i++) { + memset(buf, 0, 8); + sprintf(buf, "%02x%02x", recvTemp.Data[2*i+1],recvTemp.Data[i*2]); + iTemp = strtol(buf, NULL, 16); + if (iTemp < 0x8000) { + fTemp = iTemp * coe * 9.8; //convert to m/s2 + } else { + fTemp = (((~iTemp)&0xffff) + 1) * - coe * 9.8; //convert to m/s2 + } + // print_blue("wave data is %u,%f,%f\n",iTemp,fTemp, coe); + vecData.push_back(fTemp); + if(res[17] == "01"){ + //print_blue("vecData.size() = %d,sampleRate * ACCSampleTime = %d,iChannel = %d\n",vecData.size(),sampleRate * ACCSampleTime,iChannel); + if(vecData.size() >= sampleRate * ACCSampleTime && iChannel == 3 ){//过滤数据包结尾空数据 + print_blue("%d vecData.size() == %d,sampleRate * ACCSampleTime = %d\n",iChannel,vecData.size(),sampleRate * ACCSampleTime); + break; + } + if(vecData.size() >= sampleRate * ACCSampleTime && iChannel == 4 ){//过滤数据包结尾空数据 + print_blue("%d vecData.size() == %d,sampleRate * ACCSampleTime = %d\n",iChannel,vecData.size(),sampleRate * ACCSampleTime); + break; + } + if(vecData.size() >= sampleRate * ACCSampleTime && iChannel == 5 ){//过滤数据包结尾空数据 + print_blue("%d vecData.size() == %d,sampleRate * ACCSampleTime = %d\n",iChannel,vecData.size(),sampleRate * ACCSampleTime); + + break; + } + }else if(res[17] == "02"){ + if(vecData.size() >= 8192 && iChannel == 3 ){//过滤数据包结尾空数据 + break; + } + if(vecData.size() >= 8192 && iChannel == 4 ){//过滤数据包结尾空数据 + break; + } + if(vecData.size() >= sampleRate * ACCSampleTime && iChannel == 5 ){//过滤数据包结尾空数据 + break; + } + } + } } iter = m_VecWaveData.erase(iter); + //print_blue("m_VecWaveData.size() == %d,vecData = %d\n",m_VecWaveData.size(),vecData.size()); } else { iter++; } @@ -2061,9 +3462,12 @@ void Uart::DealWave() print_info("strLongAddr : %s\n", strLongAddr.c_str());*/ if ( 0 == strLongAddr.length() ) { - boost::this_thread::sleep(boost::posix_time::seconds(1)); + sleep(1); continue; } + char localtimestamp[32] = { 0 }; + GetTimeNet(localtimestamp, 1); + std::string nowTimetamp = std::string(localtimestamp); std::string strChannelID = ""; switch (iChannel) { @@ -2093,47 +3497,311 @@ void Uart::DealWave() FILE *fp = fopen(strFileName.c_str(), "w"); + fwrite(localtimestamp,sizeof(localtimestamp),1,fp); print_info("fopen FIle vecData.size : %d\n", vecData.size()); + float mean = pCalculation->mean(vecData); float frTemp; char buf[33]={0x00}; std::string strWaveData = ""; for (int i = 0; i < vecData.size(); i++) { - frTemp = vecData[i]; + frTemp = vecData[i] - mean; fwrite(&frTemp,sizeof(float),1,fp); memset(buf,0x00,sizeof(buf)); - sprintf(buf, "%.2f", vecData[i]); + sprintf(buf, "%.2f", frTemp); std::string waveTemp(buf); if(i == 0) strWaveData = waveTemp; strWaveData = strWaveData + "," + waveTemp; } - vecData.clear(); + fclose(fp); // Json::Value valWaveData; - valWaveData["number"] = strWaveData.length(); + int length = vecData.size(); + valWaveData["number"] = sampleRate; valWaveData["channelId"] = strChannelID; valWaveData["dataNodeNo"] = strLongAddr; valWaveData["dataNodeGatewayNo"] = GlobalConfig::MacAddr_G; valWaveData["SensorEngineeringUnit"] = ""; + valWaveData["timeStamp"] = nowTimetamp; valWaveData["waveData"] = strWaveData; + valWaveData["mean"] = mean; Json::FastWriter WaveValue; std::string WaveData = WaveValue.write(valWaveData); - //传感器发来的数据包中的表示设备信息的数据转化为json格式后,通过调用data_publish将数据传给mqttclient : Topic:wireless/cmd/60294D203717 - data_publish(WaveData.c_str(), GlobalConfig::Topic_G.mPubWaveData.c_str()); - print_info("write data to filename %s\n", strFileName.c_str()); - boost::this_thread::sleep(boost::posix_time::seconds(1)); - } - offSize = 0; + if(res[17] == "01"){ + //print_blue("vecData.size() = %d,sampleRate * ACCSampleTime = %d,iChannel = %d\n",vecData.size(),sampleRate * ACCSampleTime,iChannel); + if(vecData.size() < sampleRate * ACCSampleTime && iChannel == 3 ){//过滤数据包结尾空数据 + print_blue("%d vecData.size() == %d,sampleRate * ACCSampleTime = %d\n",iChannel,vecData.size(),sampleRate * ACCSampleTime); + std::vector().swap(vecData); + continue; + } + if(vecData.size() < sampleRate * ACCSampleTime && iChannel == 4 ){//过滤数据包结尾空数据 + print_blue("%d vecData.size() == %d,sampleRate * ACCSampleTime = %d\n",iChannel,vecData.size(),sampleRate * ACCSampleTime); + std::vector().swap(vecData); + continue; + } + if(vecData.size() < sampleRate * ACCSampleTime && iChannel == 5 ){//过滤数据包结尾空数据 + print_blue("%d vecData.size() == %d,sampleRate * ACCSampleTime = %d\n",iChannel,vecData.size(),sampleRate * ACCSampleTime); + std::vector().swap(vecData); + continue; + } + }else if(res[17] == "02"){ + if(vecData.size() < 8192 && iChannel == 3 ){//过滤数据包结尾空数据 + continue; + } + if(vecData.size() < 8192 && iChannel == 4 ){//过滤数据包结尾空数据 + continue; + } + if(vecData.size() < sampleRate * ACCSampleTime && iChannel == 5 ){//过滤数据包结尾空数据 + continue; + } + } + + char selectCon[128] = { 0 }; + sprintf(selectCon, "channelID='%s' and sendMsg = '1' ORDER BY timeStamp ASC LIMIT 0,1",strChannelID.c_str()); + std::string strTime = sql_ctl->GetData("t_data_waveSend", "timeStamp", selectCon); + long lTime = atol(nowTimetamp.c_str())-atol(strTime.c_str()); + int Count = sql_ctl->GetTableRows("t_data_waveSend", NULL); + std::string strFileName_Record = strFileName + "_" + nowTimetamp; + if ((Count * 3 < SAVE_COUNT && lTime < OneWeek ) || strTime.size() == 0 ) { + char insertSql[128]={0x00}; + sprintf(insertSql,"'%s','%s','%s',1,0",strChannelID.c_str(),strFileName_Record.c_str(),nowTimetamp.c_str()); + sql_ctl->InsertData("t_data_waveSend", insertSql); + }else{ + char updateSql[128] = { 0 },whereCon[128] = {0}; + sprintf(updateSql, "waveName='%s',timeStamp='%s'",strFileName_Record.c_str(),nowTimetamp.c_str()); + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon, "channelID='%s' and sendMsg = '1' and timeStamp = '%s'", strChannelID.c_str(),strTime.c_str()); + print_info("update static data to sql\n"); + sql_ctl->UpdateTableData("t_data_waveSend", updateSql, whereCon); + } + //传感器发来的数据包中的表示设备信息的数据转化为json格式后,通过调用data_publish将数据传给mqttclient : Topic:wireless/cmd/60294D203717 + + int iRet = data_publish(WaveData.c_str(), GlobalConfig::Topic_G.mPubWaveData.c_str()); + if(iRet != 0){ + char whereCon[1024] = {0x00}; + char updateSql[1024] = {0x00}; + char tmpWhere[128]={0x00}; + sprintf(tmpWhere,"channelID = '%s' and sendMsg = 0 ",strChannelID.c_str()); + int count = sql_ctl->GetTableRows("t_data_waveSend", tmpWhere); + LOG_ERROR("save channlID %s dat count = %d\n",strChannelID.c_str(),count); + if(count <= 12) + { + sprintf(whereCon, "channelID='%s' and timeStamp = '%s' ", strChannelID.c_str(),nowTimetamp.c_str()); + sprintf(updateSql, "SendMsg = 0 "); + sql_ctl->UpdateTableData("t_data_waveSend", updateSql, whereCon); + LOG_ERROR("send failed,filename %s,iRet = %d\n",strFileName.c_str(),iRet); + string strFileName_failed = strFileName + "_" + nowTimetamp; + char tmpCmd[128]={0x00}; + sprintf(tmpCmd,"cp %s %s",strFileName.c_str(),strFileName_failed.c_str()); + system(tmpCmd); + }else { + memset(tmpWhere,0x00,sizeof(tmpWhere)); + memset(updateSql,0x00,sizeof(updateSql)); + sprintf(tmpWhere, " sendMsg = 0 and channelID='%s' ORDER BY timeStamp ASC LIMIT 0,1",strChannelID.c_str()); + vec_t vecRet = sql_ctl->GetDataSingleLine("t_data_waveSend","*",tmpWhere); + memset(tmpWhere,0x00,sizeof(tmpWhere)); + sprintf(tmpWhere, " sendMsg = 0 and timeStamp = '%s' and channelID = '%s' ",vecRet[2].c_str(),vecRet[0].c_str()); + sprintf(updateSql, "sendMsg = 3 "); + int iRet = sql_ctl->UpdateTableData("t_data_waveSend", updateSql, tmpWhere); + memset(tmpWhere,0x00,sizeof(tmpWhere)); + memset(updateSql,0x00,sizeof(updateSql)); + sprintf(whereCon, "channelID='%s' and timeStamp = '%s' ", strChannelID.c_str(),nowTimetamp.c_str()); + sprintf(updateSql, "sendMsg = 0"); + int iRet2 = sql_ctl->UpdateTableData("t_data_waveSend", updateSql, whereCon); + + string strFileName_failed = strFileName + "_" + nowTimetamp; + char tmpCmd[128]={0x00}; + sprintf(tmpCmd,"cp %s %s",strFileName.c_str(),strFileName_failed.c_str()); + system(tmpCmd); + LOG_ERROR("cp dat file %s \n",tmpCmd); + + memset(tmpWhere,0x00,sizeof(tmpWhere)); + sprintf(tmpWhere," channelID = '%s' and sendMsg = 0 ",strChannelID.c_str()); + int count = sql_ctl->GetTableRows("t_data_waveSend", tmpWhere); + + memset(tmpCmd,0x00,sizeof(tmpCmd)); + sprintf(tmpCmd,"rm %s ",vecRet[1].c_str()); + system(tmpCmd); + LOG_ERROR("rm dat file %s \n",tmpCmd); + + } + + }else{ + LOG_DEBUG("send data , filename %s\n", strFileName.c_str()); + } +#ifdef G2UL_GATEWAY//存储6条波形数据 + char whereCon[1024] = {0x00}; + char updateSql[1024] = {0x00}; + char tmpWhere[128]={0x00}; + sprintf(tmpWhere,"channelID = '%s' and save = 1 ",strChannelID.c_str()); + int count = sql_ctl->GetTableRows("t_data_waveSend", tmpWhere); + LOG_INFO("save channlID %s dat count = %d\n",strChannelID.c_str(),count); + if(count <= 5) + { + sprintf(whereCon, "channelID='%s' and timeStamp = '%s' ", strChannelID.c_str(),nowTimetamp.c_str()); + sprintf(updateSql, "save = 1 "); + sql_ctl->UpdateTableData("t_data_waveSend", updateSql, whereCon); + string strFileName_save = strFileName + "_" + nowTimetamp + "_save"; + char tmpCmd[128]={0x00}; + sprintf(tmpCmd,"cp %s %s",strFileName.c_str(),strFileName_save.c_str()); + system(tmpCmd); + }else { + memset(tmpWhere,0x00,sizeof(tmpWhere)); + memset(updateSql,0x00,sizeof(updateSql)); + sprintf(tmpWhere, " save = 1 and channelID='%s' ORDER BY timeStamp ASC LIMIT 0,1",strChannelID.c_str()); + vec_t vecRet = sql_ctl->GetDataSingleLine("t_data_waveSend","*",tmpWhere); + memset(tmpWhere,0x00,sizeof(tmpWhere)); + sprintf(tmpWhere, " save = 1 and timeStamp = '%s' and channelID = '%s' ",vecRet[2].c_str(),vecRet[0].c_str()); + sprintf(updateSql, "save = 0 "); + int iRet = sql_ctl->UpdateTableData("t_data_waveSend", updateSql, tmpWhere); + memset(tmpWhere,0x00,sizeof(tmpWhere)); + memset(updateSql,0x00,sizeof(updateSql)); + sprintf(whereCon, "channelID='%s' and timeStamp = '%s' ", strChannelID.c_str(),nowTimetamp.c_str()); + sprintf(updateSql, "save = 1"); + int iRet2 = sql_ctl->UpdateTableData("t_data_waveSend", updateSql, whereCon); + + string strFileName_save = strFileName + "_" + nowTimetamp + "_save"; + char tmpCmd[128]={0x00}; + sprintf(tmpCmd,"cp %s %s",strFileName.c_str(),strFileName_save.c_str()); + system(tmpCmd); + + memset(tmpWhere,0x00,sizeof(tmpWhere)); + sprintf(tmpWhere," channelID = '%s' and save = 1 ",strChannelID.c_str()); + int count = sql_ctl->GetTableRows("t_data_waveSend", tmpWhere); + + memset(tmpCmd,0x00,sizeof(tmpCmd)); + sprintf(tmpCmd,"rm %s ",(vecRet[1]+"_save").c_str()); + system(tmpCmd); + LOG_INFO("rm dat file %s \n",tmpCmd); + } + +#endif + print_info("write data to filename %s\n", strFileName.c_str()); + std::vector().swap(vecData); + sleep(1); + } + std::vector().swap(m_VecWaveData); + char whereCon[1024] = {0x00}; + char updateSql[1024] = {0x00}; + sprintf(whereCon, "dataNodeNo='%s'", strLongAddr.c_str()); + sprintf(updateSql, "WaveTime = WaveTime + 1"); + sql_ctl->UpdateTableData(T_SENSOR_INFO(TNAME), updateSql, whereCon); + + //string strData = sql_ctl->GetNodeConfigureInfor(whereCon); + //data_publish(strData.c_str(), GlobalConfig::Topic_G.mPubConfig.c_str()); // memset(buf, 0, 8); // sprintf(buf, "%02x%02x", recvTemp.ShortAddr[0], recvTemp.ShortAddr[1]); // std::string strShortAddr = std::string(buf); +} +void Uart::DealNodeSendTime(unsigned char* shortaddr) +{ + + /*char updateSql[1024]={0x00},whereCon[1024]={0x00},insertSql[1024]={0x00}; + memset(whereCon,0x00,sizeof(whereCon)); + memset(insertSql,0x00,sizeof(insertSql)); + sprintf(whereCon,"dataNodeNo = '%s'",dataNodeInfo.ZigbeeLongAddr.c_str()); + int nodegroup = 0; + int staticStartTime = 0; + int nodeindex = 0; + int statictime = 0; + int nodewaveindex = 1; + if(0 == sql_ctl->GetTableRows(T_DATANODE_TIME(TNAME), whereCon)){ + + sprintf(whereCon,"staticcycle = '%d' and wavecycle = '%d' order by nodeindex desc LIMIT 0 , 1",dataNodeInfo.FeatureInterVal,dataNodeInfo.WaveInterVal); + vec_t vecResult = sql_ctl->GetDataSingleLine(T_DATANODE_TIME(TNAME),"*",whereCon); + if(vecResult.size() == 0){ + string strResult = sql_ctl->GetData(T_DATANODE_TIME(TNAME),"nodegroup"," nodegroup > 0 order by nodegroup desc LIMIT 0 , 1"); + if(atoi(strResult.c_str()) > 0){ + print_info("strResult = %s\n",strResult.c_str()); + nodegroup = atoi(strResult.c_str()) + 1; + }else{ + nodegroup = 1; + } + staticStartTime = 0; + }else{ + nodegroup = atoi(vecResult[4].c_str()); + nodewaveindex = atoi(vecResult[6].c_str()) + 1; + statictime = atoi(vecResult[7].c_str()) + atoi(vecResult[2].c_str()); + if(statictime > atoi(vecResult[3].c_str())){ + staticStartTime = ceil(atof(vecResult[2].c_str()) / 2 ); + statictime = staticStartTime; + nodewaveindex = 1; + }else{ + staticStartTime = atoi(vecResult[8].c_str()); + } + } + std::string strnodeinex = sql_ctl->GetData(T_DATANODE_TIME(TNAME), "nodeindex", "nodeindex > 0 order by nodeindex desc LIMIT 0 , 1"); + LOG_INFO("DealNodeSendTime strnodeinex = %s\n",strnodeinex.c_str()); + nodeindex = atoi(strnodeinex.c_str())+1; + sprintf(insertSql,"'%s','%s','%d','%d',%d,%d,%d,%d,%d",dataNodeInfo.ZigbeeLongAddr.c_str(),dataNodeInfo.ZigbeeShortAddr.c_str(),\ + dataNodeInfo.FeatureInterVal,dataNodeInfo.WaveInterVal,nodegroup,nodeindex,nodewaveindex,statictime,staticStartTime); + sql_ctl->InsertData(T_DATANODE_TIME(TNAME), insertSql); + LOG_INFO("DealNodeSendTime InsertData = %s\n",insertSql); + UpdateWirelessNodeTime(shortaddr,nodewaveindex,staticStartTime,nodeindex);//更新时间戳 + }else{ + sprintf(whereCon,"staticcycle = '%d' and wavecycle = '%d' order by nodeindex desc LIMIT 0 , 1", + dataNodeInfo.FeatureInterVal,dataNodeInfo.WaveInterVal); + + vec_t vecResult = sql_ctl->GetDataSingleLine(T_DATANODE_TIME(TNAME),"*",whereCon); + if(vecResult.size() == 0){ + string strResult = sql_ctl->GetData(T_DATANODE_TIME(TNAME),"nodegroup"," nodegroup > 0 order by nodeindex desc LIMIT 0 , 1"); + if(atoi(strResult.c_str()) > 0){ + nodegroup = atoi(strResult.c_str()) + 1; + }else{ + nodegroup = 1; + } + staticStartTime = 0; + statictime = 0; + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon,"dataNodeNo = '%s'",dataNodeInfo.ZigbeeLongAddr.c_str()); + sprintf(updateSql," staticcycle = '%d',wavecycle = '%d',nodegroup = %d,nodewaveindex = %d,statictime = %d, staticstarttime = %d",dataNodeInfo.FeatureInterVal,dataNodeInfo.WaveInterVal,\ + nodegroup,nodewaveindex,statictime,staticStartTime); + sql_ctl->UpdateTableData(T_DATANODE_TIME(TNAME), updateSql, whereCon); + LOG_INFO("DealNodeSendTime updateSql = %s\n",updateSql); + LOG_DEBUG("DealNodeSendTime1"); + UpdateWirelessNodeTime(shortaddr,nodewaveindex,staticStartTime,nodeindex);//更新时间戳 + }else{ + print_info("=======Send Time======\n"); + LOG_DEBUG("DealNodeSendTime2"); + UpdateWirelessNodeTime(shortaddr,atoi(vecResult[6].c_str()),atoi(vecResult[8].c_str()),atoi(vecResult[5].c_str()));//更新时间戳 + } + } + memset(whereCon,0x00,sizeof(whereCon)); + sprintf(whereCon,"dataNodeNo = '%s' and staticcycle <> '%d' and wavecycle <> '%d'",dataNodeInfo.ZigbeeLongAddr.c_str(),\ + dataNodeInfo.FeatureInterVal,dataNodeInfo.WaveInterVal); + sql_ctl->DeleteTableData(T_DATANODE_TIME(TNAME),whereCon);*/ + + +} +bool Uart::CheckCrc(char* pCheckBuff,int No) +{ + unsigned char tmp = 0x00; + for(int i = 0 ; i < No;i++){ + tmp += (unsigned char)pCheckBuff[i]; +// printf("%02x ",pCheckBuff[i]); + } + + if((unsigned char)pCheckBuff[No] != (unsigned char)tmp) + return false; + return true; + } void Uart::modify_distaddr_info(unsigned short id, char * zigbee,unsigned char* distAddr) { - char command[6]; + char command[6] = {0x00}; + command[0] = 0xDE; + command[1] = 0xDF; + command[2] = 0xEF; + command[3] = 0xDC; + command[4] = ((char *)&id)[1]; + command[5] = ((char *)&id)[0]; + WriteToUart(command, 6); + + usleep(10000); + memset(command,0x00,sizeof(command)); command[0] = 0xDE; command[1] = 0xDF; command[2] = 0xEF; @@ -2142,6 +3810,71 @@ void Uart::modify_distaddr_info(unsigned short id, char * zigbee,unsigned char* command[5] = distAddr[1]; WriteToUart(command, 6); + +} +void Uart::getZigbeeSignal(unsigned char* distAddr) +{ + usleep(10000); + char command[6] = {0x00}; + command[0] = 0xDE; + command[1] = 0xDF; + command[2] = 0xEF; + command[3] = 0xDA; + command[4] = distAddr[0]; + command[5] = distAddr[1]; + WriteToUart(command, 6); +} +void Uart::modify_DistAddr(unsigned char* distAddr) +{ + char command[6] = {0x00}; + memset(command,0x00,sizeof(command)); + command[0] = 0xDE; + command[1] = 0xDF; + command[2] = 0xEF; + command[3] = 0xD2; + command[4] = distAddr[0]; + command[5] = distAddr[1]; + WriteToUart(command, 6); +} +void Uart::modify_LocalAddr(unsigned short id) +{ + char command[6] = {0x00}; + + + command[0] = 0xDE; + command[1] = 0xDF; + command[2] = 0xEF; + command[3] = 0xDC; + command[4] = ((char *)&id)[1]; + command[5] = ((char *)&id)[0]; + WriteToUart(command, 6); +// ReadFromUart(); + +} +void Uart::modify_Localchannel(unsigned char pad) +{ + char command[6] = {0x00}; + command[0] = 0xDE; + command[1] = 0xDF; + command[2] = 0xEF; + command[3] = 0xD1; + command[4] = pad & 0xff; + WriteToUart(command, 5); +// ReadFromUart(); + +} +void Uart::modify_LocalPanID(unsigned short padID) +{ + char command[6] = {0x00}; + command[0] = 0xDE; + command[1] = 0xDF; + command[2] = 0xEF; + command[3] = 0xDB; + command[4] = ((char *)&padID)[1]; + command[5] = ((char *)&padID)[0]; + WriteToUart(command, 6); +// ReadFromUart(); + } void Uart::modify_info(unsigned short id, char * zigbee) { @@ -2153,8 +3886,8 @@ void Uart::modify_info(unsigned short id, char * zigbee) command[1] = 0xbc; command[2] = 0xcd; command[3] = 0xd6; - command[4] = ((char *)&id)[1]; - command[5] = ((char *)&id)[0]; + command[4] = ((char *)&id)[0]; + command[5] = ((char *)&id)[1]; command[6] = 0; if (zigbee != NULL) { con = 71; @@ -2166,9 +3899,9 @@ void Uart::modify_info(unsigned short id, char * zigbee) { tmp += command[i]; } - command[i] = tmp; + command[i] = 0xaa; WriteToUart(command, i+1); - boost::this_thread::sleep(boost::posix_time::seconds(1)); + sleep(1); } void Uart::zigbee_reset(unsigned short pad, unsigned short type) @@ -2197,10 +3930,13 @@ void Uart::WriteChanl2Zigbee(unsigned char pad) unsigned short tmp; tmp = GlobalConfig::Zigbee_G.MyAddr; //swap((char *)&pad1); - swap((char *)&tmp); + //swap((char *)&tmp); GlobalConfig::Zigbee_G.Chan = pad1; modify_info(tmp, (char *)& GlobalConfig::Zigbee_G); - zigbee_reset(tmp, 1); + + gpio_set(GlobalConfig::GPIO_G.zigReset,0); + usleep(10000); + gpio_set(GlobalConfig::GPIO_G.zigReset,1); } void Uart::WritePanId2Zigbee(unsigned short pad) @@ -2208,24 +3944,79 @@ void Uart::WritePanId2Zigbee(unsigned short pad) print_info("WritePanId2Zigbee : %d\n", pad); unsigned short pad1 = pad,tmp; tmp = GlobalConfig::Zigbee_G.MyAddr; + print_info("MyAddr : %d\n", GlobalConfig::Zigbee_G.MyAddr); swap((char *)&pad1); - swap((char *)&tmp); + //swap((char *)&tmp); GlobalConfig::Zigbee_G.PanID = pad1; - modify_info(tmp, (char *)&GlobalConfig::Zigbee_G); - zigbee_reset(tmp, 1); -} + modify_info(tmp, (char *)&GlobalConfig::Zigbee_G); + gpio_set(GlobalConfig::GPIO_G.zigReset,0); + usleep(10000); + gpio_set(GlobalConfig::GPIO_G.zigReset,1); +} +void Uart::WriteSpeed2Zigbee() +{ + GlobalConfig::Zigbee_G.Serial_Rate = 0x07; + GlobalConfig::Zigbee_G.Serial_DataB = 0x08; + GlobalConfig::Zigbee_G.Serial_StopB = 0x01; + unsigned short tmp; + tmp = GlobalConfig::Zigbee_G.MyAddr; + modify_info(tmp, (char *)&GlobalConfig::Zigbee_G); + gpio_set(GlobalConfig::GPIO_G.zigReset,0); + usleep(10000); + gpio_set(GlobalConfig::GPIO_G.zigReset,1); +} +/*void Uart::WriteLocalAddr(unsigned short id) +{ + gpio_set(116,0); + usleep(10000); + gpio_set(116,1); + sleep(1); + char command[8]={0x00}; + command[0] = 0xab; + command[1] = 0xbc; + command[2] = 0xcd; + command[3] = 0xdc; + command[4] = ((char *)&id)[1]; + command[5] = ((char *)&id)[0]; + command[6] = 0x00; + command[7] = 0xaa; + WriteToUart(command, 8); + usleep(600000); + gpio_set(116,0); + usleep(10000); + gpio_set(116,1); +}*/ +void Uart::WriteTranTimeout2Zigbee(unsigned char Time) +{ + print_info("WriteTranTimeout2Zigbee : %d\n", Time); + + unsigned short tmp = GlobalConfig::Zigbee_G.MyAddr; + //print_info("MyAddr : %d\n", GlobalConfig::Zigbee_G.MyAddr); + GlobalConfig::Zigbee_G.PowerLevel = 0x03; + GlobalConfig::Zigbee_G.RetryNum = 0x64; + GlobalConfig::Zigbee_G.TranTimeout = Time; + modify_info(tmp, (char *)&GlobalConfig::Zigbee_G); + + gpio_set(GlobalConfig::GPIO_G.zigReset,0); + usleep(10000); + gpio_set(GlobalConfig::GPIO_G.zigReset,1); +} void Uart::WriteShortAddr2Zigbee(unsigned short pad) { print_info("WriteShortAddr2Zigbee : %4x\n", (unsigned short)pad); unsigned short pad1 = pad,tmp; tmp = GlobalConfig::Zigbee_G.MyAddr; - swap((char *)&pad1); - swap((char *)&tmp); + //swap((char *)&pad1); + //swap((char *)&tmp); GlobalConfig::Zigbee_G.MyAddr = pad1; modify_info(tmp, (char *)& GlobalConfig::Zigbee_G); - zigbee_reset(tmp, 1); + + gpio_set(GlobalConfig::GPIO_G.zigReset,0); + usleep(10000); + gpio_set(GlobalConfig::GPIO_G.zigReset,1); + sleep(1); } void Uart::WriteShortAddr_DistAddr2Zigbee(unsigned short pad,unsigned char* pDestShortAddr) @@ -2236,55 +4027,64 @@ void Uart::WriteShortAddr_DistAddr2Zigbee(unsigned short pad,unsigned char* pDes swap((char *)&pad1); swap((char *)&tmp); char tmpDest[8]={0x00}; - sprintf(tmpDest,"%02d%02d",pDestShortAddr[0],pDestShortAddr[1]); + sprintf(tmpDest,"%02x%02x",pDestShortAddr[0],pDestShortAddr[1]); memcpy(&GlobalConfig::Zigbee_G.DstAddr,pDestShortAddr,2); GlobalConfig::Zigbee_G.MyAddr = pad1; // GlobalConfig::Zigbee_G.DstAddr = (short)atoi((char*)tmpDest); - printf("DstAddr = %d\n",GlobalConfig::Zigbee_G.DstAddr); + print_info("DstAddr = %x\n",GlobalConfig::Zigbee_G.DstAddr); GlobalConfig::ZigbeeInfo_G.MyAddr = "9999"; modify_info(tmp, (char *)& GlobalConfig::Zigbee_G); - zigbee_reset(tmp, 1); + + gpio_set(GlobalConfig::GPIO_G.zigReset,0); + usleep(10000); + gpio_set(GlobalConfig::GPIO_G.zigReset,1); } void Uart::ZigbeeInit() { - std::string strPanId = GlobalConfig::MacAddr_G.substr(8); + std::string strPanId = sql_ctl->GetData("t_gateway_info","zigbeePanID",NULL); + + { + unsigned short shortAddr = 0x8888; + //GlobalConfig::Zigbee_G.MyAddr = shortAddr; + //WriteLocalAddr(shortAddr); + WriteShortAddr2Zigbee(shortAddr); + usleep(100000); + // 更新GlobalConfig::ZigbeeInfo_G.MyAddr,用于外部显示 + + } + + //std::string strPanId = GlobalConfig::MacAddr_G.substr(8); print_info("strPanId : %s\n", strPanId.c_str()); + print_info("MacAddr_G : %s\n", GlobalConfig::MacAddr_G.c_str()); // 新增管理ZigBee代码 std::string strchan = ReadStrByOpt(ZIGBEECONFIG, "Zigbee", "channel"); - unsigned char Chan = (unsigned char)strtol(strchan.c_str(), NULL, 10); - printf("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%the chan = %u\n",Chan); + + unsigned short Chan = (unsigned short)strtol(strchan.c_str(), NULL, 10); + print_info("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%the chan = %u\n",Chan); print_info("ZigbeeInfo_G.Channel=%d\n",GlobalConfig::ZigbeeInfo_G.Channel); if(Chan > 10 && Chan < 27) { - if (Chan != GlobalConfig::ZigbeeInfo_G.Channel) { - printf("the chanl is different\n"); - WriteChanl2Zigbee(Chan); - boost::this_thread::sleep(boost::posix_time::seconds(1)); - } + //if (Chan != GlobalConfig::ZigbeeInfo_G.Channel) + { + WriteChanl2Zigbee(Chan); + //modify_Localchannel(Chan); + usleep(100000); + } } - - if (0 != GlobalConfig::ZigbeeInfo_G.PanID.compare(strPanId.c_str())) { + print_info("PanID1 = %s,strPanId = %s\n",GlobalConfig::ZigbeeInfo_G.PanID.c_str(),strPanId.c_str()); + //if (0 != GlobalConfig::ZigbeeInfo_G.PanID.compare(strPanId.c_str())) + { long lShortAddr = strtol(strPanId.c_str(), NULL, 16); unsigned short panid = lShortAddr & 0xffff; - print_info("the panid is different\n"); - WritePanId2Zigbee(panid); - boost::this_thread::sleep(boost::posix_time::seconds(1)); - } + //modify_LocalPanID(panid); - if (0 != GlobalConfig::ZigbeeInfo_G.MyAddr.compare("8888")) { - unsigned short shortAddr = 0x8888; - print_info("the short addr is different\n"); - WriteShortAddr2Zigbee(shortAddr); - boost::this_thread::sleep(boost::posix_time::seconds(1)); - LOG_INFO("[ZigbeeInit---------] ZigBee PanID: %s ; Channel: %d ; MyAddr : %4x ",GlobalConfig::ZigbeeInfo_G.PanID.c_str(),GlobalConfig::ZigbeeInfo_G.Channel, - (unsigned short)GlobalConfig::Zigbee_G.MyAddr); - // 更新GlobalConfig::ZigbeeInfo_G.MyAddr,用于外部显示 - char tmp[16]; - sprintf(tmp,"%4x",(unsigned short)GlobalConfig::Zigbee_G.MyAddr); - std::string strTmp(tmp); - GlobalConfig::ZigbeeInfo_G.MyAddr = strTmp; + WritePanId2Zigbee(panid); + usleep(100000); } + + //if (0 != GlobalConfig::ZigbeeInfo_G.MyAddr.compare("8888")) + print_info("ZigbeeInfo_G.MyAddr=%s\n",GlobalConfig::ZigbeeInfo_G.MyAddr.c_str()); } diff --git a/uart/SH_Uart.hpp b/uart/SH_Uart.hpp index 1868e77..1c769ba 100644 --- a/uart/SH_Uart.hpp +++ b/uart/SH_Uart.hpp @@ -11,7 +11,7 @@ #include "../common/SH_CommonFunc.hpp" #include "../common/SH_global.h" #include "../dbaccess/SH_SqlDB.hpp" - +#include "../calculation/Calculation.hpp" @@ -20,25 +20,47 @@ //using boost::system::error_code; typedef unsigned int UINT; +typedef void (*pTestRecvCallBack)(int Status); class Uart : public MySingleton { private : - boost::posix_time::ptime mLocalTime; - boost::asio::io_service mIoSev; - boost::asio::serial_port mUart; - int mRdLength; - enum{BUF_LENGTH = 1107}; - char mUartRecvBuf[BUF_LENGTH]; - boost::mutex mLock; - boost::asio::io_service::strand mStrand; + boost::posix_time::ptime mLocalTime; + boost::asio::io_service mIoSev; + boost::asio::serial_port mUart; + int mRdLength; + int mlastSize; + int mPackgeIndex; + string strTimetamp; + + //DataNodeInfo dataNodeInfo; + std::string m_strDestShortAddr; + int waittime; + enum{BUF_LENGTH = 40960}; + unsigned char mUartRecvBuf[BUF_LENGTH]; + char mUartRecvTmpBuf[BUF_LENGTH*15]; + boost::mutex mLock; + boost::asio::io_service::strand mStrand; public : Uart(); - void InitUart(); ~Uart(); + void InitZigbee(); + void InitUart(speed_t speed); + void Close(); + void InitTestUart(speed_t speed); + void ReadTestUart(); + int fd,TestFd; + bool bUpdate; + bool bUpdatePre; + bool bUpdateconfig; + bool bTest; + bool bZigbeeSinal; + bool bModifyAddr; + bool bSendTimeStamp; + std::string DataNodeUpdateFile; void WriteToUart(const char *strSend,int pLen); - void ReadFromUart(); + int ReadFromUart(); void setCallBack(onReceiveUart _callback); void Run(); void Stop(); @@ -46,30 +68,48 @@ public : void UpdateZigbeeInfo(const char *pData); void DealRecvData(const char *pData); void DealDataNodeInfo(const char *pData); + void DealDataNodeName(const char *pData); void DealDataNodeFeature(const char *pData, int flag); void DealDataNodeWave(const char *pData); void DealWaveThread(); void DealWave(); + void DealNodeSendTime(unsigned char* shortaddr); void ZigbeeInit(); + int ZigbeeTest(); void modify_info(unsigned short id, char * zigbee); void modify_distaddr_info(unsigned short id, char * zigbee,unsigned char* distAddr); + void modify_LocalAddr(unsigned short id); + void modify_DistAddr(unsigned char* distAddr); + void modify_Localchannel(unsigned char pad); + void modify_LocalPanID(unsigned short padID); + void getZigbeeSignal(unsigned char* distAddr); void zigbee_reset(unsigned short pad, unsigned short type); void WriteChanl2Zigbee(unsigned char pad); void WritePanId2Zigbee(unsigned short pad); + void WriteSpeed2Zigbee(); + //void WriteLocalAddr(unsigned short id); + void WriteTranTimeout2Zigbee(unsigned char Time); void WriteShortAddr2Zigbee(unsigned short pad); void WriteShortAddr_DistAddr2Zigbee(unsigned short pad,unsigned char* pDestShortAddr); void UpdateWirelessNode(unsigned short shortAdd); + void UpdateWirelessNodeTime(unsigned char* pDestShortAddr,int modifyaddr/*,int nodewaveindex,int nodetime,int nodeindex*/); + int UpdateConfig(unsigned char* pDestShortAddr); bool ReadUpdatePackge(unsigned char* shortAddr); + bool CheckCrc(char* pCheckBuff,int No); + int FindRecvPackage(int bytesRead, char* mUartRecvBuf,char* head); virtual void DataAnalysis_R(DevDataOfGwid &pData); virtual void DataAnalysis_W(DevData &pData,bool pFlag); virtual void ThreadInit(); + int UartRecv(int fd, char srcshow,char* buffer); + void openSwitch(); private : - void ReadHandle(const boost::system::error_code &ec,size_t bytesRead); + void ReadHandle(char* pUartRecvBuf,size_t bytesRead); void WriteHandle(const char *strSend,const boost::system::error_code &ec,size_t bytesWrite); onReceiveUart m_callback; std::vector m_VecWaveData; unsigned long m_TimeStamp; + bool m_waveTrans; }; diff --git a/udpqt/SH_UdpQt.cpp b/udpqt/SH_UdpQt.cpp index e692297..9a61974 100644 --- a/udpqt/SH_UdpQt.cpp +++ b/udpqt/SH_UdpQt.cpp @@ -121,7 +121,7 @@ void UdpSys::AnalysisDataSys(std::string cmd) GlobalConfig::ServerPort = localServerPort; WriteStr2Config(SERVERCONFIG, "Server", "localServerIpAddress", GlobalConfig::ServerIP); - WriteStr2Config(SERVERCONFIG, "Server", "localServerPort", boost::lexical_cast(GlobalConfig::ServerPort)); + WriteStr2Config(SERVERCONFIG, "Server", "localServerPort", to_string(GlobalConfig::ServerPort)); std::string fileserver = ReadStrByOpt(SERVERCONFIG, "FileServer", "FileServerIpAddress"); if (0 == fileserver.compare("0.0.0.0") || 0 == fileserver.length()) { @@ -191,4 +191,4 @@ UdpSys::~UdpSys() { if (udpSock.is_open()) udpSock.close(); -} \ No newline at end of file +} diff --git a/wifi/wpa_client.cpp b/wifi/wpa_client.cpp new file mode 100644 index 0000000..51a43c3 --- /dev/null +++ b/wifi/wpa_client.cpp @@ -0,0 +1,555 @@ +#include "wpa_client.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace wifi { + +size_t strlcpy (char *dst, const char *src, size_t dst_sz) +{ + size_t n; + + for (n = 0; n < dst_sz; n++) { + if ((*dst++ = *src++) == '\0') + break; + } + + if (n < dst_sz) + return n; + if (n > 0) + *(dst - 1) = '\0'; + return n + strlen (src); +} + +static std::string to_string(int val) { + char *buf = NULL; + int size; + int temp; + if (val < 0) + { + temp = -val; + size = 2; + } + else + { + temp = val; + size = 1; + } + for(; temp > 0; temp = temp / 10, size++); + size++; + + buf = (char *)malloc(size); + if (buf == NULL) + { + return ""; + } + memset(buf, 0, size); + sprintf(buf, "%d", val); + std::string re(buf); + free(buf); + return re; +} + + +MXDHCP::MXDHCP() +{ + pstream = NULL; +} + +MXDHCP::~MXDHCP() +{ + if(pstream!=NULL) + { + pclose(pstream); + pstream = NULL; + } +} + +bool MXDHCP::Start(const std::string & net_interface) +{ + if(pstream!=NULL) + { + pclose(pstream); + pstream = NULL; + } + std::string cmd = "udhcpc -b -i " + net_interface + " &"; + system("killall -9 udhcpc &"); + usleep(1000*100); + pstream = popen(cmd.data(),"r"); + if(pstream == NULL) + { + return false; + } + return true; +} + +/* +* dhcp 这个类的主要原理是通过读取udhcpc 的输出来判断是否拿到了ip地址,实际情况中可以使用别的方法 +*/ +bool MXDHCP::GetDHCPStatus() +{ + if(pstream == NULL) + { + return false; + } + int len = 1024; + char *buff = (char *)malloc(sizeof(char)*len); + if(buff==NULL) + { + return false; + } + int res = fread(buff,sizeof(char),len,pstream); + if(res<=0) + { + free(buff); + return false; + } + if(!CheckString(buff,res)) + { + free(buff); + return false; + } + pclose(pstream); + pstream = NULL; + free(buff); + return true; +} + +bool MXDHCP::CheckString(char *buf ,int len) +{ + if(strstr(buf,"adding dns")==NULL) + { + return false; + } + return true; +} + + +WPAClient::WPAClient(const std::string & wpa_control_path) +{ + wpa_context_ = NULL; + wpa_control_path_ = wpa_control_path; + SetConnStatus(STEP_SCAN); + Init(); +} + +WPAClient::~WPAClient() +{ + Close(wpa_context_); +} + +bool WPAClient::Init() +{ + wpa_context_ = Open(wpa_control_path_); + if (wpa_context_ == NULL) + { + print_error("open wpa failed\n"); + return false; + } + SetConnStatus(STEP_SCAN); + return true; +} + +std::string WPAClient::GetCurrentSSID() +{ + std::string cmd = "STATUS"; + std::string ssid_key = "\nssid="; + std::string recv; + std::string ssid = ""; + + if (!Request(wpa_context_, cmd, recv)) + { + return ""; + } + char temp[1024] = {0}; + strcpy(temp, recv.data()); + char *key = NULL; + key = strstr(temp, ssid_key.data()); + if (key == NULL) + { + return ""; + } + key += ssid_key.length(); + for(; (*key != '\0') && (*key != '\n') && (*key != '\r'); key++) + { + ssid += *key; + } + + return ssid; +} + +std::string WPAClient::GetNetSsid() +{ + std::string cmd = "SCAN"; + std::string recv; + if (!Request(wpa_context_, cmd, recv)) + { + return ""; + } + + recv.clear(); + cmd = "SCAN_RESULTS"; + + if (!Request(wpa_context_, cmd, recv)) + { + return ""; + } + return recv; +} +int WPAClient::GetWiFiRssi() +{ + std::string cmd = "SIGNAL_POLL"; + std::string rssi_key = "RSSI"; + std::string recv; + if (!Request(wpa_context_, cmd, recv)) + { + return 0; + } + char temp[1024] = {0}; + strcpy(temp, recv.data()); + print_info("recv = %s\n",recv.c_str()); + char *key = NULL; + key = strstr(temp, rssi_key.data()); + if (key == NULL) + { + return 0; + } + for(; (*key != '\0') && (*key != '\n') && (*key != '\r'); key++) + { + if ((*key >= '0') && (*key <= '9')) + { + return atoi(key); + } + } + return 0; +} + +bool WPAClient::ConnectWiFi(const std::string & ssid, const std::string & password) { + int net_id; + SetConnStatus(STEP_SCAN); + if (!CleanAllWiFi()) + { + return false; + } + print_info("CleanAllWiFi \n"); + if (!AddWiFi(net_id)) + { + return false; + } + print_info("AddWiFi \n"); + if (!SetSSID(ssid, net_id)) + { + return false; + } + print_info("SetSSID \n"); + if (!SetPassword(password, 0)) + { + return false; + } + if (!SetProtocol(net_id, 1)) + { + return false; + } + print_info("SetProtocol\n"); + SetScanSSID(net_id); + if (!EnableWiFi(net_id)) + { + return false; + } + print_info("EnableWiFi\n"); + return CheckCommandWithOk("SAVE_CONFIG"); + //return true; +} + +bool WPAClient::ConnectWiFiWithNoPassword(const std::string & ssid) +{ + int net_id; + SetConnStatus(STEP_SCAN); + if (!CleanAllWiFi()) + { + return false; + } + print_info("CleanAllWiFi\n"); + if (!AddWiFi(net_id)) + { + return false; + } + print_info("AddWiFi\n"); + if (!SetSSID(ssid, net_id)) + { + return false; + } + print_info("SetSSID\n"); + if (!SetProtocol(net_id, 0)) + { + return false; + } + print_info("SetProtocol\n"); + SetScanSSID(net_id); + if (!EnableWiFi(net_id)) + { + return false; + } + print_info("EnableWiFi\n"); + + return CheckCommandWithOk("SAVE_CONFIG"); +} + +bool WPAClient::ConnectWiFiWithLast() +{ + SetConnStatus(STEP_SCAN); + if (!CheckCommandWithOk("ENABLE_NETWORK all")) + { + return false; + } + return true; +} + +bool WPAClient::GetConnectStatus() { + std::string cmd = "STATUS"; + std::string recv; + int addr; + switch (step_) { + case STEP_SCAN: + if (!Request(wpa_context_, cmd, recv)) { + return false; + } + addr = recv.find("COMPLETED"); + if (addr == -1) { + return false; + } + SetConnStatus(STEP_CONNECT_AP_OK); + case STEP_CONNECT_AP_OK: + if (!dhcp_.Start("wlan0")) { + return false; + } + SetConnStatus(STEP_DHCP_IP); + case STEP_DHCP_IP: + if (!dhcp_.GetDHCPStatus()) { + return false; + } + SetConnStatus(STEP_SUCCESS); + case STEP_SUCCESS: + return true; + default: + return false; + } + return false; +} + +void WPAClient::SetConnStatus(ConnectStatus status) { + step_ = status; +} + +void WPAClient::wifiup() +{ + system("ifconfig mlan0 up"); + system("ifconfig mlan0 up"); + system("ifconfig mlan0 up"); +} + +bool WPAClient::CleanWifi() +{ + bool flag = CleanAllWiFi(); + CheckCommandWithOk("SAVE_CONFIG"); + return flag; +} + +int WPAClient::GetConnStatus() { + return step_; +} + +WPAContext * WPAClient::Open(const std::string & path) { + struct WPAContext *ctrl; + ctrl = (struct WPAContext*)malloc(sizeof(struct WPAContext)); + if (ctrl == NULL) { + print_error("malloc failed\n"); + return NULL; + } + memset(ctrl, 0, sizeof(struct WPAContext)); + static int counter = 0; + int ret; + int tries = 0; + size_t res; + ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0); + if (ctrl->s < 0) { + print_error("socket failed\n"); + free(ctrl); + return NULL; + } + ctrl->local.sun_family = AF_UNIX; + counter++; +try_again: + ret = snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), + "/tmp" "/" + "wpa_ctrl_" "%d-%d", + (int)getpid(), counter); + if (ret < 0 || (size_t)ret >= sizeof(ctrl->local.sun_path)) { + print_error("snprintf failed\n"); + close(ctrl->s); + free(ctrl); + return NULL; + } + tries++; + if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, + sizeof(ctrl->local)) < 0) { + if (errno == EADDRINUSE && tries < 2) { + /* + * getpid() returns unique identifier for this instance + * of wpa_ctrl, so the existing socket file must have + * been left by unclean termination of an earlier run. + * Remove the file and try again. + */ + unlink(ctrl->local.sun_path); + goto try_again; + } + print_error("bind failed\n"); + close(ctrl->s); + free(ctrl); + return NULL; + } + ctrl->dest.sun_family = AF_UNIX; + res = strlcpy(ctrl->dest.sun_path, wpa_control_path_.data(), + sizeof(ctrl->dest.sun_path)); + if (res >= sizeof(ctrl->dest.sun_path)) { + close(ctrl->s); + free(ctrl); + return NULL; + } + if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, + sizeof(ctrl->dest)) < 0) { + print_error("connect failed\n"); + close(ctrl->s); + unlink(ctrl->local.sun_path); + free(ctrl); + return NULL; + } + return ctrl; +} + +void WPAClient::Close(WPAContext * context) { + if (context == NULL) + return; + unlink(context->local.sun_path); + if (context->s >= 0) + close(context->s); + free(context); +} + +bool WPAClient::Request(WPAContext * context, const std::string & cmd, std::string& reply) { + int res; + fd_set rfds; + struct timeval tv; + const char *_cmd; + char *cmd_buf = NULL; + size_t _cmd_len; + _cmd = cmd.data(); + _cmd_len = cmd.length(); + if (wpa_context_ == NULL) { + print_error("wpa_context_ is null\n"); + return false; + } + if (send(wpa_context_->s, _cmd, _cmd_len, 0) < 0) { + free(cmd_buf); + return -1; + } + free(cmd_buf); + for (;;) { + tv.tv_sec = 10; + tv.tv_usec = 0; + FD_ZERO(&rfds); + FD_SET(wpa_context_->s, &rfds); + res = select(wpa_context_->s + 1, &rfds, NULL, NULL, &tv); + if (res < 0) + return false; + if (FD_ISSET(wpa_context_->s, &rfds)) { + char temp[1024] = {0}; + int temp_len = 1024; + res = recv(wpa_context_->s, temp, temp_len, 0); + if (res < 0) + return false; + if (res > 0 && temp[0] == '<') { + continue; + } + reply = temp; + break; + } else { + return false; + } + } + return true; +} + +bool WPAClient::CheckCommandWithOk(const std::string cmd) { + std::string recv; + if (!Request(wpa_context_, cmd, recv)) { + print_error("send cmd falied\n"); + return false; + } + print_error("recv cmd %s\n",recv.data()); + if (strstr(recv.data(), "OK") == NULL) { + return false; + } + return true; +} + +bool WPAClient::AddWiFi(int & id) { + std::string add_cmd = "ADD_NETWORK"; + std::string recv; + if (!Request(wpa_context_, add_cmd, recv)) { + return false; + } + id = atoi(recv.data()); + return true; +} + +bool WPAClient::SetScanSSID(int id) { + std::string cmd = "SET_NETWORK " + to_string(id) + " scan_ssid 1"; + return CheckCommandWithOk(cmd); +} +bool WPAClient::SetSSID(const std::string & ssid, int id) { + std::string cmd = "SET_NETWORK " + to_string(id) + " ssid " + "\"" + ssid + "\""; + return CheckCommandWithOk(cmd); +} +bool WPAClient::SetPassword(const std::string & password, int id) { + std::string cmd = "SET_NETWORK " + to_string(id) + " psk " + "\"" + password + "\""; + return CheckCommandWithOk(cmd); +} +bool WPAClient::SetProtocol(int id, int en_crypt) { + std::string cmd = "SET_NETWORK " + to_string(id); + if (en_crypt) { + cmd += " key_mgmt WPA-PSK"; + return CheckCommandWithOk(cmd); + } else { + cmd += " key_mgmt NONE"; + return CheckCommandWithOk(cmd); + } +} +bool WPAClient::CleanAllWiFi() { + CheckCommandWithOk("REMOVE_NETWORK all"); + CheckCommandWithOk("DISABLE_NETWORK all"); + return true; +} +bool WPAClient::EnableWiFi(int id) { + std::string cmd = "ENABLE_NETWORK " + to_string(id); + return CheckCommandWithOk(cmd); +} + +bool WPAClient::ReconnectWiFi() { + std::string cmd = "RECONNECT"; + return CheckCommandWithOk(cmd); +} +} diff --git a/wifi/wpa_client.h b/wifi/wpa_client.h new file mode 100644 index 0000000..c3d7d0e --- /dev/null +++ b/wifi/wpa_client.h @@ -0,0 +1,90 @@ +/* +# +# wifi连接接口 +# 说明:通过进程间通信与wpa_supplicant进行交互实现wifi连接 +# 注意:使用该接口的应用运行前要确保wpa_supplicant应用已经启动 +# 并且能明确进程间通信地址。 +# +*/ +#ifndef __WPA_CLIENT_H__ +#define __WPA_CLIENT_H__ +#include +#include +#include "../utility/SH_MySingleton.hpp" +#include "../common/SH_global.h" + +namespace wifi +{ +#ifdef G2UL_GATEWAY +const std::string WPA_PATH = "/var/run/wpa_supplicant/wlan0"; //进程间通信地址加上网络接口额名称 +#endif +#ifdef IMX6UL_GATEWAY +const std::string WPA_PATH = "/var/run/wpa_supplicant/wlan2"; //进程间通信地址加上网络接口额名称 +#endif +struct WPAContext +{ + int s; + struct sockaddr_un local; + struct sockaddr_un dest; +}; + +enum ConnectStatus +{ + STEP_SCAN = 0, + STEP_CONNECT_AP_OK, + STEP_DHCP_IP, + STEP_SUCCESS +}; +class MXDHCP +{ //dhcp ip地址的工具类,实现方法不算特别合理。可以根据具体情况进行更改 +public: + MXDHCP(); + ~MXDHCP(); + bool Start(const std::string& net_interface); + bool GetDHCPStatus(); +private: + bool CheckString(char *buf,int len); + FILE *pstream; +}; + +class WPAClient //: public MySingleton +{ +public: + WPAClient(const std::string& wpa_control_path = WPA_PATH); + ~WPAClient(); + bool GetInitStatus(){return wpa_context_!=NULL;} //获取wpa进程间通信是否建立连接 + int GetWiFiRssi(); //获取wifi信号强度,需要在连接成功之后调用 + std::string GetCurrentSSID(); //获取当前连接的wifi的名称 + bool ConnectWiFi(const std::string& ssid, const std::string& password); //连接加密wifi,传入wifi名称和密码 + bool ConnectWiFiWithNoPassword(const std::string& ssid); //连接无加密的wifi,传入wifi名称即可 + bool ConnectWiFiWithLast(); //直接连接上次已保存的wifi + bool GetConnectStatus(); //获取wifi连接状态 + std::string GetNetSsid(); + void wifiup(); //mlan0 up + bool CleanWifi(); + bool ReconnectWiFi(); //重新连接WIFI +protected: + bool Init(); + struct WPAContext* Open(const std::string& path); + void Close(struct WPAContext* context); + bool Request(struct WPAContext* context, const std::string& cmd,std::string& reply); + bool CheckCommandWithOk(const std::string cmd); + bool AddWiFi(int& id); + bool SetScanSSID(int id); + bool SetSSID(const std::string& ssid, int id); + bool SetPassword(const std::string& password, int id); + bool SetProtocol(int id, int en_crypt); + bool CleanAllWiFi(); + bool EnableWiFi(int id); + void SetConnStatus(ConnectStatus status); + int GetConnStatus(); +protected: + struct WPAContext* wpa_context_; + std::string wpa_control_path_; + MXDHCP dhcp_; +private: + int step_; +}; + +} +#endif // __WPA_CLIENT_H__