diff --git a/build/build.log b/build/build.log new file mode 100644 index 0000000..e69de29 diff --git a/clean.bat b/clean.bat new file mode 100644 index 0000000..efc0758 --- /dev/null +++ b/clean.bat @@ -0,0 +1,11 @@ +del build\GmAppMain.axf +del build\GmAppMain.bin +del build\GmAppMain.htm +del build\GmAppMain.map +del build\build.log +del build\*.o +del build\*.sym +del build\*.ex +del inc\app_date_time.h +del inc\trace_debug_flag.h +del output\* /Q diff --git a/cmd.exe b/cmd.exe new file mode 100644 index 0000000..1956add Binary files /dev/null and b/cmd.exe differ diff --git "a/doc/GPS\346\265\201\347\250\213\345\233\276.vsd" "b/doc/GPS\346\265\201\347\250\213\345\233\276.vsd" new file mode 100644 index 0000000..6fd0433 Binary files /dev/null and "b/doc/GPS\346\265\201\347\250\213\345\233\276.vsd" differ diff --git a/doc/GS03_MB_V1.1.pdf b/doc/GS03_MB_V1.1.pdf new file mode 100644 index 0000000..f46017b Binary files /dev/null and b/doc/GS03_MB_V1.1.pdf differ diff --git a/doc/GS05_MB_V2.1.pdf b/doc/GS05_MB_V2.1.pdf new file mode 100644 index 0000000..1632091 Binary files /dev/null and b/doc/GS05_MB_V2.1.pdf differ diff --git a/doc/GS10_MB_V1.0_0622A.pdf b/doc/GS10_MB_V1.0_0622A.pdf new file mode 100644 index 0000000..f2da720 Binary files /dev/null and b/doc/GS10_MB_V1.0_0622A.pdf differ diff --git a/doc/IHI0042F_aapcs.pdf b/doc/IHI0042F_aapcs.pdf new file mode 100644 index 0000000..efb17b8 Binary files /dev/null and b/doc/IHI0042F_aapcs.pdf differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide.html" new file mode 100644 index 0000000..1022dd1 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide.html" @@ -0,0 +1,14 @@ + + + + + + + + + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/MediaTek.PNG" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/MediaTek.PNG" new file mode 100644 index 0000000..b1032d9 Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/MediaTek.PNG" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/PMTK255.jpg" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/PMTK255.jpg" new file mode 100644 index 0000000..a68c7e6 Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/PMTK255.jpg" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/PMTK256.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/PMTK256.png" new file mode 100644 index 0000000..7c23c68 Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/PMTK256.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/PMTK810.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/PMTK810.png" new file mode 100644 index 0000000..7ca9c98 Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/PMTK810.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/_mtk___packet_8h_source.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/_mtk___packet_8h_source.html" new file mode 100644 index 0000000..1bc867c --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/_mtk___packet_8h_source.html" @@ -0,0 +1,223 @@ + + + + + + +MT33xx GNSS PMTK User's Guide: Source/Doxygen/PMTK/Mtk_Packet.h Source File + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
MT33xx GNSS PMTK User's Guide +  Version 1.2.0 +
+
+
+ + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Mtk_Packet.h
+
+
+
1 
2 #define COMM_PORT_INDEPENDENT_CONFIG
3 #define SUPPORT_SET_HDOP_THRESHOLD
4 //#define USING_REAL_HOST_BASE_PLATFORM
5 #define WN_OVERFLOW
6 #define ENABLE_XTAL_CALIBRATION
7 #define PER_TEST
8 #define SUPPORT_CHN_ROAD_VEHICLES_PROTOCOL
9 #define TELIT_SETTING
10 #define REDUCE_OUTPUT_THRESHOLD
11 
21 typedef enum {
329 #ifdef USING_REAL_HOST_BASE_PLATFORM
330 #else
331 
387 #endif
388 #ifndef USING_REAL_HOST_BASE_PLATFORM
389 #endif
390 
517 #ifdef COMM_PORT_INDEPENDENT_CONFIG
518 #endif
519 
597 PMTK_SET_AIC_CMD = 286, // active interference cancellation
598 #ifdef USING_REAL_HOST_BASE_PLATFORM
599 #else
600 #endif
601 
756 #ifndef TELIT_SETTING
757 #else
758 #ifdef COMM_PORT_INDEPENDENT_CONFIG
759 #endif
760 #endif
761 
781 #ifdef REDUCE_OUTPUT_THRESHOLD
782 
800 #endif
801 
840 #ifdef USING_REAL_HOST_BASE_PLATFORM
841 PMTK_API_SET_RTC_TIME = 335,
842 #endif
843 
936 #ifdef SUPPORT_SET_HDOP_THRESHOLD
937 
975 #endif
976 
1172 #ifdef REDUCE_OUTPUT_THRESHOLD
1173 
1190 #endif
1191 
1411 #ifdef REDUCE_OUTPUT_THRESHOLD
1412 
1427 #endif
1428 
1552 #ifdef COMM_PORT_INDEPENDENT_CONFIG
1553 #endif
1554 
1938 #ifdef USING_REAL_HOST_BASE_PLATFORM
1939 #endif
1940 
2066 #ifdef USING_REAL_HOST_BASE_PLATFORM
2067 #else
2068 #ifdef WN_OVERFLOW
2069 #endif
2070 #endif
2071 #ifdef USING_REAL_HOST_BASE_PLATFORM
2072 #ifdef WN_OVERFLOW
2073 #endif
2074 #else
2075 #endif
2076 #ifdef USING_REAL_HOST_BASE_PLATFORM
2077 #else
2078 #endif
2079 #ifdef ENABLE_XTAL_CALIBRATION
2080 #endif
2081 #ifdef PER_TEST
2082 #endif
2083 
2230 #ifndef USING_REAL_HOST_BASE_PLATFORM
2231 #endif
2232 #ifdef SUPPORT_CHN_ROAD_VEHICLES_PROTOCOL
2233 #endif
2234 } PMTK_PKT_TYPE_T;
2235 
2471 #endif
Definition: Mtk_Packet.h:36
+
Definition: Mtk_Packet.h:2012
+
Definition: Mtk_Packet.h:290
+
Definition: Mtk_Packet.h:1982
+
Definition: Mtk_Packet.h:1534
+
Definition: Mtk_Packet.h:1375
+
Definition: Mtk_Packet.h:56
+
Definition: Mtk_Packet.h:498
+
Definition: Mtk_Packet.h:433
+
Definition: Mtk_Packet.h:169
+
Definition: Mtk_Packet.h:1767
+
Definition: Mtk_Packet.h:1116
+
Definition: Mtk_Packet.h:2195
+
Definition: Mtk_Packet.h:1794
+
Definition: Mtk_Packet.h:1224
+
Definition: Mtk_Packet.h:861
+
Definition: Mtk_Packet.h:1258
+
Definition: Mtk_Packet.h:2065
+
Definition: Mtk_Packet.h:1482
+
Definition: Mtk_Packet.h:654
+
Definition: Mtk_Packet.h:707
+
Definition: Mtk_Packet.h:819
+
Definition: Mtk_Packet.h:215
+
Definition: Mtk_Packet.h:253
+
Definition: Mtk_Packet.h:916
+
Definition: Mtk_Packet.h:780
+
Definition: Mtk_Packet.h:1154
+
Definition: Mtk_Packet.h:1445
+
Definition: Mtk_Packet.h:1171
+
Definition: Mtk_Packet.h:1713
+
Definition: Mtk_Packet.h:1189
+
Definition: Mtk_Packet.h:2166
+
Definition: Mtk_Packet.h:92
+
Definition: Mtk_Packet.h:1060
+
Definition: Mtk_Packet.h:839
+
Definition: Mtk_Packet.h:2028
+
Definition: Mtk_Packet.h:1905
+
Definition: Mtk_Packet.h:1844
+
Definition: Mtk_Packet.h:880
+
Definition: Mtk_Packet.h:1025
+
Definition: Mtk_Packet.h:154
+
Definition: Mtk_Packet.h:671
+
Definition: Mtk_Packet.h:689
+
Definition: Mtk_Packet.h:618
+
Definition: Mtk_Packet.h:1426
+
Definition: Mtk_Packet.h:1276
+
Definition: Mtk_Packet.h:1466
+
Definition: Mtk_Packet.h:1097
+
Definition: Mtk_Packet.h:1937
+
Definition: Mtk_Packet.h:1410
+
Definition: Mtk_Packet.h:1881
+
Definition: Mtk_Packet.h:2128
+
Definition: Mtk_Packet.h:232
+
Definition: Mtk_Packet.h:1823
+
Definition: Mtk_Packet.h:307
+
Definition: Mtk_Packet.h:476
+
Definition: Mtk_Packet.h:386
+ +
Definition: Mtk_Packet.h:956
+
Definition: Mtk_Packet.h:755
+
Definition: Mtk_Packet.h:1864
+
Definition: Mtk_Packet.h:1659
+
Definition: Mtk_Packet.h:1603
+
Definition: Mtk_Packet.h:1997
+
Definition: Mtk_Packet.h:1329
+
Definition: Mtk_Packet.h:557
+
Definition: Mtk_Packet.h:1578
+
Definition: Mtk_Packet.h:538
+
Definition: Mtk_Packet.h:1310
+
Definition: Mtk_Packet.h:597
+
Definition: Mtk_Packet.h:1629
+
Definition: Mtk_Packet.h:1241
+
Definition: Mtk_Packet.h:2229
+
Definition: Mtk_Packet.h:186
+
Definition: Mtk_Packet.h:516
+
Definition: Mtk_Packet.h:328
+
Definition: Mtk_Packet.h:637
+
Definition: Mtk_Packet.h:799
+
Definition: Mtk_Packet.h:412
+
Definition: Mtk_Packet.h:974
+
Definition: Mtk_Packet.h:990
+
Definition: Mtk_Packet.h:1207
+
Definition: Mtk_Packet.h:454
+
Definition: Mtk_Packet.h:1293
+
PMTK_PKT_TYPE_T
This enum defines the type of PMTK command.
Definition: Mtk_Packet.h:21
+
Definition: Mtk_Packet.h:1077
+
Definition: Mtk_Packet.h:1043
+
Definition: Mtk_Packet.h:107
+
Definition: Mtk_Packet.h:76
+
Definition: Mtk_Packet.h:1137
+
Definition: Mtk_Packet.h:270
+
Definition: Mtk_Packet.h:1353
+
Definition: Mtk_Packet.h:2044
+
Definition: Mtk_Packet.h:1551
+
Definition: Mtk_Packet.h:1393
+
Definition: Mtk_Packet.h:935
+
Definition: Mtk_Packet.h:137
+
Definition: Mtk_Packet.h:2106
+
Definition: Mtk_Packet.h:579
+
Definition: Mtk_Packet.h:1517
+
Definition: Mtk_Packet.h:122
+
Definition: Mtk_Packet.h:1500
+
+
+ + + + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/arrowdown.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/arrowdown.png" new file mode 100644 index 0000000..0b63f6d Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/arrowdown.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/arrowright.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/arrowright.png" new file mode 100644 index 0000000..c6ee22f Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/arrowright.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/bc_s.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/bc_s.png" new file mode 100644 index 0000000..224b29a Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/bc_s.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/bdwn.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/bdwn.png" new file mode 100644 index 0000000..940a0b9 Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/bdwn.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/closed.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/closed.png" new file mode 100644 index 0000000..98cc2c9 Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/closed.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_29c008a3d6007eb363d0585658336295.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_29c008a3d6007eb363d0585658336295.html" new file mode 100644 index 0000000..b163f85 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_29c008a3d6007eb363d0585658336295.html" @@ -0,0 +1,125 @@ + + + + + + +MT33xx GNSS PMTK User's Guide: Source/Doxygen/PMTK Directory Reference + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
MT33xx GNSS PMTK User's Guide +  Version 1.2.0 +
+
+
+ + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
PMTK Directory Reference
+
+
+ + +

+Files

+
+
+ + + + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_29c008a3d6007eb363d0585658336295.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_29c008a3d6007eb363d0585658336295.js" new file mode 100644 index 0000000..951bdcf --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_29c008a3d6007eb363d0585658336295.js" @@ -0,0 +1,4 @@ +var dir_29c008a3d6007eb363d0585658336295 = +[ + [ "Mtk_Packet.h", "_mtk___packet_8h_source.html", null ] +]; \ No newline at end of file diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_47892d94e1d0bf342f4cec549ae2e06e.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_47892d94e1d0bf342f4cec549ae2e06e.html" new file mode 100644 index 0000000..49b7837 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_47892d94e1d0bf342f4cec549ae2e06e.html" @@ -0,0 +1,125 @@ + + + + + + +MT33xx GNSS PMTK User's Guide: Source/Doxygen Directory Reference + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
MT33xx GNSS PMTK User's Guide +  Version 1.2.0 +
+
+
+ + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Doxygen Directory Reference
+
+
+ + +

+Directories

+
+
+ + + + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_47892d94e1d0bf342f4cec549ae2e06e.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_47892d94e1d0bf342f4cec549ae2e06e.js" new file mode 100644 index 0000000..b4a4d40 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_47892d94e1d0bf342f4cec549ae2e06e.js" @@ -0,0 +1,4 @@ +var dir_47892d94e1d0bf342f4cec549ae2e06e = +[ + [ "PMTK", "dir_29c008a3d6007eb363d0585658336295.html", "dir_29c008a3d6007eb363d0585658336295" ] +]; \ No newline at end of file diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_74389ed8173ad57b461b9d623a1f3867.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_74389ed8173ad57b461b9d623a1f3867.html" new file mode 100644 index 0000000..95c4abd --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_74389ed8173ad57b461b9d623a1f3867.html" @@ -0,0 +1,125 @@ + + + + + + +MT33xx GNSS PMTK User's Guide: Source Directory Reference + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
MT33xx GNSS PMTK User's Guide +  Version 1.2.0 +
+
+
+ + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Source Directory Reference
+
+
+ + +

+Directories

+
+
+ + + + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_74389ed8173ad57b461b9d623a1f3867.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_74389ed8173ad57b461b9d623a1f3867.js" new file mode 100644 index 0000000..f975c20 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dir_74389ed8173ad57b461b9d623a1f3867.js" @@ -0,0 +1,4 @@ +var dir_74389ed8173ad57b461b9d623a1f3867 = +[ + [ "Doxygen", "dir_47892d94e1d0bf342f4cec549ae2e06e.html", "dir_47892d94e1d0bf342f4cec549ae2e06e" ] +]; \ No newline at end of file diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/doc.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/doc.png" new file mode 100644 index 0000000..17edabf Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/doc.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/doxygen.css" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/doxygen.css" new file mode 100644 index 0000000..1425ec5 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/doxygen.css" @@ -0,0 +1,1475 @@ +/* The standard CSS for doxygen 1.8.11 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd { + margin-top: 2px; +} + +p.starttd { + margin-top: 0px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 4px 6px; + margin: 4px 8px 4px 2px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line:after { + content:"\000A"; + white-space: pre; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah, span.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000 110%); +} + +div.classindex ul { + list-style: none; + padding-left: 0; +} + +div.classindex span.ai { + display: inline-block; +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view inside a (index) page */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #9CAFD4; + border-bottom: 1px solid #9CAFD4; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +.arrow { + color: #9CAFD4; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 22px; +} + +.icon { + font-family: Arial, Helvetica; + font-weight: bold; + font-size: 12px; + height: 14px; + width: 16px; + display: inline-block; + background-color: #728DC1; + color: white; + text-align: center; + border-radius: 4px; + margin-left: 2px; + margin-right: 2px; +} + +.icona { + width: 24px; + height: 22px; + display: inline-block; +} + +.iconfopen { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderopen.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.iconfclosed { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderclosed.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.icondoc { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('doc.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +table.directory { + font: 400 14px Roboto,sans-serif; +} + +/* @end */ + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable caption { + caption-side: top; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +table.classindex +{ + margin: 10px; + white-space: nowrap; + margin-left: 3%; + margin-right: 3%; + width: 94%; + border: 0; + border-spacing: 0; + padding: 0; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectalign +{ + vertical-align: middle; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.diagraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 8px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/doxygen.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/doxygen.png" new file mode 100644 index 0000000..3ff17d8 Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/doxygen.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dynsections.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dynsections.js" new file mode 100644 index 0000000..85e1836 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/dynsections.js" @@ -0,0 +1,97 @@ +function toggleVisibility(linkObj) +{ + var base = $(linkObj).attr('id'); + var summary = $('#'+base+'-summary'); + var content = $('#'+base+'-content'); + var trigger = $('#'+base+'-trigger'); + var src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.hide(); + summary.show(); + $(linkObj).addClass('closed').removeClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); + } else { + content.show(); + summary.hide(); + $(linkObj).removeClass('closed').addClass('opened'); + $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); + } + return false; +} + +function updateStripes() +{ + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); +} + +function toggleLevel(level) +{ + $('table.directory tr').each(function() { + var l = this.id.split('_').length-1; + var i = $('#img'+this.id.substring(3)); + var a = $('#arr'+this.id.substring(3)); + if (l + + + + + +MT33xx GNSS PMTK User's Guide: File List + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
MT33xx GNSS PMTK User's Guide +  Version 1.2.0 +
+
+
+ + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
File List
+
+
+
Here is a list of all documented files with brief descriptions:
+
[detail level 1234]
+ + + + +
  Source
  Doxygen
  PMTK
 Mtk_Packet.h
+
+
+
+ + + + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/files.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/files.js" new file mode 100644 index 0000000..e370db4 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/files.js" @@ -0,0 +1,4 @@ +var files = +[ + [ "Source", "dir_74389ed8173ad57b461b9d623a1f3867.html", "dir_74389ed8173ad57b461b9d623a1f3867" ] +]; \ No newline at end of file diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/folderclosed.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/folderclosed.png" new file mode 100644 index 0000000..bb8ab35 Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/folderclosed.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/folderopen.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/folderopen.png" new file mode 100644 index 0000000..d6c7f67 Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/folderopen.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/group__pmtk__appendix.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/group__pmtk__appendix.html" new file mode 100644 index 0000000..56bd3ec --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/group__pmtk__appendix.html" @@ -0,0 +1,571 @@ + + + + + + +MT33xx GNSS PMTK User's Guide: Appendix + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
MT33xx GNSS PMTK User's Guide +  Version 1.2.0 +
+
+
+ + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Appendix
+
+
+ +

This chapter shows some usefull table. +More...

+

This chapter shows some usefull table.

+

+Datum List

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
No Datum Region
0 WGS1984 International
1 Tokyo Japan
2 Tokyo Mean For Japan, South Korea, Okinawa
3 User Setting User Setting
4 Adindan Burkina Faso
5 Adindan Cameroon
6 Adindan Ethiopia
7 Adindan Mali
8 Adindan Mean For Ethiopia, Sudan
9 Adindan Senegal
10 Adindan Sudan
11 Afgooye Somalia
12 Ain El Abd1970 Bahrain
13 Ain El Abd1970 Saudi Arabia
14 American Samoa1962 American Samoa Islands
15 Anna 1 Astro1965 Cocos Island
16 Antigua Island Astro1943 Antigua(Leeward Islands)
17 Arc1950 Botswana
18 Arc1950 Burundi
19 Arc1950 Lesotho
20 Arc1950 Malawi
21 Arc1950 Mean For Botswana, Lesotho, Malawi, Swaziland, Zaire, Zambia, Zimbabwe
22 Arc1950 Swaziland
23 Arc1950 Zaire
24 Arc1950 Zambia
25 Arc1950 Zimbabwe
26 Arc1960 Mean For Kenya Tanzania
27 Arc1960 Kenya
28 Arc1960 Tamzamia
29 Ascension Island1958 Ascension Island
30 Astro Beacon E 1945 Iwo Jima
31 Astro Dos 71/4 St Helena Island
32 Astro Tern Island (FRIG) 1961 Tern Island
33 Astronomical Station 1952 Marcus Island
34 Australian Geodetic 1966 Australia, Tasmania
35 Australian Geodetic 1984 Australia, Tasmania
36 Ayabelle Lighthouse Djibouti
37 Bellevue (IGN) Efate and Erromango Islands
38 Bermuda 1957 Bermuda
39 Bissau Guuinea-Bissau
40 Bogota Observatory Colombia
41 Bukit Rimpah Indonesia(Bangka and Belitung Ids)
42 Camp Area Astro Antarctica(McMurdi Camp Area)
43 Campo Inchauspe Argentina
44 Canton Astro1966 Phoenix Island
45 Cape South Africa
46 Cape Canaveral Bahamas, Florida
47 Carthage Tunisia
48 Chatham Island Astro1971 New Zealand(Chatham Island)
49 Chua Astro Paraguay
50 Corrego Alegre Brazil
51 Dabola Guinea
52 Deception Island Deception Island, Antarctia
53 Djakarta (Batavia) Indonesia(Sumatra)
54 Dos 1968 New Georgia Islands (Gizo Island)
55 Easter Island 1967 Easter Island
56 Estonia Coordinate System1937 Estonia
57 European 1950 Cyprus
58 European 1950 Egypt
59 European 1950 England, Channel Islands, Scotland, Shetland Islands
60 European 1950 England, Ireland, Scotland, Shetland Islands
61 European 1950 Finland, Norway
62 European 1950 Greece
63 European 1950 Iran
64 European 1950 Italy (Sardinia)
65 European 1950 Italy (Slcily)
66 European 1950 Malta
67 European 1950 Mean For Austria, Belgium,Denmark, Finland, France, W Germany, Gibraltar, Greece, Italy, Luxembourg, Netherlands, Norway, Portuga,l Spain, Sweden, Switzerland
68 European 1950 Mean For Austria, Debnmark,France, W Germany, Netherland ,Switzerland
69 European 1950 Mean For Irag, Israel, Jordan, Lebanon, Kuwait, Saudi Arabia, Syria
70 European 1950 Portugal, Spain
71 European 1950 Tunisia,
72 European 1979 Mean For Austria, Finland ,Netherlands ,Norway, Spain, Sweden, Switzerland
73 Fort Thomas 1955 Nevis St Kitts (Leeward Islands)
74 Gan 1970 Republic Of Maldives
75 Geodetic Dataum 1970 New Zealand
76 Graciosa Base SW1948 Azores (Faial, Graciosa, Pico, Sao, Jorge, Terceria)
77 Guam1963 Guam
78 Gunung Segara Indonesia (Kalimantan)
79 Gux l Astro Guadalcanal Island
80 Herat North Afghanistan
81 Hermannskogel Datum Croatia-Serbia, Bosnia-Herzegoivna
82 Hjorsey 1955 Iceland
83 Hongkong 1963 Hongkong
84 Hu Tzu Shan Taiwan
85 Indian Bangladesh
86 Indian India,Nepal
87 Indian Pakistan
88 Indian 1954 Thailand
89 Indian 1960 Vietnam (Con Son Island)
90 Indian 1960 Vietnam (Near 16 deg N)
91 Indian 1975 Thailand
92 Indonesian 1974 Indonesian
93 Ireland 1965 Ireland
94 ISTS 061 Astro 1968 South Georgia Islands
95 ISTS 073 Astro 1969 Diego Garcia
96 Johnston Island 1961 Johnston Island
97 Kandawala Sri Lanka
98 Kerguelen Island 1949 Kerguelen Island
99 Kertau 1948 West Malaysia and Singapore
100 Kusaie Astro 1951 Caroline Islands
101 Korean Geodetic System South Korea
102 LC5 Astro 1961 Cayman Brac Island
103 Leigon Ghana
104 Liberia 1964 Liberia
105 Luzon Philippines (Excluding Mindanao)
106 Luzon Philippines (Mindanao)
107 M'Poraloko Gabon
108 Mahe 1971 Mahe Island
109 Massawa Ethiopia (Eritrea)
110 Merchich Morocco
111 Midway Astro 1961 Midway Islands
112 Minna Cameroon
113 Minna Nigeria
114 Montserrat Island Astro 1958 Montserrat (Leeward Island)
115 Nahrwan Oman (Masirah Island)
116 Nahrwan Saudi Arabia
117 Nahrwan United Arab Emirates
118 Naparima BWI Trinidad and Tobago
119 North American 1927 Alaska (Excluding Aleutian Ids)
120 North American 1927 Alaska (Aleutian Ids East of 180 degW)
121 North American 1927 Alaska (Aleutian Ids West of 180 degW)
122 North American 1927 Bahamas (Except San Salvador Islands)
123 North American 1927 Bahamas (San Salvador Islands)
124 North American 1927 Canada (Alberta, British Columbia)
125 North American 1927 Canada (Manitoba, Ontario)
126 North American 1927 Canada (New Brunswick, Newfoundland, Nova Scotia, Qubec)
127 North American 1927 Canada (Northwest Territories, Saskatchewan)
128 North American 1927 Canada (Yukon)
129 North American 1927 Canal Zone
130 North American 1927 Cuba
131 North American 1927 Greenland (Hayes Peninsula)
132 North American 1927 Mean For Antigua, Barbados, Barbuda, Caicos Islands, Cuba, Dominican, Grand Cayman, Jamaica, Turks Islands
133 North American 1927 Mean For Belize, Costa Rica, El Salvador, Guatemala, Honduras, Nicaragua
134 North American 1927 Mean For Canada
135 North American 1927 Mean For Conus
136 North American 1927 Mean For Conus (East of Mississippi, River Including Louisiana,Missouri, Minnesota)
137 North American 1927 Mean For Conus (West of Mississippi, Rive Excluding Louisiana, Minnesota, Missouri)
138 North American 1927 Mexico
139 North American 1983 Alaska (Excluding Aleutian Ids)
140 North American 1983 Aleutian Ids
141 North American 1983 Canada
142 North American 1983 Conus
143 North American 1983 Hahawii
144 North American 1983 Mexico, Central America
145 North Sahara 1959 Algeria
146 Observatorio Meteorologico 1939 Azores (Corvo and Flores Islands)
147 Old Egyptian 1907 Egypt
148 Old Hawaiian Hawaii
149 Old Hawaiian Kauai
150 Old Hawaiian Maui
151 Old Hawaiian Mean For Hawaii, Kauai, Maui, Oahu
152 Old Hawaiian Oahu
153 Oman Oman
154 Ordnance Survey Great Britian 1936 England
155 Ordnance Survey Great Britian 1936 England, Isle of Man, Wales
156 Ordnance Survey Great Britian 1936 Mean For England ,Isle of Man, Scotland, Shetland Island, Wales
157 Ordnance Survey Great Britian 1936 Scotland, Shetland Islands
158 Ordnance Survey Great Britian 1936 Wales
159 Pico de las Nieves Canary Islands
160 Pitcairn Astro 1967 Pitcairn Island
161 Point 58 Mean For Burkina Faso and Niger
162 Pointe Noire 1948 Congo
163 Porto Santo 1936 Porto Santo, Maderia Islands
164 Provisional South American 1956 Bolovia
165 Provisional South American 1956 Chile (Northern Near 19 deg S)
166 Provisional South American 1956 Chile (Southern Near 43 deg S)
167 Provisional South American 1956 Colombia
168 Provisional South American 1956 Ecuador
169 Provisional South American 1956 Guyana
170 Provisional South American 1956 Mean For Bolivia Chile,Colombia, Ecuador, Guyana, Peru, Venezuela
171 Provisional South American 1956 Peru
172 Provisional South American 1956 Venezuela
173 Provisional South Chilean 1963 Chile (Near 53 deg S) (Hito XVIII)
174 Puerto Rico Puerto Rico, Virgin Islands
175 Pulkovo 1942 Russia
176 Qatar National Qatar
177 Qornoq Greenland (South)
178 Reunion Mascarene Island
179 Rome 1940 Italy (Sardinia)
180 S-42 (Pulkovo 1942) Hungary
181 S-42 (Pulkovo 1942) Poland
182 S-42 (Pulkovo 1942) Czechoslavakia
183 S-42 (Pulkovo 1942) Lativa
184 S-42 (Pulkovo 1942) Kazakhstan
185 S-42 (Pulkovo 1942) Albania
186 S-42 (Pulkovo 1942) Romania
187 S-JTSK Czechoslavakia (Prior 1 Jan1993)
188 Santo (Dos) 1965 Espirito Santo Island
189 Sao Braz Azores (Sao Miguel, Santa Maria Ids)
190 Sapper Hill 1943 East Falkland Island
191 Schwarzeck Namibia
192 Selvagem Grande 1938 Salvage Islands
193 Sierra Leone 1960 Sierra Leone
194 South American 1969 Argentina
195 South American 1969 Bolivia
196 South American 1969 Brazial
197 South American 1969 Chile
198 South American 1969 Colombia
199 South American 1969 Ecuador
200 South American 1969 Ecuador (Baltra, Galapagos)
201 South American 1969 Guyana
202 South American 1969 Mean For Argentina, Bolivia, Brazil,Chile, Colombia, Ecuador, Guyana, Paraguay, Peru, Trinidad and Tobago, Venezuela
203 South American 1969 Paraguay
204 South American 1969 Peru
205 South American 1969 Trinidad and Tobago
206 South American 1969 Venezuela
207 South Asia Singapore
208 Tananarive Observatory 1925 Madagascar
209 Timbalai 1948 Brunei, E Malaysia (Sabah Sarawak)
210 Tokyo Japan
211 Tokyo Mean For Japan, South Korea, Okinawa
212 Tokyo Okinawa
213 Tokyo South Korea
214 Tristan Astro 1968 Tristam Da Cunha
215 Viti Levu 1916 Fiji (Viti Levu Island)
216 Voirol 1960 Algeria
217 Wake Island Astro 1952 Wake Atoll
218 Wake-Eniwetok 1960 Marshall Islands
219 WGS 1972 Global Definition
220 WGS 1984 Global Definition
221 Yacare Uruguay
222 Zanderij Suriname
+
+
+ + + + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/group__pmtk__command.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/group__pmtk__command.html" new file mode 100644 index 0000000..6b1e47c --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/group__pmtk__command.html" @@ -0,0 +1,2407 @@ + + + + + + +MT33xx GNSS PMTK User's Guide: PMTK Command + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
MT33xx GNSS PMTK User's Guide +  Version 1.2.0 +
+
+
+ + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+ +
+
PMTK Command
+
+
+ +

PMTK command is a MediaTek proprietary GNSS data transfer protocol. +More...

+

Overview

+

PMTK command is a MediaTek proprietary GNSS data transfer protocol.

+

This protocol is used to configure the GNSS module's parameters, aiding information and to receive notification from the GNSS module. The PMTK aligns with the NMEA sentence format to process data more conveniently.

+ + + + + +

+Enumerations

enum  PMTK_PKT_TYPE_T {
+  PMTK_TEST = 0, +
+  PMTK_ACK = 1, +
+  PMTK_SYS_MSG = 10, +
+  PMTK_TXT_MSG = 11, +
+  PMTK_CMD_HOT_START = 101, +
+  PMTK_CMD_WARM_START = 102, +
+  PMTK_CMD_COLD_START = 103, +
+  PMTK_CMD_FULL_COLD_START = 104, +
+  PMTK_CMD_CLEAR_EPO = 127, +
+  PMTK_CMD_STANDBY_MODE = 161, +
+  PMTK_LOCUS_QUERY_STATUS = 183, +
+  PMTK_LOCUS_ERASE_FLASH = 184, +
+  PMTK_LOCUS_STOP_LOGGER = 185, +
+  PMTK_LOCUS_LOG_NOW = 186, +
+  PMTK_LOCUS_CONFIG = 187, +
+  PMTK_SET_POS_FIX = 220, +
+  PMTK_SET_AL_DEE_CFG = 223, +
+  PMTK_SET_PERIODIC_MODE = 225, +
+  PMTK_SET_DATA_PORT = 250, +
+  PMTK_SET_NMEA_BAUDRATE = 251, +
+  PMTK_SET_OUTPUT_FMT = 253, +
+  PMTK_SET_SYNC_PPS_NMEA = 255, +
+  PMTK_SET_TIMING_PRODUCT = 256, +
+  PMTK_SET_HIGH_ACCURACY = 257, +
+  PMTK_SET_GLP_MODE = 262, +
+  PMTK_SET_NMEA_DECIMAL_PRECISION = 265, +
+  PMTK_SET_PPS_CONFIG_CMD = 285, +
+  PMTK_SET_AIC_CMD = 286, +
+  PMTK_SET_OUTPUT_DEBUG = 299, +
+  PMTK_API_SET_DGPS_MODE = 301, +
+  PMTK_API_SET_MIN_SNR = 306, +
+  PMTK_API_SET_DR_LIMIT = 308, +
+  PMTK_API_SET_ELEV_MASK = 311, +
+  PMTK_API_SET_SBAS_ENABLED = 313, +
+  PMTK_API_SET_NMEA_OUTPUT = 314, +
+  PMTK_API_SET_PPS = 326, +
+  PMTK_API_SET_HACC_MASK = 328, +
+  PMTK_API_SET_DATUM = 330, +
+  PMTK_API_SET_DATUM_ADVANCE = 331, +
+  PMTK_API_SET_SUPPORT_QZSS_NMEA = 351, +
+  PMTK_API_SET_STOP_QZSS = 352, +
+  PMTK_API_SET_GNSS_SEARCH_MODE = 353, +
+  PMTK_API_GET_GNSS_OPERAT_MODE = 355, +
+  PMTK_API_SET_HDOP_THRESHOLD = 356, +
+  PMTK_API_GET_HDOP_THRESHOLD = 357, +
+  PMTK_API_SET_PLL = 381, +
+  PMTK_API_SET_HIGH_SENSITIVITY_TRACKING_NO_FIX = 385, +
+  PMTK_API_SET_STATIC_NAVI_THD = 386, +
+  PMTK_API_SET_FLASH_DATA = 399, +
+  PMTK_API_Q_FIX_CTL = 400, +
+  PMTK_API_Q_DGPS_MODE = 401, +
+  PMTK_API_Q_MIN_SNR = 406, +
+  PMTK_API_Q_DR_LIMIT = 408, +
+  PMTK_API_Q_ELEV_MASK = 411, +
+  PMTK_API_Q_SBAS_ENABLED = 413, +
+  PMTK_API_Q_NMEA_OUTPUT = 414, +
+  PMTK_API_Q_HACC_MASK = 428, +
+  PMTK_API_Q_DATUM = 430, +
+  PMTK_API_Q_DATUM_ADVANCE = 431, +
+  PMTK_API_Q_RTC_TIME = 435, +
+  PMTK_API_Q_HIGH_SENSITIVITY_TRACKING_NO_FIX = 436, +
+  PMTK_API_Q_EPH_STATUS = 449, +
+  PMTK_API_GET_POS_XYZ = 458, +
+  PMTK_API_GET_VEL_XYZ = 461, +
+  PMTK_API_GET_FLASH_DATA = 499, +
+  PMTK_DT_FIX_CTL = 500, +
+  PMTK_DT_DGPS_MODE = 501, +
+  PMTK_DT_SBAS_ENABLED = 513, +
+  PMTK_DT_NMEA_OUTPUT = 514, +
+  PMTK_DT_HACC_MASK = 528, +
+  PMTK_DT_DATUM = 530, +
+  PMTK_DT_RTC_TIME = 535, +
+  PMTK_DT_HIGH_SENSITIVITY_TRACKING_NO_FIX = 536, +
+  PMTK_DT_FLASH_DATA = 599, +
+  PMTK_Q_DATA_PORT = 602, +
+  PMTK_Q_RELEASE = 605, +
+  PMTK_Q_EPO_INFO = 607, +
+  PMTK_Q_LOCUS_DATA = 622, +
+  PMTK_Q_AVAILABLE_SV_EPH = 660, +
+  PMTK_Q_AVAILABLE_SV_ALM = 661, +
+  PMTK_Q_UTC_CORRECTION_DATA = 667, +
+  PMTK_Q_GPS_KEP = 668, +
+  PMTK_Q_BDS_KEP = 669, +
+  PMTK_Q_GPS_IONO = 670, +
+  PMTK_DT_DATA_PORT = 702, +
+  PMTK_DT_RELEASE = 705, +
+  PMTK_DT_EPO_INFO = 707, +
+  PMTK_DT_SV_EPO = 721, +
+  PMTK_DT_UTC = 740, +
+  PMTK_DT_POS = 741, +
+  PMTK_TEST_ALL = 810, +
+  PMTK_TEST_STOP = 811, +
+  PMTK_TEST_FINISH = 812, +
+  PMTK_TEST_ALL_ACQ = 813, +
+  PMTK_TEST_ALL_BITSYNC = 814, +
+  PMTK_TEST_ALL_SIGNAL = 815, +
+  PMTK_TEST_JAMMING = 837, +
+  PMTK_TEST_JAMMING_DETECTION = 838, +
+  PMTK_EASY_ENABLE = 869, +
+  PTMK_PMTKLSC_STN_OUTPUT = 875, +
+  PMTK_FR_MODE = 886 +
+ }
 This enum defines the type of PMTK command. More...
 
+

Enumeration Type Documentation

+ +
+
+ + + + +
enum PMTK_PKT_TYPE_T
+
+ +

This enum defines the type of PMTK command.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Enumerator
PMTK_TEST  +
+[Packet Type]
+ 000
+[Command]
+ PMTK_TEST
+[Description]
+   Test Packet.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Example]
+   $PMTK000*32<CR><LF>
+
PMTK_ACK  +
+[Packet Type]
+ 001
+[Command]
+ PMTK_ACK
+[Description]
+   Acknowledge of PMTK command.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK001,Cmd,Flag*CS<CR><LF>
+   Cmd: The command / packet type the acknowledge responds.
+   Flag: '0' = Invalid command / packet.
+   '1' = Unsupported command / packet type
+   '2' = Valid command / packet, but action failed
+   '3' = Valid command / packet, and action succeeded
+[Example]
+   $PMTK001,604,3*32<CR><LF>
+
PMTK_SYS_MSG  +
+[Packet Type]
+ 010
+[Command]
+ PMTK_SYS_MSG
+[Description]
+   System output message.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK010,Type*CS<CR><LF>
+   Type: The system message type.
+   "0", UNKNOWN
+   "1", STARTUP
+   "2", Notification for the host aiding EPO. 
+   "3", Notification for the transition to Normal mode completes successfully.
+[Example]
+   $PMTK010,001*2E<CR><LF>
+
PMTK_TXT_MSG  +
+[Packet Type]
+ 011
+[Command]
+ PMTK_TXT_MSG
+[Description]
+   Output system text message.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK011,msg*CS<CR><LF>
+   msg: The system text message.
+[Example]
+   $PMTK011,MTKGPS*08 <CR><LF>
+
PMTK_CMD_HOT_START  +
+[Packet Type]
+ 101
+[Command]
+ PMTK_CMD_HOT_START
+[Description]
+   Hot Start. Use the available data in the NVRAM.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Example]
+   $PMTK101*32<CR><LF>
+
PMTK_CMD_WARM_START  +
+[Packet Type]
+ 102
+[Command]
+ PMTK_CMD_WARM_START
+[Description]
+   Warm Start. Not using Ephemeris data at start.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Example]
+   $PMTK102*31<CR><LF>
+
PMTK_CMD_COLD_START  +
+[Packet Type]
+ 103
+[Command]
+ PMTK_CMD_COLD_START
+[Description]
+   Cold Start. Not using the Position, Almanac and Ephemeris data at start. 
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Example]
+   $PMTK103*30<CR><LF>
+
PMTK_CMD_FULL_COLD_START  +
+[Packet Type]
+ 104
+[Command]
+ PMTK_CMD_FULL_COLD_START
+[Description]
+   Full Cold Start.
+   In addition to Cold start, this command clears the system/user configurations at start. 
+   It resets the GNSS module to the factory default.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Example]
+   $PMTK104*37<CR><LF>
+
PMTK_CMD_CLEAR_EPO  +
+[Packet Type]
+ 127
+[Command]
+ PMTK_CMD_CLEAR_EPO
+[Description]
+   Erase the EPO data stored in the flash memory. 
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Example]
+   $PMTK127*36<CR><LF>
+
PMTK_CMD_STANDBY_MODE  +
+[Packet Type]
+ 161
+[Command]
+ PMTK_CMD_STANDBY_MODE
+[Description]
+   Enter standby modes (stop mode or sleep mode) for power saving. 
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK161,Type*CS<CR><LF>
+   Type: "0". Stop mode.
+   "1". Sleep mode.
+[Example]
+   $PMTK161,1*29<CR><LF>
+
PMTK_LOCUS_QUERY_STATUS  +
+[Packet Type]
+ 183
+[Command]
+ PMTK_LOCUS_QUERY_STATUS
+[Description]
+   Query the GNSS is in the log status or not.
+   Keep status after reboot –> No.
+[Data Field]
+   NONE
+[Return]
+   $PMTKLOG,Serial#,Type, Mode, Content, Interval, Distance, Speed, Status, Log number, Percentage*CH 
+   Serial#: Logging serial number : 0~65535 
+   Type: Logging type - 0: Overlap, 1: FullStop 
+   Mode: Logging mode - 0x08 : Interval logger 
+   Content: Logging contents of configuration 
+   Interval: Logging interval setting (valid when interval mode is selected) 
+   Distance: Logging distance setting (valid when distance mode is selected) 
+   Speed: Logging speed setting (valid when speed mode is selected) 
+   Status : Logging status - 1: Stop Logging, 0: Logging 
+   Percentage : Logging life used percentage 
+[Example]
+    Input : PMTK183*38<CR><LF> 
+   Output : $PMTKLOG,32,1,b,31,1,0,0,0,8032,100*2F<CR><LF> 
+[Note]
+   This feature can't use when data cache (PMTK189) is running. This command will get error response when data cache is running.
+
PMTK_LOCUS_ERASE_FLASH  +
+[Packet Type]
+ 184
+[Command]
+ PMTK_LOCUS_ERASE_FLASH
+[Description]
+   Erase the logged GNSS data on the flash.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK184,Type*CS<CR><LF>
+   Type: Erase type   '1': erase the logged internal flash data.
+[Example]
+   Input : PMTK184,1*22<CR><LF>
+   Output: $PMTK001,184,3*3D<CR><LF>
+
PMTK_LOCUS_STOP_LOGGER  +
+[Packet Type]
+ 185
+[Command]
+ PMTK_LOCUS_STOP_LOGGER
+[Description]
+   Stop the data logging.
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK185,Status*CS<CR><LF>
+   Status: Stop logging
+   '1': Stop logging
+   '0': Start logging
+[Example]
+   Input : PMTK185,1*23<CR><LF>
+   Output: $PMTK001,185,3*3C<CR><LF>
+[Note]
+   This feature can't use when data cache (PMTK189) is running. Please don't set any data cache configuration when LOCUS is running.
+
PMTK_LOCUS_LOG_NOW  +
+[Packet Type]
+ 186
+[Command]
+ PMTK_LOCUS_LOG_NOW
+[Description]
+   Snapshot write log.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK186, Type*CS<CR><LF>
+   Type: '1': Snapshot data logging.
+[Example]
+   Input : $PMTK186,1*20<CR><LF>
+   Output:$PMTK001,186,3*3F<CR><LF>
+
PMTK_LOCUS_CONFIG  +
+[Packet Type]
+ 187
+[Command]
+ PMTK_LOCUS_CONFIG
+[Description]
+   Configure Locus settings by command.  
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK187, mode, setting*CS<CR><LF>
+   mode: "1", interval mode.(1sec<=Interval<=12hours)
+   setting: New setting instead of the original configuration (e.g. change to 5 seconds interval as the example below) 
+[Example]
+   Input: $PMTK187,1,5*38<CR><LF>
+   Output: $PMTK001,187,3*3E<CR><LF>
+[Note]
+   This feature can't use when data cache (PMTK189) is running. Please don't set any data cache configuration when LOCUS is running.
+
PMTK_SET_POS_FIX  +
+[Packet Type]
+ 220
+[Command]
+ PMTK_SET_POS_FIX
+[Description]
+   Position Fix Interval.
+   This command only for test.
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK220,time*CS<CR><LF>
+   time: Position fix interval in milliseconds (ms). 
+[Example]
+   $PMTK220,1000*1F<CR><LF>
+
PMTK_SET_AL_DEE_CFG  +
+[Packet Type]
+ 223
+[Command]
+ PMTK_SET_AL_DEE_CFG
+[Description]
+   Used for setting periodic mode parameters and is used after PMTK225 command.
+   Keep status after reboot –> Yes.
+[Data Field]
+$ PMTK223, SV, SNR, Extension Threshold, Extension gap*CS<CR><LF>
+   Below parameters can be modified by Host command message
+   SV: The range is from 1 to 4. Default value is 1.
+   SNR: The range is from 25 to 30. Default value is 30.
+   Extension Threshold: The range is from 40000 to 180000.Default value is 180000 ms.
+   Extension gap: The range is from 0 to 3600000. Default value is 60000 msec
+   (Extension gap is the limitation between neighboring Dynamic Ephemeris Extension (DEE)).
+[Example]
+   $PMTK223,1,32,180000,60000*3E<CR><LF>
+
PMTK_SET_PERIODIC_MODE  +
+[Packet Type]
+ 225
+[Command]
+ PMTK_SET_PERIODIC_MODE
+[Description]
+   Periodic Power Saving Mode Settings: (See following chart).
+   In RUN stage, the GNSS module measures and calculates the position.
+   In SLEEP stage, the GNSS module may enter two different power saving modes. 
+   One is the Periodic Standby Mode and the other is Periodic Backup Mode. 
+   Due to hardware limitations, the maximum power down duration (SLEEP) is 2047 seconds. 
+   If the configured SLEEP interval is larger than 2047 seconds, the GNSS firmware 
+   automatically extends the interval using software. However, the GNSS system is powered 
+   on for the interval extension and powered down again after the extension is complete.
+   Keep status after reboot –> Yes.
+[Data Field]
+$ PMTK225, Type, Run time, Sleep time, Second run time, Second sleep time*CS<CR><LF>
+   Type : Set operation mode of power saving 
+   '0': Back to normal mode 
+   '1' Periodic backup mode
+   '2' Periodic standby mode
+   '4': Perpetual backup mode 
+   '8': Always Locate standby mode 
+   '9': Always Locate backup mode 
+   Run time. Duration in milliseconds (ms) to fix for (or attempt to fix for) before
+   switching from running mode back to a minimum power sleep mode. 
+   '0': Disable
+   >= '1000': Enable
+   [Range: 1000~518400000]
+   Sleep time: Interval in ms to exit the minimum power sleep mode and get a new position fix.[Range: 1000~518400000]
+   Second run time: Duration in ms to fix for (or attempt to fix for) before switching 
+   from running mode back to a minimum power sleep mode.
+   '0': Disable
+   >= '1000': Enable
+   [Range: Second set both 0 or 1000~518400000]
+   Second sleep time: Interval in ms to exit the minimum power sleep mode and get a new position fix.[Range: Second set both 0 or 1000~518400000]
+[Example]
+   Commands to enter periodic modes.
+   Periodic Backup mode 
+   PMTK225,0*2B<CR><LF> 
+   PMTK223,1,25,180000,60000*38<CR><LF> 
+   PMTK225,1,3000,12000,18000,72000*16<CR><LF> 
+   Periodic Standby mode 
+   PMTK225,0*2B<CR><LF> 
+   PMTK223,1,25,180000,60000*38<CR><LF>  
+   PMTK225,2,3000,12000,18000,72000*16<CR><LF> 
+   Commands to enter Always Locate modes 
+   Always Locate Standby 
+   PMTK225,0*2B<CR><LF> 
+   PMTK225,8*23<CR><LF> 
+   AlwaysLocateTM Backup 
+   PMTK225,0*2B<CR><LF> 
+   PMTK225,9*22<CR><LF> 
+
PMTK_SET_DATA_PORT  +
+[Packet Type]
+ 250
+[Command]
+ PMTK_SET_DATA_PORT
+[Description]
+   Set data port input/output data type and baudrate.
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK250,InType,OutType,Baudrate*CS<CR><LF>
+   InType: Data port input data type
+   '0' = DPORT_IN_NONE  (No data input)
+   '1' = DPORT_IN_RTCM  (RTCM input)
+   '3' = DPORT_IN_NMEA  (MTK NMEA)
+   OutType: Data port input data type
+   '0' = DPORT_OUT_NONE   (No data output)
+   '3' = DPORT_OUT_NMEA     (MTK NMEA)
+   Baudrate. Possible values are: 4800, 9600, 14400, 19200, 38400, 57600, 115200, 460800, 921600. 
+[Example]
+   $PMTK250,1,1,9600*16<CR><LF>
+
PMTK_SET_NMEA_BAUDRATE  +
+[Packet Type]
+ 251
+[Command]
+ PMTK_SET_NMEA_BAUDRATE
+[Description]
+   Set NMEA port baudrate. 
+   Using PMTK251 command to setup baud rate setting, the setting will be back to defatult value in the two conditions.
+   1. Full cold start command is issued
+   2. Enter standby mode
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK251,Baudrate*CS<CR><LF>
+   Baudrate. Possible values are: 0 (default), 4800, 9600, 14400, 19200, 38400, 57600, 115200, 230400, 460800, 921600.
+[Example]
+   $PMTK251,38400*27<CR><LF>
+[Note]
+   The option "Allow change of baudrate" at the "NMEA" page in the CoreBuilder should be checked before using this command.
+
PMTK_SET_OUTPUT_FMT  +
+[Packet Type]
+ 253
+[Command]
+ PMTK_SET_OUTPUT_FMT
+[Description]
+   Set data output format for current port.
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK253,Flag*CS<CR><LF>
+   Flag (unsigned 1 byte): 0 - NMEA mode
+   1 - binary mode
+[Example]
+   $PMTK253,1*2B<CR><LF>  //Change output format from NMEA mode to binary mode
+[Note]
+   When you switch from binary mode to NMEA mode, you will receive a binary 
+   ACK after the command is processed. 
+   When you switch from NMEA mode to binary mode, NO ACK will be sent.
+
PMTK_SET_SYNC_PPS_NMEA  +
+[Packet Type]
+ 255
+[Command]
+ PMTK_SET_SYNC_PPS_NMEA
+[Description]
+   Enable or disable fixed NMEA output time in pulse per second (PPS) function (default value is "0").
+   The latency range of the beginning of UART Tx is between 170 ms and 180 ms at MT3339 platform (465 ms~485ms at MT3333 
+   platform) and behind the rising edge of PPS.
+   
+PMTK255.jpg +
+ + Keep status after reboot –> No. +[Data Field] +$PMTK255,Flag*CS<CR><LF> + Flag "0", Disable. + "1", Enable. +[Example] + $PMTK255,1*23<CR><LF> +[Note] + Only support in AXN 3.6(8) and 2.3(5) after 2014/4/21. +
PMTK_SET_TIMING_PRODUCT  +
+[Packet Type]
+ 256
+[Command]
+ PMTK_SET_TIMING_PRODUCT        
+[Description]
+   Enable or disable timing product mode (Default off).
+   The timing product mode will enhance the PPS output timing accuracy which is listed in below table. 
+   
+PMTK256.png +
+ + Keep status after reboot –> No. +[Data Field] +$PMTK256,Enabled *CS<CR><LF> + Enabled: Enable or disable + '0' = Disable + '1' = Enable +[Example] + $PMTK256,1*2E<CR><LF> + Note: + Please measure the accuracy after the device collect all satellites almanac. +
PMTK_SET_HIGH_ACCURACY  +
+[Packet Type]
+ 257
+[Command]
+ PMTK_SET_HIGH_ACCURACY          
+[Description]
+   Enable fast TTFF or high accuracy function when out of the tunnel or garage. (Default enabled high accuracy function). 
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK257, Functionality *CS<CR><LF>
+   Functionality: 
+   '0' = Enable fast TTFF when out of the tunnel or garage 
+   '1' = Enable high accuracy when out of the tunnel or garage 
+[Example]
+   $PMTK257,1*2F<CR><LF> 
+
PMTK_SET_GLP_MODE  +
+[Packet Type]
+ 262
+[Command]
+ PMTK_SET_GLP_MODE              
+[Description]
+   Enable or disable GNSS Low Power(GLP) mode.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK262, Enabled *CS<CR><LF>
+   Enabled: 
+   '0' = Disable GLP mode 
+   '1' = Enable GLP mode for MT3339
+   '3' = Enable GLP mode for MT3333
+[Example]
+   $PMTK262,1*29<CR><LF> (Enable GLP mode for MT3339) 
+   $PMTK262,3*2B<CR><LF> (Enable GLP mode for MT3333) 
+
PMTK_SET_NMEA_DECIMAL_PRECISION  +
+[Packet Type]
+ 265
+[Command]
+ PMTK_SET_NMEA_DECIMAL_PRECISION
+[Description]
+  Set number of fractional digit in NMEA.
+  Keep status after reboot –> No.
+[Data Field]
+$PMTK265, Number*CS<CR><LF>
+ Number:     
+ "1", 4 digits
+ "2", 5 digits
+ "3", 6 digits
+[Example]
+   $PMTK265,1*2E<CR><LF>
+
PMTK_SET_PPS_CONFIG_CMD  +
+[Packet Type]
+ 285
+[Command]
+ PMTK_SET_PPS_CONFIG_CMD
+[Description]
+   Configure the PPS settings.   
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK285,PPSType,PPSPulseWidth*CS<CR><LF>
+   PPSType. Availability
+   "0", Disable
+   "1", After the first fix
+   "2", 3D fix only
+   "3", 2D/3D fix only
+   "4", Always
+   PPSPulseWidth. PPS Pulse Width (unit in ms).
+[Example]
+   $PMTK285,2,100*23<CR><LF>
+
PMTK_SET_AIC_CMD  +
+[Packet Type]
+ 286
+[Command]
+ PMTK_SET_AIC_CMD
+[Description]
+   Enable or disable active interference cancellation function. 
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK286,Enabled*CS<CR><LF>
+   Enabled. Enable or disable
+   "0", Disable.
+   "1", Enable.
+[Example]
+   $PMTK286,1*23<CR><LF>
+
PMTK_SET_OUTPUT_DEBUG  +
+[Packet Type]
+ 299
+[Command]
+ PMTK_SET_OUTPUT_DEBUG
+[Description]
+   Enable or disable the Debug log output.
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK299,Enabled*CS<CR><LF>
+   Enabled. Enable or disable
+   "0", Disable.
+   "1", Enable.
+[Example]
+   $PMTK299,1*2D<CR><LF>
+
PMTK_API_SET_DGPS_MODE  +
+[Packet Type]
+ 301
+[Command]
+ PMTK_API_SET_DGPS_MODE
+[Description]
+   DGPS correction data source mode.
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK301,Mode *CS<CR><LF>
+   Mode: DGPS data source mode. 
+   '0': No DGPS source 
+   '1': RTCM 
+   '2': SBAS(Include WAAS/EGNOS/GAGAN/MSAS) 
+[Example]
+   $PMTK301,1*2D<CR><LF>
+
PMTK_API_SET_MIN_SNR  +
+[Packet Type]
+ 306
+[Command]
+ PMTK_API_SET_MIN_SNR
+[Description]
+   Set the minimum SNR of used satellites. 
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK306,MIN_SNR *CS<CR><LF>
+   MIN_SNR: Minimum SNR threshold of used satellites. (Valid range: 9~37) 
+[Example]
+   $PMTK306,15*1F<CR><LF> 
+   => Set the minimum SNR threshold to 15, the chip would not use the satellite which SNR is smaller than 15. 
+
PMTK_API_SET_DR_LIMIT  +
+[Packet Type]
+ 308
+[Command]
+ PMTK_API_SET_DR_LIMIT
+[Description]
+   Set the number of estimated fix when entering the tunnel. 
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK308,DR_LIMIT *CS<CR><LF>
+   DR_LIMIT: Number of estimated fix. (Valid range: 0~500) 
+[Example]
+   $PMTK308,0*25<CR><LF> => Disable the estimated fix when entering the tunnel. 
+   $PMTK308,3*26<CR><LF> => Keep outputting 3 fix when entering the tunnel. 
+
PMTK_API_SET_ELEV_MASK  +
+[Packet Type]
+ 311
+[Command]
+ PMTK_API_SET_ELEV_MASK
+[Description]
+   Set satellite elevation mask. 
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK311,Degree *CS<CR><LF>
+   Degree: Satellite elevation-mask. 
+[Example]
+   $PMTK311,5*28<CR><LF> 
+   Note: 
+   Only support in AXN3.8 after 2015/6/17, and AXN2.5 after 2015/10/19. 
+
PMTK_API_SET_SBAS_ENABLED  +
+[Packet Type]
+ 313
+[Command]
+ PMTK_API_SET_SBAS_ENABLED
+[Description]
+   Enable to search a SBAS satellite or not. 
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK313,Enabled*CS<CR><LF>
+   Enabled: Enable or disable
+   '0' = Disable
+   '1' = Enable
+[Example]
+   $PMTK313,1*2E<CR><LF>
+
PMTK_API_SET_NMEA_OUTPUT  +
+[Packet Type]
+ 314
+[Command]
+ PMTK_API_SET_NMEA_OUTPUT
+[Description]
+   Set the NMEA sentence output type and frequencies.
+   Keep status after reboot –> Yes.
+[Data Field]
+   There are totally 19 data fields that present output frequencies for the 19 supported NMEA sentences individually.
+   Supported NMEA Sentences
+   0 NMEA_SEN_GLL,     // GPGLL interval - Geographic Position - Latitude longitude
+   1 NMEA_SEN_RMC,     // GPRMC interval - Recomended Minimum Specific GNSS Sentence
+   2 NMEA_SEN_VTG,     // GPVTG interval - Course Over Ground and Ground Speed
+   3 NMEA_SEN_GGA,     // GPGGA interval - GPS Fix Data
+   4 NMEA_SEN_GSA,     // GPGSA interval - GNSS DOPS and Active Satellites
+   5 NMEA_SEN_GSV,     // GPGSV interval - GNSS Satellites in View
+   6 NMEA_SEN_GRS,     // GPGRS interval - GNSS Range Residuals
+   7 NMEA_SEN_GST,     // GPGST interval - GNSS Pseudorange Erros Statistics
+   8 NMEA_SEN_PLT,     // POLYT interval - Time
+   9 NMEA_SEN_PLP,     // POLYP interval - Position (Lat, Long)
+   10 NMEA_SEN_PLS,     // POLYS interval - Satellite data
+   11 NMEA_SEN_PLI,      // POLYI interval - Additional Information
+   12 NMEA_SEN_PLH,     // POLYH interval - HDS Time Information
+   13 NMEA_SEN_MALM,    // PMTKALM interval - GPS almanac information
+   14 NMEA_SEN_MEPH,    // PMTKEPH interval - GPS ephmeris information
+   15 NMEA_SEN_MDGP,    // PMTKDGP interval - GPS differential correction information
+   16 NMEA_SEN_MDBG,    // PMTKDBG interval - MTK debug information
+   17 NMEA_SEN_ZDA,      // GPZDA interval - Time & Date
+   18 NMEA_SEN_MCHN,    // PMTKCHN interval - GPS channel status
+   Supported Frequency Setting
+   0 - Disabled or not supported sentence
+   1 - Output once every one position fix
+   2 - Output once every two position fixes
+   3 - Output once every three position fixes
+   4 - Output once every four position fixes
+   5 - Output once every five position fixes
+[Example]
+   $PMTK314,1,1,1,1,1,5,0,0,0,0,0,0,0,0,0,0,0,1,1,0*30<CR><LF>
+   This command set GLL output frequency to be outputting once every 1 position fix, 
+   and RMC to be outputting once every 1 position fix, and so on.
+   You can also restore the system default setting via issue:
+   $PMTK314,-1*04<CR><LF>
+   Note: 
+   Settings of GST and GRS are valid only when firmware supports GST/GRS sentences.
+
PMTK_API_SET_PPS  +
+[Packet Type]
+ 326
+[Command]
+ PMTK_API_SET_PPS
+[Description]
+   This packet contains the local time in milliseconds and phase where the PPS should be placed.  
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK326,PPS_BY_USER,Local_ms,phase*CS<CR><LF>
+   PPS_BY_USER
+   "1", PPS output by user.
+   "0", PPS automatic output.
+   Local_ms. Local receiver time tick. Range is from 0 to 4294967295 (232-1). 
+   Phase. Time tick phase range is from 0 to 262143. 
+[Example]
+   $PMTK326,1,1345,555*3F<CR><LF>
+
PMTK_API_SET_HACC_MASK  +
+[Packet Type]
+ 328
+[Command]
+ PMTK_API_SET_HACC_MASK
+[Description]
+   Set horizontal accuracy mask. Range from 30m to 200m or -1. GPS will get fix only when hacc value < mask.
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK328,HaccMask*CS<CR><LF>
+   HaccMask: 
+       30~200: enable hacc mask feature.  (Units: meter)
+       -1: disable hacc mask feature.
+[Example]
+   $PMTK328,50*12<CR><LF>
+
PMTK_API_SET_DATUM  +
+[Packet Type]
+ 330
+[Command]
+ PMTK_API_SET_DATUM
+[Description]
+   Set default datum.
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK330,Datum*CS<CR><LF>
+   Datum: 0: WGS84
+   1: TOKYO-M
+   2: TOKYO-A
+   Support 219 different datums. The total datums list in the Appendix A.
+[Example]
+   $PMTK330,0*2E<CR><LF>
+
PMTK_API_SET_DATUM_ADVANCE  +
+[Packet Type]
+ 331
+[Command]
+ PMTK_API_SET_DATUM_ADVANCE
+[Description]
+   Set user defined datum.
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK331,majA,ecc,dX,dY,dZ*CS<CR><LF>
+   majA: User defined datum semi-major axis [m] [Range: 0 ~ 7000000]
+   ecc: User defined datumeccentric [m] [Range: 0 ~ 330]
+   dX: User defined datum to WGS84 X axis offset [m]
+   dY: User defined datum to WGS84 X axis offset [m]
+   dZ: User defined datum to WGS84 X axis offset [m]
+[Example]
+   $PMTK331, 6377397.155, 299.1528128, -148.0, 507.0,685.0*16<CR><LF>
+
PMTK_API_SET_SUPPORT_QZSS_NMEA  +
+[Packet Type]
+ 351
+[Command]
+ PMTK_API_SET_SUPPORT_QZSS_NMEA
+[Description]
+   The receiver supports new NMEA format for QZSS. The command allow user enable or disable QZSS NMEA format.
+   Default is disabling QZSS NMEA format. (Using NMEA 0183 V3.01) 
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK351,Enabled*CS<CR><LF>
+   Enabled: '0': Disable
+   '1': Enable
+[Example]
+   $PMTK351,0*29<CR><LF> : Disable QZSS NMEA format
+   $PMTK351,1*28 <CR><LF>: Enable QZSS NMEA format
+
PMTK_API_SET_STOP_QZSS  +
+[Packet Type]
+ 352
+[Command]
+ PMTK_API_SET_STOP_QZSS
+[Description]
+   Since QZSS is regional positioning service. The command allow user enable or disable QZSS function.
+   Default is enable QZSS function. 
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK352,Enabled*CS<CR><LF>
+   Enabled: '0': Enable
+   '1': Disable
+[Example]
+   $PMTK352,0*2A<CR><LF> : Enable QZSS function
+   $PMTK352,1*2B<CR><LF> : Disable QZSS function
+
PMTK_API_SET_GNSS_SEARCH_MODE  +
+[Packet Type]
+ 353
+[Command]
+ PMTK_API_SET_GNSS_SEARCH_MODE
+[Description]
+   Configure the receiver to start searching for satellites. The setting is available when the NVRAM data is valid.
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK353, GPS_Enabled, GLONASS_Enabled, GALILEO_Enabled, Reserve, BEIDOU_Enabled*CS<CR><LF>
+   GPS_Enabled:                     
+   "0", disable (DO NOT search GPS satellites).
+   "1", or non-ZERO: search GPS satellites. 
+   GLONASS_Enabled:
+   "0", disable (DO NOT search GLONASS satellites).
+   "1", or non-ZERO: search GLONASS satellites.
+   GALILEO_Enabled:     
+   "0", disable (DO NOT search GALILEO satellites).
+   "1", or non-ZERO: search GALILEO satellites.
+   Reserve: no used.
+   BEIDOU_Enabled:           
+   "0", disable (DO NOT search BEIDOU satellites).
+   "1", or non-ZERO: search BEIDOU satellites.
+[Example]
+   $PMTK353,0,1,0,0,0*2A : Search GLONASS satellites only.
+   $PMTK353,1,0,0,0,0*2A : Search GPS satellites only.   
+   $PMTK353,1,1,0,0,0*2B : Search GPS and GLONASS satellites.
+   $PMTK353,1,0,1,0,0*2B : Search GPS and GALILEO satellites.
+   $PMTK353,1,1,1,0,0*2A : Search GPS GLONASS, GALILEO satellites.
+   $PMTK353,0,0,0,0,1*2A : Search BEIDOU satellites only.
+   $PMTK353,1,0,0,0,1*2B : Search GPS and BEIDOU satellites.
+   Note: GLONASS only, BeiDou only and GALILEO only mode is only for testing purpose. 
+   Use (GPS + GLONASS) or (GPS + BeiDou) or (GPS + GALILEO) or (GPS + GLONASS + GALILEO) in your applications. GLONASS and BeiDou cannot be enabled at the same time. GALILEO and BeiDou cannot be enabled at the same time.
+
PMTK_API_GET_GNSS_OPERAT_MODE  +
+[Packet Type]
+ 355
+[Command]
+ PMTK_API_GET_GNSS_OPERAT_MODE  
+[Description]
+   This command is to get GPS,GLONASS, BeiDou and GALILEO search settings.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Example]
+   $PMTK355*31
+[Return]
+   $PMTK001,353,3,1,0,1,0*35 
+   //"$PMTK001,355,3,GPS_Enable,GLON_Enable,BEIDOU_Enable,GALILEO_Enable"
+   The return value in this example means GPS + Beidou searching mode is enabled. 
+
PMTK_API_SET_HDOP_THRESHOLD  +
+[Packet Type]
+ 356
+[Command]
+ PMTK_API_SET_HDOP_THRESHOLD
+[Description]
+   This command is to set the HDOP threshold. 
+   If the HDOP value is larger than this threshold value, the position will not be fixed.    
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK356,HDOPThreshold*CS<CR><LF>
+   HDOPThreshold:
+   "0": Disable this function.
+   Other value: Enable set the HDOP threshold
+[Example]
+   $PMTK356,0.8
+   Return $PMTK356,0.8 Set OK!*5F 
+
PMTK_API_GET_HDOP_THRESHOLD  +
+[Packet Type]
+ 357
+[Command]
+ PMTK_API_GET_HDOP_THRESHOLD
+[Description]
+   This command is to get the HDOP threshold.    
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK357,HDOPThreshold*CS<CR><LF>
+   HDOPThreshold. "0", Disable this function.
+   Other value. Enable.
+[Example]
+   $PMTK357
+   Return $PMTK357,0.8*39 
+
PMTK_API_SET_PLL  +
+[Packet Type]
+ 381
+[Command]
+ PMTK_API_SET_PLL 
+[Description]
+   Set PLL on or off. 
+[Data Field]
+$PMTK381, PLL status*CS<CR><LF>
+   0: PLL off, 1: PLL on
+[Example]
+   $PMTK381,1*25<CR><LF>
+
PMTK_API_SET_HIGH_SENSITIVITY_TRACKING_NO_FIX  +
+[Packet Type]
+ 385
+[Command]
+ PMTK_API_SET_HIGH_SENSITIVITY_TRACKING_NO_FIX 
+[Description]
+   Disable/Enable position output in high sensitivity tracking mode. 
+[Data Field]
+$PMTK385,Disable_Position_Output*CS<CR><LF>
+   0: Enable, 1: Disable
+[Example]
+   $PMTK385,1*21<CR><LF>
+
PMTK_API_SET_STATIC_NAVI_THD  +
+[Packet Type]
+ 386
+[Command]
+ PMTK_API_SET_STATIC_NAVI_THD
+[Description]
+   Set the speed threshold for static navigation. 
+   If the actual speed is below the threshold, output position remains the 
+   same and the output speed will be zero. If the threshold value is set to 0, 
+   this function is disabled.    
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK386, speed_threshold*CS<CR><LF>
+   Speed_threshold.  0~2 m/s.
+   The minimum is 0.1 m/s, the maximum is 2.0 m/s.
+[Example]
+   $PMTK386, 0.4*19<CR><LF>
+
PMTK_API_SET_FLASH_DATA  +
+[Packet Type]
+ 399
+[Command]
+ PMTK_API_SET_FLASH_DATA
+[Description]
+   Write data to the flash.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK399, Address, Length, Data0, Data1, Data2, ...... *CS<CR><LF>
+   Address: the starting address in hex format (the address is fixed at 0x1C0) 
+   Length: the number of bytes of incoming data fields in hex format (Max length = 7 bytes) 
+   DataN: data byte in hex format 
+[Example]
+   $PMTK399,1c0,7,30,5C,22,1D,02,04,01*4F<CR><LF>
+
PMTK_API_Q_FIX_CTL  +
+[Packet Type]
+ 400
+[Command]
+ PMTK_API_Q_FIX_CTL
+[Description]
+   API_Query_Fix_Ctl
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_FIX_CTL (See Packet Type: 500) 
+[Example]
+   $PMTK400*36<CR><LF>
+
PMTK_API_Q_DGPS_MODE  +
+[Packet Type]
+ 401
+[Command]
+ PMTK_API_Q_DGPS_MODE
+[Description]
+   API_Query_Dgps_Mode
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_DGPS_MODE (See Packet Type: 501) 
+[Example]
+   $PMTK401*37<CR><LF>
+
PMTK_API_Q_MIN_SNR  +
+[Packet Type]
+ 406
+[Command]
+ PMTK_API_Q_MIN_SNR
+[Description]
+   Query the minimum SNR of used satellites.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_MIN_SNR
+[Example]
+   $PMTK406*30<CR><LF>
+   Return:
+   $PMTK506,15*19<CR><LF> => The minimum SNR threshold is 15 
+   $PMTK506,0*2D<CR><LF> => The user didn't set the minimum SNR threshold
+
PMTK_API_Q_DR_LIMIT  +
+[Packet Type]
+ 408
+[Command]
+ PMTK_API_Q_DR_LIMIT
+[Description]
+   Query the number of estimated fix when entering the tunnel. 
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_DR_LIMIT
+[Example]
+   $PMTK408*3E<CR><LF> 
+   Return:
+   $PMTK508,0*23<CR><LF> => The user disable the DR estimated fix 
+
PMTK_API_Q_ELEV_MASK  +
+[Packet Type]
+ 411
+[Command]
+ PMTK_API_Q_ELEV_MASK
+[Description]
+   Query satellite elevation mask. 
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_ELEV_MASK
+[Example]
+   $PMTK411*36<CR><LF> 
+   Return:
+   $PMTK511,Degree 
+   Note: 
+   Only support in AXN3.8 after 2015/6/17, and AXN2.5 after 2015/10/19. 
+
PMTK_API_Q_SBAS_ENABLED  +
+[Packet Type]
+ 413
+[Command]
+ PMTK_API_Q_SBAS_ENABLED
+[Description]
+   Query the status of SBAS to check if it is enabled or not.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_SBAS_ENABLED (See Packet Type: 513) 
+[Example]
+   $PMTK413*34<CR><LF>
+
PMTK_API_Q_NMEA_OUTPUT  +
+[Packet Type]
+ 414
+[Command]
+ PMTK_API_Q_NMEA_OUTPUT
+[Description]
+   Query current NMEA sentence output frequencies.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_NMEA_OUTPUT (See Packet Type: 514) 
+[Example]
+   $PMTK414*33<CR><LF>
+
PMTK_API_Q_HACC_MASK  +
+[Packet Type]
+ 428
+[Command]
+ PMTK_API_Q_HACC_MASK
+[Description]
+   Query horizontal accuracy mask.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_HACC_MASK  
+[Example]
+   $PMTK428*3C<CR><LF>
+
PMTK_API_Q_DATUM  +
+[Packet Type]
+ 430
+[Command]
+ PMTK_API_Q_DATUM
+[Description]
+   Query default datum.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_DATUM
+[Example]
+   $PMTK430*35<CR><LF>
+
PMTK_API_Q_DATUM_ADVANCE  +
+[Packet Type]
+ 431
+[Command]
+ PMTK_API_Q_DATUM_ADVANCE
+[Description]
+   Query user defined datum.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_DATUM
+[Example]
+   $PMTK431*34<CR><LF>
+
PMTK_API_Q_RTC_TIME  +
+[Packet Type]
+ 435
+[Command]
+ PMTK_API_Q_RTC_TIME
+[Description]
+   Query current RTC UTC time.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_API_DT_RTC_TIME 
+[Example]
+   $PMTK435*30<CR><LF>
+
PMTK_API_Q_HIGH_SENSITIVITY_TRACKING_NO_FIX  +
+[Packet Type]
+ 436
+[Command]
+ PMTK_API_Q_HIGH_SENSITIVITY_TRACKING_NO_FIX
+[Description]
+   Query setting of position output disabled/enabled in high sensitivity tracking mode.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_HIGH_SENSITIVITY_TRACKING_NO_FIX 
+[Example]
+   $PMTK436*33<CR><LF>
+
PMTK_API_Q_EPH_STATUS  +
+[Packet Type]
+ 449
+[Command]
+ PMTK_API_Q_EPH_STATUS          
+[Description]
+   This command is to query the current status of ephemeris downloading 
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Example]
+   PMTK449*3B 
+   Return:
+   $PMTK001,449,3,1*24 : The ephemeris downloading is finished. 
+   $PMTK001,449,3,0*25 : The ephemeris downloading is not finished yet. 
+
PMTK_API_GET_POS_XYZ  +
+[Packet Type]
+ 458
+[Command]
+ PMTK_API_GET_POS_XYZ
+[Description]
+   Returns the WGS84 ECEF XYZ Cartesian Position vector ( metres ) with an estimated 1-sigma accuracy.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_POS_XYZ
+[Example]
+   $PMTK458*3B<CR><LF>
+
PMTK_API_GET_VEL_XYZ  +
+[Packet Type]
+ 461
+[Command]
+ PMTK_API_GET_VEL_XYZ
+[Description]
+   Returns the WGS84 ECEF XYZ Cartesian velocity vector ( m/s ) with an estimated 1-sigma accuracy.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_VEL_XYZ
+[Example]
+   $PMTK461*31<CR><LF>
+
PMTK_API_GET_FLASH_DATA  +
+[Packet Type]
+ 499
+[Command]
+ PMTK_API_GET_FLASH_DATA
+[Description]
+   Read the flash memory.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK499, Address, Length*CS<CR><LF>
+   Address: the starting address in hex format. (The address is fixed at 0x1C0) 
+   Length: the number of bytes requested in hex format (Max length is 7 bytes) 
+[Return]
+   PMTK_DT_FLASH_DATA
+[Example]
+   $PMTK499,1C0,7*43<CR><LF>
+
PMTK_DT_FIX_CTL  +
+[Packet Type]
+ 500
+[Command]
+ PMTK_DT_FIX_CTL
+[Description]
+   These parameters show the rate of position fixing activity. 
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK500,FixInterval,Duration,RunInterval,HAcc,VAcc*CS<CR><LF>
+   FixInterval: Position fix interval. (msec). [Range: 100 ~ 10000].
+   Duration: Duration to fix for (or attempt to fix for) before switching from running mode back to a minimum 
+   power sleep mode. (msec)
+   RunInterval: Interval to come out of a minimum power sleep mode and start running in order to get a new 
+   position fix. (msec)
+   HAcc: One-sigma estimated Horizontal position accuracy mask at which point a suitable fix is deemed to have 
+   been obtained and the receiver may prematurely switch into its minimum power sleep mode. (m)
+   VAcc: One-sigma estimated Horizontal position accuracy mask at which point a suitable fix is deemed to have 
+   been obtained and the receiver may prematurely switch into its minimum power sleep mode. (m)
+[Example]
+   $PMTK500,1000,0,0,0,0*1A<CR><LF>
+
PMTK_DT_DGPS_MODE  +
+[Packet Type]
+ 501
+[Command]
+ PMTK_DT_DGPS_MODE
+[Description]
+   DGPS Data Source Mode.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK501,Mode*CS<CR><LF>
+   Mode: DGPS data source mode
+   '0': No DGPS source
+   '1': RTCM
+   '2': WAAS
+   '3': GSM
+   '4': WCDMA
+   '5': CDMA2K
+[Example]
+   $PMTK501,1*2B<CR><LF>
+
PMTK_DT_SBAS_ENABLED  +
+[Packet Type]
+ 513
+[Command]
+ PMTK_DT_SBAS_ENABLED
+[Description]
+   Enable or disable searching for SBAS satellites.  
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK513,Enabled*CS<CR><LF>
+   Enabled: Enable or disable
+   '0' = Disable
+   '1' = Enable
+[Example]
+   $PMTK513,1*28<CR><LF>
+
PMTK_DT_NMEA_OUTPUT  +
+[Packet Type]
+ 514
+[Command]
+ PMTK_DT_NMEA_OUTPUT
+[Description]
+   The NMEA sentence output frequency configuration.  
+   Keep status after reboot –> No.
+[Data Field]
+   There are totally 20 data fields that present output frequencies for the 
+   20 supported NMEA sentences individually. Please refer to PMTK_API_SET_NMEA_OUTPUT 
+   for the Supported NMEA Sentences and Frequency Setting.
+[Example]
+   $PMTK514,1,1,1,1,1,5,1,1,1,1,1,1,0,1,1,1,1,1,1,1*37<CR><LF>
+
PMTK_DT_HACC_MASK  +
+[Packet Type]
+ 528
+[Command]
+ PMTK_DT_HACC_MASK
+[Description]
+   Current horizontal accuracy mask.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK528,mask*CS<CR><LF>
+[Example]
+   $PMTK528,50.00*3A<CR><LF>
+
PMTK_DT_DATUM  +
+[Packet Type]
+ 530
+[Command]
+ PMTK_DT_DATUM
+[Description]
+   Current datum used.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK530,Datum*CS<CR><LF>
+   Datum: 0: WGS84
+   1: TOKYO-M
+   2: TOKYO-A
+[Example]
+   $PMTK530,0*28<CR><LF>
+
PMTK_DT_RTC_TIME  +
+[Packet Type]
+ 535
+[Command]
+ PMTK_DT_RTC_TIME
+[Description]
+   This packet carries current RTC UTC time.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK535,Year,Month,Day,Hour,Min,Sec*CS<CR><LF>
+   Year: Year
+   Month: 1 ~ 12
+   Day: 1 ~ 31
+   Hour: 0 ~ 23
+   Min: 0 ~ 59
+   Sec: 0 ~ 59
+[Example]
+   $PMTK535,2007,1,1,0,0,0*04<CR><LF>
+
PMTK_DT_HIGH_SENSITIVITY_TRACKING_NO_FIX  +
+[Packet Type]
+ 536
+[Command]
+ PMTK_DT_HIGH_SENSITIVITY_TRACKING_NO_FIX
+[Description]
+   This packet carries setting of position output disabled/enabled in high sensitivity tracking mode.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK536,Disable_Position_Output*CS<CR><LF>
+   0: Enable, 1: Disable
+[Example]
+   $PMTK536,1*2F<CR><LF>
+
PMTK_DT_FLASH_DATA  +
+[Packet Type]
+ 599
+[Command]
+ PMTK_DT_FLASH_DATA
+[Description]
+   The data in the flash memory.
+   Keep status after reboot –> No.
+[Data Field]
+   There are totally 'length+2' data fields that present the followings:
+   1. Starting address in hex format
+   2. Length in hex format
+   3~n: Data bytes in hex format
+[Example]
+   $PMTK599,1C,7,30,5C,22,1D,02,04,01*58<CR><LF> 
+
PMTK_Q_DATA_PORT  +
+[Packet Type]
+ 602
+[Command]
+ PMTK_Q_DATA_PORT
+[Description]
+   Read data port input/output data type and baudrate.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Return]
+   PMTK_DT_DATA_PORT 
+[Example]
+   $PMTK602*36<CR><LF>
+
PMTK_Q_RELEASE  +
+[Packet Type]
+ 605
+[Command]
+ PMTK_Q_RELEASE
+[Description]
+   Query the firmware release information.
+   Keep status after reboot –> No.
+[Data Field]
+   NONE
+[Return]
+   PMTK_DT_RELEASE
+[Example]
+   $PMTK605*31<CR><LF>
+
PMTK_Q_EPO_INFO  +
+[Packet Type]
+ 607
+[Command]
+ PMTK_Q_EPO_INFO
+[Description]
+   Query the EPO data status stored in the GPS chip.
+   Keep status after reboot –> No.
+[Data Field]
+   NONE
+[Return]
+   PMTK_DT_EPO_INFO
+[Example]
+   $PMTK607*33<CR><LF>
+
PMTK_Q_LOCUS_DATA  +
+[Packet Type]
+ 622
+[Command]
+ PMTK_Q_LOCUS_DATA
+[Description]
+   Use Locus tool to retrieve the logging data from the NVRAM.  
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK622,type*CS<CR><LF>
+   Type: 0-Dump full LOCUS flash data. 
+   1-Dump partial in used LOCUS flash data 
+$PMTK622,type,offset,size*CS<CR><LF>
+   Type: 2-Dump specified sectors' LOCUS flash data 
+   offset: The start address for dump (0<=offset<32, the unit is sector[4KB]) 
+   size: The dump length (0<=size<=32, the unit is sector[4KB]) 
+[Example]
+   Input: $PMTK622,0*28 //Dump full LOCUS flash data 
+   Input: $PMTK622,1*29 //Dump partial in used LOCUS flash data 
+   Input: $PMTK622,2,3,2*2B //Skip sector 1,2,3. Dump sector4 and sector5 LOCUS flash data 
+   [Note] 
+   If the input values of offset and size are out of range, it will dump all LOCUS flash like using $PMTK622,0*28. 
+
PMTK_Q_AVAILABLE_SV_EPH  +
+[Packet Type]
+ 660
+[Command]
+ PMTK_Q_AVAILABLE_SV_EPH
+[Description]
+   Support PMTK660 which report valid Ephemeris SV. 
+   (a) Host -> MT3329: A PMTK660 command to request the EPH info, together with a time interval parameter (for 
+   example, 1800sec). 
+   (b) MT3329 -> Host: Reply 32-bit flags of 32SV to indicate which EPHs will be available after the specified time interval. 
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK660, Time interval *CS<CR><LF>
+   Time interval: Set the time interval for MT3329 to reply 32-bit flags of 32SV. Note that the Time interval > 0 and <= 
+   7200 (2 hours). 
+[Example]
+   Indicate which EPHs will be available after 1800 seconds 
+   $PMTK660,1800*17<CR><LF> 
+[Return]
+   $PMTK001,660,3,40449464*17<CR><LF> 
+   Note the Hex 40449464 means 0100 0000 0100 0100 1001 0100 0110 0100 and the Valid SV's numbers are 3, 6, 7, 11, 
+   13, 16, 19, 23, 31.
+
PMTK_Q_AVAILABLE_SV_ALM  +
+[Packet Type]
+ 661
+[Command]
+ PMTK_Q_AVAILABLE_SV_ALM
+[Description]
+   Support PMTK661 which report valid Almanac SV. 
+   (a) Host -> MT3329: A PMTK661 command to request the Almanac info, together with a time interval parameter (for 
+   example, 30 days). 
+   (b) MT3329 -> Host: Reply 32-bit flags of 32SV to indicate which Almanac will be available after the specified time 
+   interval. 
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK661, Time interval *CS<CR><LF>
+   Time interval: Set the time interval for MT3329 to reply 32-bit flags of 32SV. Note that the Time interval > 0 and <= 365 
+   (1 year for maximum) 
+[Example]
+   Indicate which Almanac will be available after 30 days 
+   $PMTK661,30*1C<CR><LF> 
+[Return]
+   $PMTK001,661,3,fec0bfff*49<CR><LF> 
+   Note the Hex fec0bfff means 11111110110000001011111111111111 and the Valid SV's numbers are 
+   1,2,3,4,5,6,7,8,9,10,11,12,13,14,16,23,24,26,27,28,29,30,31,32. 
+
PMTK_Q_UTC_CORRECTION_DATA  +
+[Packet Type]
+ 667
+[Command]
+ PMTK_Q_UTC_CORRECTION_DATA     
+[Description]
+   Get UTC correction data.     
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK001,667,3,A0,A1,dtLS,Tot,WNt,WNLSF,DN,dtLSF*CS<CR><LF>
+   Action flag:  '3' means UTC correnction data are available.
+                 '2' means UTC correnction data are not available.
+   A0: UTC parameter A0. Unit is (seconds)/(2^-30).
+   A1: UTC parameter A1. Unit is (seconds/second)/(2^-50).
+   dtLS: UTC time difference due to leap seconds before event. Unit is seconds.
+   Tot: UTC reference time of week. Unit is seconds.
+   WNt: UTC reference week number. Unit is weeks.
+   WNLSF: UTC week number when next leap second event occurs. Unit is weeks.
+   DN: UTC day of week when next leap second event occurs. Unit is days.
+   dtLSF: UTC time difference due to leap seconds after event. Unit is seconds.
+[Example]
+   $PMTK667 
+[Return]
+   If UTC correnction data are available, the receiver returns 
+   $PMTK001,667,3,0,0,16,507904,237,237,3,17*0A 
+   If UTC correnction data are not available, the receiver returns 
+   $PMTK001,667,2*36 
+
PMTK_Q_GPS_KEP  +
+[Packet Type]
+ 668
+[Command]
+ PMTK_Q_GPS_KEP                 
+[Description]
+   Get GPS ephemeris data in kepler format. 
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK668,PRN *CS<CR><LF>
+   PRN: The SVID of the satellite. Choose which satellite's ephemeris you want to get. 
+[Example]
+   $PMTK668,3*25<CR><LF> 
+[Return]
+   If ephemeris data of specified satellite is available, the receiver returns 
+   $PMTK668,PRN,WeekNo,URAI,IDOT,IODE,Toc,af2,af1,af0,IODC,Crs,dn,M0,Cuc,e,Cus,SqrtA,Toe,Cic,Omega0,Cis,i0,Crc,w,OmegaDot,Tgd,SVHealth*CS
    PRN: SVID of satellite
+    WeekNo: Reference week number[weeks]
+    URAI: Figure of Merit - Defines URA
+    IDOT: Rate of inclination angle[rad/s]
+    IODE: Issue of data counter
+    Toc: Reference time of week[s]
+    af2: SV clock correction polynomial coefficient[s/s/s]
+    af1: SV clock correction polynomial coefficient[s/s]
+    af0: SV clock correction polynomial coefficient[s]
+    IODC: Issue of data counter
+    Crs: Ampof sin harmonic corr term orbit radius[m]
+    dn: Delta n mean motion diff from computed value[rad/s]
+    M0: Mean anomaly at reference time[rad]
+    Cuc: Amplitude of cos harm corr term arg of latitude[rad]
+    e: Eccentricity
+    Cus: Amplitude of sin harm corr term arg of latitude[rad]
+    SqrtA: Square root of the semi-major axis
+    Toe: Reference time of week[Ephemeris terms][s]
+    Cic: Amplitude of cos harm corr term ang of inclination[rad]
+    Omega0: Longitude of ascending node of orbit plane[rad]
+    Cis: Amplitude of sin harm corr term ang of inclination[rad]
+    i0: Inclination angle at reference time[rad]
+    Crc: Amplitude of cos harm corr term orbit radius[rad]
+    w: Argument of perigee[rad]
+    OmegaDot: Rate of right ascention[rad/s]
+    Tgd: Group delay[s]
+    SVHealth: The 5 LSBs of the NAV data's health status from the ephemeris.
   Note: Please use the factor scale(refer to ICD-GPS-200c, page 96) to calculate the actual value. 
+   Example:
+   $PMTK668,3,804,0,1378,97,18900,0,211,348491,97,1529,14047,-433441886,1302,8251567,3333,2702051329,18900,26,935176585,4,655529795,8214,-2063355058,-23169,3,0*3D
   If ephemeris data of specified satellite is not available, the receiver returns
+   $PMTK001,668,3,0*24   
+
PMTK_Q_BDS_KEP  +
+[Packet Type]
+ 669
+[Command]
+ PMTK_Q_BDS_KEP                 
+[Description]
+   Get BDS ephemeris data in kepler format. 
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK669,PRN *CS<CR><LF>
+   PRN: The SVID of the satellite. Choose which satellite's ephemeris you want to get. 
+[Example]
+   $PMTK669,3*25<CR><LF>     
+[Return]
+   If ephemeris data of specified satellite is available, the receiver returns 
+   $PMTK669,PRN,WeekNo,URAI,IDOT,IODE,Toc,af2,af1,af0,IODC,Crs,dn,M0,Cuc,e,Cus,SqrtA,Toe,Cic,Omega0,Cis,i0,Crc,w,OmegaDot,Tgd,SVHealth*CS
    PRN: SVID of satellite
+    WeekNo: Reference week number[weeks]
+    URAI: Figure of Merit - Defines URA
+    IDOT: Rate of inclination angle[rad/s]
+    IODE: Issue of data counter
+    Toc: Reference time of week[s]
+    af2: SV clock correction polynomial coefficient[s/s/s]
+    af1: SV clock correction polynomial coefficient[s/s]
+    af0: SV clock correction polynomial coefficient[s]
+    IODC: Issue of data counter
+    Crs: Amplitude of sin harmonic corr term orbit radius[m]
+    dn: Delta n mean motion diff from computed value[rad/s]
+    M0: Mean anomaly at reference time[rad]
+    Cuc: Amplitude of cos harm corr term arg of latitude[rad]
+    e: Eccentricity
+    Cus: Amplitude of sin harm corr term arg of latitude[rad]
+    SqrtA: Square root of the semi-major axis
+    Toe: Reference time of week[Ephemeris terms][s]
+    Cic: Amplitude of cos harm corr term ang of inclination[rad]
+    Omega0: Longitude of ascending node of orbit plane[rad]
+    Cis: Amplitude of sin harm corr term ang of inclination[rad]
+    i0: Inclination angle at reference time[rad]
+    Crc: Amplitude of cos harm corr term orbit radius[rad]
+    w: Argument of perigee[rad]
+    OmegaDot: Rate of right ascention[rad/s]
+    Tgd: Group delay[s]
+    SVHealth: The 5 LSBs of the NAV data's health status from the ephemeris.
   Note: please use the factor scale(refer to BeiDou Navigation Satellite System Signal In Space Interface Control Document) to calculate the actual value. 
+   Example:
+   $PMTK669,3,804,0,1567,2,38250,0,-26092,-4263927,0,-21176,581,1267572402,-23869,2546953,66039,3404432795,38250,-126,22528884,-260,55957758,-59905,-1898601724,2465,6,0*19
   If ephemeris data of specified satellite is not available, the receiver returns
+   $PMTK001,669,3,0*25 
+
PMTK_Q_GPS_IONO  +
+[Packet Type]
+ 670
+[Command]
+ PMTK_Q_GPS_IONO                
+[Description]
+   Query ionospheric parameters. 
+[Return]
+   $PMTK001,670,3,a0,a1,a2 ,a3, b0, b1, b2, b3 *CS<CR><LF>
+    a0: IONO parameter a0. Unit is Seconds.
+    a1: IONO parameter a1. Unit is sec/semi-circle.
+    a2: IONO parameter a2. Unit is sec/(semi-circle)^2.
+    a3: IONO parameter a3. Unit is sec/(semi-circle)^3.
+    b0: IONO parameter b0. Unit is Seconds.
+    b1: IONO parameter b1. Unit is sec/semi-circle.
+    b2: IONO parameter b2. Unit is sec/(semi-circle)^2.
+    b3: IONO parameter b3. Unit is sec/(semi-circle)^3.
+[Example]
+   $PMTK670*33<CR><LF> 
+   Return:
+   If ionospheric paremeters are available, the receiver returns 
+   $PMTK001,670,3,19,3,-2,-1,63,10,-3,-4*15 
+   If ionospheric paremeters are not available, the receiver returns 
+   $PMTK001,670,2*30 
+
PMTK_DT_DATA_PORT  +
+[Packet Type]
+ 702
+[Command]
+ PMTK_DT_DATA_PORT
+[Description]
+   Display Data port input/output data type and baud rate.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK702,InType,OutType,Baud*CS<CR><LF>
+   InType: Data port input data type
+   '0' = DPORT_IN_NONE
+   '1' = DPORT_IN_RTCM
+   '2' = DPORT_IN_NA
+   OutType: Data port input data type
+   '0' = DPORT_OUT_NONE
+   '1' = DPORT_OUT_DEBUG
+   Baud: Baudrate setting
+   4800
+   9600
+   19200
+   38400
+   57600
+   115200
+[Example]
+   $PMTK702,1,1,9600*14<CR><LF>
+
PMTK_DT_RELEASE  +
+[Packet Type]
+ 705
+[Command]
+ PMTK_DT_RELEASE
+[Description]
+   Firmware release information.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK705,ReleaseStr,Build_ID,Product_Model,(SDK_Version,) *CS<CR><LF>
+   ReleaseStr: Firmware release name and version 
+   3318 : Mcore_x.x 
+   3329 : AXN_x.x 
+   Build_ID: Build ID set in CoreBuilder for firmware version control 
+   Product_Model: Product Model set in CoreBuilder for product identification 
+   SDK_Version: Showing SDK version if the firmware is used for SDK 
+[Example]
+   $PMTK705,AXN_0.2,1234,ABCD,*14<CR><LF> 
+
PMTK_DT_EPO_INFO  +
+[Packet Type]
+ 707
+[Command]
+ PMTK_DT_EPO_INFO
+[Description]
+   EPO data status stored in GPS chip.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK707,Set,FWN,FTOW,LWN,LTOW,FCWN,FCTOW,LCWN,LCTOW*CS<CR><LF>
+   Set: Total number sets of EPO data stored in chip
+   FWN, FTOW: GPS week number & TOW of the first set of EPO data stored in chip respectively
+   LWN, LTOW: GPS week number & TOW of the last set of EPO data stored in chip respectively
+   FCWN, FCTOW: GPS week number & TOW of the first set of EPO data that are currently used respectively
+   LCWN, LCTOW: GPS week number & TOW of the last set of EPO data that are currently used respectively
+[Example]
+   $PMTK707,56,1468,172800,1470,151200,1468,259200,1468,259200*1F<CR><LF>
+
PMTK_DT_SV_EPO  +
+[Packet Type]
+ 721
+[Command]
+ PMTK_DT_SV_EPO
+[Description]
+   The packet contains GPS EPO data for a single satellite.
+   Keep status after reboot –> No.
+[Data Field]
+   $PMTK721,SatID,W[0],...,W[17]*CS<CR><LF>
+   SatID: Range 1 ~ 32. Satellite PRN number [Represented in HEX characters] for the EPO data to follow.
+   W[0] ~ W[17]: words [LSB first] of one EPO segment data (total 72 bytes).
+[Example]
+   None
+
PMTK_DT_UTC  +
+[Packet Type]
+ 740
+[Command]
+ PMTK_DT_UTC
+[Description]
+   The packet contains current UTC time. 
+   Please do not use local time, which has time-zone offset. 
+   To have faster TTFF, the accuracy of reference UTC shall be better less than 3 seconds.
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK740,YYYY,MM,DD,hh,mm,ss*CS<CR><LF>
+   YYYY  year    > 1980  UTC time: year in 4 digits
+   MM    month   1 - 12  UTC time: month
+   DD    day     1 - 31  UTC time: day
+   hh    hour    0 - 23  UTC time: hour
+   mm    minute  0 - 59  UTC time: minute
+   ss    second  0 - 59  UTC time: second
+[Example]
+   The packet indicates that the current UTC time 2010/Feb/10 09:00:58.
+   $PMTK740,2010,2,10,9,0,58*05<CR><LF>
+
PMTK_DT_POS  +
+[Packet Type]
+ 741
+[Command]
+ PMTK_DT_POS
+[Description]
+   The packet contains reference location for the GNSS module. 
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK741,Lat,Long,Alt,YYYY,MM,DD,hh,mm,ss *CS<CR><LF>
+   Name   Unit      Range            Description
+   Lat    degree    -90.0 ~ 90.0     WGS84 geodetic latitude. Suggest to express this value in floating-point 
+                                     with 6 decimal points. Minus: south; Plus: north
+   Long   degree    -180.0 ~ 180.0   WGS84 geodetic longitude. Suggest to express this value in floating-point 
+                                     with 6 decimal points. Minus: west; Plus: east
+   Alt    m         —              WGS84 ellipsoidal altitude.
+   YYYY   year      > 1980           Reference UTC time: year in 4 digits 
+   MM     month     1 - 12           Reference UTC time: month 
+   DD     day       1 - 31           Reference UTC time: day 
+   hh     hour      0 - 23           Reference UTC time: hour 
+   mm     minute    0 - 59           Reference UTC time: minute 
+   ss     second    0 - 59           Reference UTC time: second 
+[Example]
+   $PMTK741,24.772816,121.022636,160,2011,8,1,08,00,00
+   The packet indicates that the GNSS receiver is at latitude 24.772816 degrees, 
+   longitude 121.022636 degrees, and altitude 160m.
+   GNSS module will check the range for the following parameters:
+   Latitude: -90.0 ~ 90.0
+   Longitude: -180.0 ~ 180.0
+
PMTK_TEST_ALL  +
+[Packet Type]
+ 810
+[Command]
+ PMTK_TEST_ALL
+[Description]
+   Enter MP test mode and set test item and SV id.
+   
+PMTK810.png +
+ + Keep status after reboot –> No. +[Data Field] +$PMTK810,Bitmap,SVID*CS<CR><LF> + Bitmap: The first data field means the test items. + Each bit of test item field means one test item. List these test items below. + Supported Test Items + Bit0 TEST_INFO // Include f/w version, NMEA type and NMEA output rate + Bit1 TEST_ACQ // the time of acquiring the specific SV + Bit2 TEST_BITSYNC // the time of bit sync + Bit3 TEST_SIGNAL // Include phase error, TCXO clock/drift and CNR mean/sigma + Bit4 -15 (Reserved) + SVID: The second means the SV id. + The value of SV id is between 1 and 20 in Hex format. + The value of Glonass SVID is Frequency ID which is between C9 and D6 in Hex format. + Note. Glonass frequency id representation + -7 = C9 + -6 = CA + -5 = CB + -4 = CC + -3 = CD + -2 = DE + -1 = CF + 0 = D0 + 1 = D1 + 2 = D2 + 3 = D3 + 4 = D4 + 5 = D5 + 6 = D6 +[Example] + $PMTK810,0003,1D*4D<CR><LF> + This command only tests TEST_INFO and TEST_ACQ test items.The specific SV id is PRN29. +
PMTK_TEST_STOP  +
+[Packet Type]
+ 811
+[Command]
+ PMTK_TEST_STOP
+[Description]
+   Testing tool could send this command to GPS receiver to leave MP test mode.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Example]
+   $PMTK811*3A<CR><LF>
+
PMTK_TEST_FINISH  +
+[Packet Type]
+ 812
+[Command]
+ PMTK_TEST_FINISH
+[Description]
+   GPS receiver will send out this PMTK packet to show that MP testing has finished.
+   Keep status after reboot –> No.
+[Data Field]
+   None
+[Example]
+   $PMTK812*39<CR><LF>
+
PMTK_TEST_ALL_ACQ  +
+[Packet Type]
+ 813
+[Command]
+ PMTK_TEST_ALL_ACQ
+[Description]
+   The result of TEST_ACQ item.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK813,<SVid>,<Acq time>="">*<CheckSum><CR><LF>
+[Example]
+   $PMTK813,29,2*01<CR><LF>
+   The target device acquires SV29 within 2 seconds.
+
PMTK_TEST_ALL_BITSYNC  +
+[Packet Type]
+ 814
+[Command]
+ PMTK_TEST_ALL_BITSYNC
+[Description]
+   The result of TEST_BITSYNC item.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK814,<SVid>,<BitSync time>="">*<CheckSum><CR><LF>
+[Example]
+   $PMTK814,29,1*05<CR><LF>
+   Regard to SV29, the target device reach bit sync state within 1 second.
+
PMTK_TEST_ALL_SIGNAL  +
+[Packet Type]
+ 815
+[Command]
+ PMTK_TEST_ALL_SIGNAL
+[Description]
+   The result of TEST_SIGNAL item.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK815,<SVid>,<Testing time>="">,<Phase>,<TCXO offset>="">,<TCXO drift>="">,<CNR mean>="">,<CNR sigma>="">*<CheckSum><CR><LF>
+   The unit of <Phase>,<CNR mean>="">,<CNR sigma>=""> is 0.01.
+   The unit of <TCXO offset>="">,<TCXO drift>=""> is 0.001.
+[Example]
+   $PMTK815,29,16,98,10000,30,4100,0*18<CR><LF>
+   Regard to SV29, take 16 seconds to test and the result is ...
+   Phase Error: 0.98
+   TCXO offset/drift(Hz): 10/0.03
+   CNR mean/sigma: 41/0
+
PMTK_TEST_JAMMING  +
+[Packet Type]
+ 837
+[Command]
+ PMTK_TEST_JAMMING
+[Description]
+   Jamming scan test command.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK837, JamScanType, JamScanNum*CS<CR><LF>
+   JamScanType: '0' enable GPS jamming scan
+                '1' enable GLONASS jamming scan
+                '2' enable BEIDOU jamming scan
+   JamScanNum: Jamming scan test times.
+[Example]
+   $PMTK837,0,50*0B<CR><LF>
+   GPS jamming scan test 50 times
+   $PMTK837,1,50*0A<CR><LF>
+   GLONASS jamming scan test 50 times
+   $PMTK837,2,50*09<CR><LF>
+   BEIDOU jamming scan test 50 times
+
PMTK_TEST_JAMMING_DETECTION  +
+[Packet Type]
+ 838
+[Command]
+ PMTK_TEST_JAMMING_DETECTION        
+[Description]
+   Jamming detection test command.
+   Keep status after reboot –> No.
+[Data Field]
+$PMTK838, CmdType*CS<CR><LF> 
+   CmdType: "0" disable jamming detection message output. 
+            "1" enable jamming detection message output.
+[Example]
+   $PMTK838,1*2C<CR><LF> 
+   Enable the jamming detection message output 
+   Return: 
+   $PMTKSPF,1*5A => No jamming, healthy status.
+   $PMTKSPF,2*59 => Warning status.
+   $PMTKSPF,3*5A => Critical status.
+
PMTK_EASY_ENABLE  +
+[Packet Type]
+ 869
+[Command]
+ PMTK_EASY_ENABLE
+[Description]
+   Enable or disable EASY function.  Query if EASYis enabled orr disabled.
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK869,CmdType,[Enable],[Extension Day]*CS<CR><LF>
+   CmdType:  Set or Query
+   '0': Query
+   '1': Set
+   '2': Result for Query operation
+   Enable:   Enable or disable
+   '0': Disable
+   '1': Enable
+    Extension Day: Finished extension day.
+[Example]
+   To enable EASY, use
+   $PMTK869,1,1*35<CR><LF>
+   To disable EASY, use
+   $PMTK869,1,0*36<CR><LF>
+   To query if EASY is enabled or disabled, use
+   $PMTK869,0*29<CR><LF>
+   If EASY is disabled, the receiver returns
+   $PMTK869,2,0,0*37<CR><LF>
+   If EASY is enabled and is not finished yet, the receiver may returns
+   $PMTK869,2,1,0*2A<CR><LF>
+   If EASY is enabled and is finished 1-day extension, the receiver may returns
+   $PMTK869,2,1,1*2B<CR><LF>
+   If EASY is enabled and is finished 2-day extension, the receiver may returns
+   $PMTK869,2,1,2*28<CR><LF>
+   If EASY is enabled and is finished 3-day extension, the receiver may returns
+   $PMTK869,2,1,3*29<CR><LF>
+
PTMK_PMTKLSC_STN_OUTPUT  +
+[Packet Type]
+ 875
+[Command]
+ PTMK_PMTKLSC_STN_OUTPUT        
+[Description]
+   Enable or disable PMTKLSC Sentence output.Query if PMTKLSC Sentence output enabled or disabled.
+   Keep status after reboot –> Yes.
+[Data Field]
+$PMTK875,CmdType,[Enable]*CS<CR><LF>
+   CmdType: Set or Query
+   '0': Query
+   '1': Set
+   '2': Result for Query operation
+   Enable:   Enable or disable
+   '0': Disable
+   '1': Enable
+[Return]
+   $PMTKLSC, Parameter1, Parameter2, Parameter3*CS
+   $PMTKLSCB, Parameter1, Parameter2, Parameter3*CS
+   where Parameter 1 : current leap second
+   Parameter 2 : leap indicator, 1 means updated from broadcast data
+   Parameter 3 : next leap second
+[Example]
+   $PMTK875,1,1*35<CR><LF>   :Enable PMTKLSC and PMTKLSCB Sentence output
+   $PMTK875,1,0*34<CR><LF>   :Disable PMTKLSC and PMTKLSCB Sentence output
+
PMTK_FR_MODE  +
+[Packet Type]
+ 886
+[Command]
+ PMTK_FR_MODE
+[Description]
+   Set navigation mode.
+   Keep status after reboot –> No.
+[Data Field]
+   $PMTK886,CmdType
+   CmdType: '0' Normal mode: For general purpose
+            '1' Fitness mode: For running and walking purpose that the low-speed (< 5m/s) movement will have more effect on the position calculation.
+            '2' Aviation mode: For high-dynamic purpose that the large-acceleration movement will have more effect on the position calculation.
+            '3' Balloon mode: For high-altitude balloon purpose that the vertical movement will have more effect on the position calculation.
+            '4' Stationary mode: For stationary applications that zero dynamics is assumed.
+[Example]
+   $PMTK886,0*28<CR><LF> :Enter normal mode.
+   $PMTK886,1*29<CR><LF> :Enter fitness mode.
+   $PMTK886,2*2A<CR><LF> :Enter aviation mode.
+   $PMTK886,3*2B<CR><LF> :Enter balloon mode.
+   $PMTK886,4*2C<CR><LF> :Enter stationary mode.
+[Note]
+   Each mode has its altitude limitation. Please base on below table to choose the appropriate mode. If your test scenario exceeds the limitation, the position calculation will be incorrect.
+     Mode              Altitude Limitation
+     Normal mode      10000 m
+     Fitness mode     10000 m
+     Aviation mode    10000 m
+     Stationary mode  10000 m
+     Balloon mode     80000 m
+[Return]
+   $PMTK001,886,3*36<CR><LF>
+
+ +
+
+
+
+ + + + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/group__pmtk__command.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/group__pmtk__command.js" new file mode 100644 index 0000000..672315b --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/group__pmtk__command.js" @@ -0,0 +1,106 @@ +var group__pmtk__command = +[ + [ "PMTK_PKT_TYPE_T", "group__pmtk__command.html#ga6012e5fa857099f0e5fd61bb6d1f84be", [ + [ "PMTK_TEST", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea684eb8a711e4201f6de6aa5067100f21", null ], + [ "PMTK_ACK", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beabf86ac7cc7d3b0ce907b0a86e6a1338b", null ], + [ "PMTK_SYS_MSG", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa957fa7398464443cff5412f35fd0611", null ], + [ "PMTK_TXT_MSG", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea3c5bcc16f2cb139831b0c05d7e77d4d3", null ], + [ "PMTK_CMD_HOT_START", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea3ace760b44e085e0142fef46f1837e0d", null ], + [ "PMTK_CMD_WARM_START", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea7bd230a1d411831e909a6bdeaec2f7eb", null ], + [ "PMTK_CMD_COLD_START", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea815b92d27ea9a9adb14e4dbf2c6eb939", null ], + [ "PMTK_CMD_FULL_COLD_START", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea48aff60bb41ea828e9ccaf810f3f47f9", null ], + [ "PMTK_CMD_CLEAR_EPO", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea7cff33d092ea4b69a868898082a9383d", null ], + [ "PMTK_CMD_STANDBY_MODE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea466830c3723b4afc4ffaa5d389f528c3", null ], + [ "PMTK_LOCUS_QUERY_STATUS", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaf8f88476f893e2e7445714372c99b6f3", null ], + [ "PMTK_LOCUS_ERASE_FLASH", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea37e936f37aef1900a7e5a87fddbf8861", null ], + [ "PMTK_LOCUS_STOP_LOGGER", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaca811436d2d5072939d0f5cee493231c", null ], + [ "PMTK_LOCUS_LOG_NOW", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab7a9a31d9329df65b587ae512e1e6a14", null ], + [ "PMTK_LOCUS_CONFIG", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea69756339c6d97ad458e3ccadc60e3059", null ], + [ "PMTK_SET_POS_FIX", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaf38eaf459a6e12d9579a52ea433d2b3b", null ], + [ "PMTK_SET_AL_DEE_CFG", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea5d520ba1d9f1b61bcce90b521632c32d", null ], + [ "PMTK_SET_PERIODIC_MODE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8789b7bc5c5abad0ab627ad50aba79d4", null ], + [ "PMTK_SET_DATA_PORT", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9e91e2fdcbc35d2cb5e9c9fe9f564e98", null ], + [ "PMTK_SET_NMEA_BAUDRATE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1c16678ddc76189e4215f65893655821", null ], + [ "PMTK_SET_OUTPUT_FMT", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beac94b5ff1087757868d8afeff20c011fa", null ], + [ "PMTK_SET_SYNC_PPS_NMEA", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaec48bc94e3f15bdf3f9eda6d76fbd7ab", null ], + [ "PMTK_SET_TIMING_PRODUCT", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1265f33d4aba1384f11ef5872119f573", null ], + [ "PMTK_SET_HIGH_ACCURACY", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea56cefa0d6551ed89dc1974929c35a875", null ], + [ "PMTK_SET_GLP_MODE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa23a5c6e8e35b989498e6b6b101731e7", null ], + [ "PMTK_SET_NMEA_DECIMAL_PRECISION", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9e2fbd7c984e5e6e082b3825b060ca00", null ], + [ "PMTK_SET_PPS_CONFIG_CMD", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea2855fd322f2e27500a2844b7776c1061", null ], + [ "PMTK_SET_AIC_CMD", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beabbbb799ada6d27a16cb6a9e7fabcc0fd", null ], + [ "PMTK_SET_OUTPUT_DEBUG", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8371d87a4fab64e97e5a53200fa6cda2", null ], + [ "PMTK_API_SET_DGPS_MODE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea83e665f81bc20f6d8e425e0749f3f288", null ], + [ "PMTK_API_SET_MIN_SNR", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8060ce5da125915a4b00f7aff4220889", null ], + [ "PMTK_API_SET_DR_LIMIT", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8782a9c367032850565b8d449225ddda", null ], + [ "PMTK_API_SET_ELEV_MASK", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaeb41c59cd96e6d16e343046893ff7442", null ], + [ "PMTK_API_SET_SBAS_ENABLED", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea153232faf17c74620043aa97852fbf93", null ], + [ "PMTK_API_SET_NMEA_OUTPUT", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9b58e4f853bd537a8d44fe1021c57bb1", null ], + [ "PMTK_API_SET_PPS", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beafab5347f328ae50a3b524cad27b2be8d", null ], + [ "PMTK_API_SET_HACC_MASK", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaafb3f64364e21510313190785e3fc7d0", null ], + [ "PMTK_API_SET_DATUM", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea467817db20c8c590ea5c065e5faa1f53", null ], + [ "PMTK_API_SET_DATUM_ADVANCE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaff110d710ff9d5961dd33c7291e5824d", null ], + [ "PMTK_API_SET_SUPPORT_QZSS_NMEA", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8ddbdbf2649933cc970f831500dfe66f", null ], + [ "PMTK_API_SET_STOP_QZSS", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa8d6e40f333aff7e4435f88809042ac8", null ], + [ "PMTK_API_SET_GNSS_SEARCH_MODE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea2edaf5cac4aa4a2fc73b5312d7428b24", null ], + [ "PMTK_API_GET_GNSS_OPERAT_MODE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beace569382848d8559a16fa090e8d56100", null ], + [ "PMTK_API_SET_HDOP_THRESHOLD", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea377b4ea82070d970dbfa11b6cf426594", null ], + [ "PMTK_API_GET_HDOP_THRESHOLD", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead7e27c02b08d6ff4296f7a67a00dfe26", null ], + [ "PMTK_API_SET_PLL", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9873165a5537dafa3b4c57dbea50d258", null ], + [ "PMTK_API_SET_HIGH_SENSITIVITY_TRACKING_NO_FIX", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea3fb309c02edc5daf43592d9f2959928e", null ], + [ "PMTK_API_SET_STATIC_NAVI_THD", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea144340c8d86359dce90bcdc73a1c3f47", null ], + [ "PMTK_API_SET_FLASH_DATA", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9b4d921b1fe8ac8f59195773a81a9aa3", null ], + [ "PMTK_API_Q_FIX_CTL", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8d1f075aa6a35cbca97ca5fb7ac07fa1", null ], + [ "PMTK_API_Q_DGPS_MODE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea55bd5f9f60b4113329eef6c1ad3ed296", null ], + [ "PMTK_API_Q_MIN_SNR", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea05ed0801721f44c80238d29c18bf9a02", null ], + [ "PMTK_API_Q_DR_LIMIT", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1ce00a71b2d49bed618e16eaf551cd9a", null ], + [ "PMTK_API_Q_ELEV_MASK", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa99559cfe61a412f1e302dc39021b879", null ], + [ "PMTK_API_Q_SBAS_ENABLED", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaf1a7e2d71a17c147d1ef007986a29cfb", null ], + [ "PMTK_API_Q_NMEA_OUTPUT", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa932726f1937dfdd7955fbee8819489a", null ], + [ "PMTK_API_Q_HACC_MASK", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8a11d9cb5cca390770b0f6b6ffc64b5a", null ], + [ "PMTK_API_Q_DATUM", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea94e91e0b1e6fa7207f32a1f49bdf5c94", null ], + [ "PMTK_API_Q_DATUM_ADVANCE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead2312b41c26e764ef34621c560f9973c", null ], + [ "PMTK_API_Q_RTC_TIME", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa84af36afd8dbaa82b104bbf0b263592", null ], + [ "PMTK_API_Q_HIGH_SENSITIVITY_TRACKING_NO_FIX", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab3eae09a18fc5417f8b359d9efdfd235", null ], + [ "PMTK_API_Q_EPH_STATUS", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea349fe122413c42817cdd46f0888a6c5f", null ], + [ "PMTK_API_GET_POS_XYZ", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab139be3d7b4b2482f2838bac51db2b39", null ], + [ "PMTK_API_GET_VEL_XYZ", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea32f454682a68a9c3bccef8e25b15b8ba", null ], + [ "PMTK_API_GET_FLASH_DATA", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea063d8815c8ee51cd08acda80daa1e81e", null ], + [ "PMTK_DT_FIX_CTL", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9c0c1ca48067fdd105f70e04487ff701", null ], + [ "PMTK_DT_DGPS_MODE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea08e334f61a3facbee28df70210d878d3", null ], + [ "PMTK_DT_SBAS_ENABLED", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae99971090e79d0b006294059e32301b0", null ], + [ "PMTK_DT_NMEA_OUTPUT", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab2b4ec0b0540e9fc51bc8a839d44c8ff", null ], + [ "PMTK_DT_HACC_MASK", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea807d8bf7605b87d790f4593f06dbb2f6", null ], + [ "PMTK_DT_DATUM", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab85d515c5cb70af97c6afb7f15e225b2", null ], + [ "PMTK_DT_RTC_TIME", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea6732848b6864eda4c0bf2d6e665ebeb9", null ], + [ "PMTK_DT_HIGH_SENSITIVITY_TRACKING_NO_FIX", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beabadd7524424255f446ccfd0a37b1df97", null ], + [ "PMTK_DT_FLASH_DATA", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae4a762e079462ab42723d0052ad9c5b4", null ], + [ "PMTK_Q_DATA_PORT", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead90684782d20bd184adebce214da0fb7", null ], + [ "PMTK_Q_RELEASE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaf8a05f41e01df87665ca9237aa9f416e", null ], + [ "PMTK_Q_EPO_INFO", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea3f53bb52d96bb7739b2c6cf17d05c268", null ], + [ "PMTK_Q_LOCUS_DATA", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea2625b3468647086a44ea53b5e7b58288", null ], + [ "PMTK_Q_AVAILABLE_SV_EPH", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab0a80b268936db695d5a7ccff70e10bf", null ], + [ "PMTK_Q_AVAILABLE_SV_ALM", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae8b254db5898fe8f36f6f650d81cb0d1", null ], + [ "PMTK_Q_UTC_CORRECTION_DATA", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead7650c8cb304121491fdf61bc284c036", null ], + [ "PMTK_Q_GPS_KEP", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea72e57a8d23a2f9d09d2c9685cb93d9c7", null ], + [ "PMTK_Q_BDS_KEP", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea6dc3a9739c6f1928716ee2c97e28204b", null ], + [ "PMTK_Q_GPS_IONO", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9c90d1ead04106ba8d52a532d9e0cb14", null ], + [ "PMTK_DT_DATA_PORT", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae96a7db722c3fbaececd2c8d9a45b19c", null ], + [ "PMTK_DT_RELEASE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beac6d9aff834a28ac4feddf34a66102a43", null ], + [ "PMTK_DT_EPO_INFO", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea6b852645bdf9e0680bb45017559105e5", null ], + [ "PMTK_DT_SV_EPO", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1397b023e0d48ec75adabef05a22e061", null ], + [ "PMTK_DT_UTC", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1f021ebe90b969144edb422d2e41d62d", null ], + [ "PMTK_DT_POS", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea00bfa74b9ab4be1cb538d6720808c007", null ], + [ "PMTK_TEST_ALL", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea19e1adb3e180af8c09c84c63ae9e789f", null ], + [ "PMTK_TEST_STOP", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea7bc54655b91905cd5de5770adef0b58e", null ], + [ "PMTK_TEST_FINISH", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea037ee569708e29066d04d6b24a589998", null ], + [ "PMTK_TEST_ALL_ACQ", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae2dbe959ff5bc2dcd3dc71a92d5c053c", null ], + [ "PMTK_TEST_ALL_BITSYNC", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa93754c9b38d52d93c691c0ab53a7b7d", null ], + [ "PMTK_TEST_ALL_SIGNAL", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead90d6c9f7c3e751fd1cab1b92187bfb0", null ], + [ "PMTK_TEST_JAMMING", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea86e6074288800bb3626e16e735dcc6f8", null ], + [ "PMTK_TEST_JAMMING_DETECTION", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea42011586fa1fca5a3643cac6b05b60c0", null ], + [ "PMTK_EASY_ENABLE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea2ac3e95cf254fb53202aa90270d17492", null ], + [ "PTMK_PMTKLSC_STN_OUTPUT", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beadd3af74a2c6d9ea8a5411dfdb51e93a4", null ], + [ "PMTK_FR_MODE", "group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1552640a94f244c1a0c27e14bafdd426", null ] + ] ] +]; \ No newline at end of file diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/index.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/index.html" new file mode 100644 index 0000000..c02ab7c --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/index.html" @@ -0,0 +1,456 @@ + + + + + + +MT33xx GNSS PMTK User's Guide: Introduction + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
MT33xx GNSS PMTK User's Guide +  Version 1.2.0 +
+
+
+ + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+ +
+ +
+
+
Introduction
+
+
+

+Overview

+

PMTK command is a MediaTek proprietary GNSS data transfer protocol. This protocol is used to configure the GNSS module's parameters, aiding information and to receive notifications from the GNSS module. The PMTK aligns with the NMEA sentence format to process data more conveniently.


+

+Command Format

+

The PMTK packet format with number of bytes allocated for each field is show in the table.

+ + + + +
1 4 3 variable 1 1 1 1 1
Preamble Tracker ID PktType DataField * CHK1 CHK2 CR LF
+

The details of each field in the packet are provided in the table.

+ + + + + + + + + + + + + + + + +
Parameter Description
Preamble One byte character.
+ - Example, '$'
TalkerID Four bytes character string.
+ - Example, PMTK.
PktType Three bytes character string.
+ - From 000 to 999. An identifier used to tell the decoder how to decode the packet.
DataField Has a variable length depending on the packet type.
+ - A comma symbol ',' must be inserted ahead each data filed to help the decoder process the DataField.
* One byte character.
+ - The star symbol is used to mark the end of the DataField.
CHK1, CHK2 One byte character for each.
+ - CHK1 and CHK2 are the checksum of the data between Preamble and '*'.
CR, LF One byte ASCII data for each.
+ - The two bytes are used to identify the end of a packet.
+

+Command List

+

The PMTK command list for each packet type is given in the table.
+

Note
1. The commands with "_SET_" are set commands, to set the GNSS configuration. The commands with "_Q_" are query commands, to query GNSS configuration set by the set commands with "_SET_". The commands with "_DT_" are the response to the query commands.
+ 2. You can check the result in response of PMTK001 after send a PMTK command.
+

PMTK Command Table:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Packet Type Command Description
000 PMTK_TEST Test Packet.
001 PMTK_ACK Acknowledge of PMTK command.
010 PMTK_SYS_MSG System output message.
011 PMTK_TXT_MSG Output system text message.
101 PMTK_CMD_HOT_START Hot Start. Use the available data in the NVRAM.
102 PMTK_CMD_WARM_START Warm Start. Not using Ephemeris data at start.
103 PMTK_CMD_COLD_START Cold Start. Not using the Position, Almanac and Ephemeris data at start.
104 PMTK_CMD_FULL_COLD_START Full Cold Start.
127 PMTK_CMD_CLEAR_EPO Erase the EPO data stored in the flash memory.
161 PMTK_CMD_STANDBY_MODE Enter standby modes (stop mode or sleep mode) for power saving.
183 PMTK_LOCUS_QUERY_STATUS Query the GNSS is in the log status or not.
184 PMTK_LOCUS_ERASE_FLASH Erase the logged GNSS data on the flash.
185 PMTK_LOCUS_STOP_LOGGER Stop the data logging.
186 PMTK_LOCUS_LOG_NOW Snapshot write log.
187 PMTK_LOCUS_CONFIG Configure Locus settings by command.
220 PMTK_SET_POS_FIX Position Fix Interval.
223 PMTK_SET_AL_DEE_CFG Used for setting periodic mode parameters and is used after PMTK225 command.
225 PMTK_SET_PERIODIC_MODE Periodic Power Saving Mode Settings: (See following chart).
250 PMTK_SET_DATA_PORT Set data port input/output data type and baudrate.
251 PMTK_SET_NMEA_BAUDRATE Set NMEA port baudrate.
253 PMTK_SET_OUTPUT_FMT Set data output format for current port.
255 PMTK_SET_SYNC_PPS_NMEA Enable or disable fixed NMEA output time in pulse per second (PPS) function (default value is "0").
256 PMTK_SET_TIMING_PRODUCT Enable or disable timing product mode (Default off).
257 PMTK_SET_HIGH_ACCURACY Enable fast TTFF or high accuracy function when out of the tunnel or garage. (Default enabled high accuracy function).
262 PMTK_SET_GLP_MODE Enable or disable GNSS Low Power(GLP) mode.
265 PMTK_SET_NMEA_DECIMAL_PRECISION Set number of fractional digit in NMEA.
285 PMTK_SET_PPS_CONFIG_CMD Configure the PPS settings.
286 PMTK_SET_AIC_CMD Enable or disable active interference cancellation function.
299 PMTK_SET_OUTPUT_DEBUG Enable or disable the Debug log output.
301 PMTK_API_SET_DGPS_MODE DGPS correction data source mode.
306 PMTK_API_SET_MIN_SNR Set the minimum SNR of used satellites.
308 PMTK_API_SET_DR_LIMIT Set the number of estimated fix when entering the tunnel.
311 PMTK_API_SET_ELEV_MASK Set satellite elevation mask.
313 PMTK_API_SET_SBAS_ENABLED Enable to search a SBAS satellite or not.
314 PMTK_API_SET_NMEA_OUTPUT Set the NMEA sentence output type and frequencies.
326 PMTK_API_SET_PPS This packet contains the local time in milliseconds and phase where the PPS should be placed.
328 PMTK_API_SET_HACC_MASK Set horizontal accuracy mask. Range from 30m to 200m or -1. GPS will get fix only when hacc value < mask.
330 PMTK_API_SET_DATUM Set default datum.
331 PMTK_API_SET_DATUM_ADVANCE Set user defined datum.
351 PMTK_API_SET_SUPPORT_QZSS_NMEA The receiver supports new NMEA format for QZSS. The command allow user enable or disable QZSS NMEA format.
352 PMTK_API_SET_STOP_QZSS Since QZSS is regional positioning service. The command allow user enable or disable QZSS function.
353 PMTK_API_SET_GNSS_SEARCH_MODE Configure the receiver to start searching for satellites. The setting is available when the NVRAM data is valid.
355 PMTK_API_GET_GNSS_OPERAT_MODE This command is to get GPS,GLONASS, BeiDou and GALILEO search settings.
356 PMTK_API_SET_HDOP_THRESHOLD This command is to set the HDOP threshold.
357 PMTK_API_GET_HDOP_THRESHOLD This command is to get the HDOP threshold.
381 PMTK_API_SET_PLL Set PLL on or off.
385 PMTK_API_SET_HIGH_SENSITIVITY_TRACKING_NO_FIX Disable/Enable position output in high sensitivity tracking mode.
386 PMTK_API_SET_STATIC_NAVI_THD Set the speed threshold for static navigation.
399 PMTK_API_SET_FLASH_DATA Write data to the flash.
400 PMTK_API_Q_FIX_CTL API_Query_Fix_Ctl
401 PMTK_API_Q_DGPS_MODE API_Query_Dgps_Mode
406 PMTK_API_Q_MIN_SNR Query the minimum SNR of used satellites.
408 PMTK_API_Q_DR_LIMIT Query the number of estimated fix when entering the tunnel.
411 PMTK_API_Q_ELEV_MASK Query satellite elevation mask.
413 PMTK_API_Q_SBAS_ENABLED Query the status of SBAS to check if it is enabled or not.
414 PMTK_API_Q_NMEA_OUTPUT Query current NMEA sentence output frequencies.
428 PMTK_API_Q_HACC_MASK Query horizontal accuracy mask.
430 PMTK_API_Q_DATUM Query default datum.
431 PMTK_API_Q_DATUM_ADVANCE Query user defined datum.
435 PMTK_API_Q_RTC_TIME Query current RTC UTC time.
436 PMTK_API_Q_HIGH_SENSITIVITY_TRACKING_NO_FIX Query setting of position output disabled/enabled in high sensitivity tracking mode.
449 PMTK_API_Q_EPH_STATUS This command is to query the current status of ephemeris downloading
458 PMTK_API_GET_POS_XYZ Returns the WGS84 ECEF XYZ Cartesian Position vector ( metres ) with an estimated 1-sigma accuracy.
461 PMTK_API_GET_VEL_XYZ Returns the WGS84 ECEF XYZ Cartesian velocity vector ( m/s ) with an estimated 1-sigma accuracy.
499 PMTK_API_GET_FLASH_DATA Read the flash memory.
500 PMTK_DT_FIX_CTL These parameters show the rate of position fixing activity.
501 PMTK_DT_DGPS_MODE DGPS Data Source Mode.
513 PMTK_DT_SBAS_ENABLED Enable or disable searching for SBAS satellites.
514 PMTK_DT_NMEA_OUTPUT The NMEA sentence output frequency configuration.
528 PMTK_DT_HACC_MASK Current horizontal accuracy mask.
530 PMTK_DT_DATUM Current datum used.
535 PMTK_DT_RTC_TIME This packet carries current RTC UTC time.
536 PMTK_DT_HIGH_SENSITIVITY_TRACKING_NO_FIX This packet carries setting of position output disabled/enabled in high sensitivity tracking mode.
599 PMTK_DT_FLASH_DATA The data in the flash memory.
602 PMTK_Q_DATA_PORT Read data port input/output data type and baudrate.
605 PMTK_Q_RELEASE Query the firmware release information.
607 PMTK_Q_EPO_INFO Query the EPO data status stored in the GPS chip.
622 PMTK_Q_LOCUS_DATA Use Locus tool to retrieve the logging data from the NVRAM.
660 PMTK_Q_AVAILABLE_SV_EPH Support PMTK660 which report valid Ephemeris SV.
661 PMTK_Q_AVAILABLE_SV_ALM Support PMTK661 which report valid Almanac SV.
667 PMTK_Q_UTC_CORRECTION_DATA Get UTC correction data.
668 PMTK_Q_GPS_KEP Get GPS ephemeris data in kepler format.
669 PMTK_Q_BDS_KEP Get BDS ephemeris data in kepler format.
670 PMTK_Q_GPS_IONO Query ionospheric parameters.
702 PMTK_DT_DATA_PORT Display Data port input/output data type and baud rate.
705 PMTK_DT_RELEASE Firmware release information.
707 PMTK_DT_EPO_INFO EPO data status stored in GPS chip.
721 PMTK_DT_SV_EPO The packet contains GPS EPO data for a single satellite.
740 PMTK_DT_UTC The packet contains current UTC time.
741 PMTK_DT_POS The packet contains reference location for the GNSS module.
810 PMTK_TEST_ALL Enter MP test mode and set test item and SV id.
811 PMTK_TEST_STOP Testing tool could send this command to GPS receiver to leave MP test mode.
812 PMTK_TEST_FINISH GPS receiver will send out this PMTK packet to show that MP testing has finished.
813 PMTK_TEST_ALL_ACQ The result of TEST_ACQ item.
814 PMTK_TEST_ALL_BITSYNC The result of TEST_BITSYNC item.
815 PMTK_TEST_ALL_SIGNAL The result of TEST_SIGNAL item.
837 PMTK_TEST_JAMMING Jamming scan test command.
838 PMTK_TEST_JAMMING_DETECTION Jamming detection test command.
869 PMTK_EASY_ENABLE Enable or disable EASY function. Query if EASYis enabled orr disabled.
875 PTMK_PMTKLSC_STN_OUTPUT Enable or disable PMTKLSC Sentence output.Query if PMTKLSC Sentence output enabled or disabled.
886 PMTK_FR_MODE Set navigation mode.
+
+

+Version Control

+ + + + + + + + + + + + + + + + + + + + + + + +
Version Date Description
3.0 2014/07/11 Initial version.
+ Based on 2.16.
+ 1. Add PMTKJAM
3.1 2014/10/15 1. Delete PMTK389
+ 2. Delete PMTK589
+ 3. Modify the description of PMTK301
+ 4. Modify the description of PMTK314
+ 5. Modify the description of PMTK353
+ 6. Add PMTK183
+ 7. Add PMTK184
+ 8. Add PMTK185
+ 9. Add PMTK186
+ 10. Add PMTK622
3.2 2015/02/13 1. Modify the description of PMTK183
+ 2. Modify the description of PMTK220
+ 3. Add PMTK253
+ 4. Add PMTK435
+ 5. Modify the description of PMTK500
+ 6. Add PMTK535
+ 7. Add PMTK602
+ 8. Add PMTK668
+ 9. Add PMTK669
+ 10. Add PMTK702
+ 11. Add PMTK707
+ 12. Add PMTK721
3.3 2015/06/10 1. Add PMTK256
+ 2. Add PMTK257
+ 3. Delete PMTK300
+ 4. Modify PMTK314
+ 5. Modify PMTK352
+ 6. Modify PMTK622
+ 7. Modify PMTK667
+ 8. Modify PMTK886
3.4 2015/10/19 1. Correct PMTK875 checksum
+ 2. Modify PMTK255
+ 3. Correct PMTK314 checksum
+ 4. Add PMTK311
+ 5. Add PMTK411
+ 6. Add PMTK262
+ 7. Add PMTK449
3.5 2016/04/15 1. Modify PMTK262
+ 2. Add PMTK306
+ 3. Add PMTK308
+ 4. Modify PMTK355
+ 5. Add PMTK406
+ 6. Add PMTK408
+ 7. Modify PMTK741
+ 8. Modify PMTK837
3.6 2016/12/16 1. Remove PMTK120
+ 2. Add PMTK838
+ 3. Update PMTK886 altitude limit
1.0.0 2017/01/01 1. Rename to "MT33xx_GNSS_PMTK_Users_Guide".
+ 2. Reset version as "Version 1.0.0".
1.1.0 2017/02/22 1. Add PMTK189.
+ 2. Modify PMTK260.
+ 3. PMTK262 renaming.
+ 4. Add PMTK328.
+ 5. Add PMTK381.
+ 6. Add PMTK385.
+ 7. Add PMTK428.
+ 8. Add PMTK436.
+ 9. Add PMTK528.
+ 9. Add PMTK536.
+ 10. PMTK838 renaming.
+ 11. Modify PMTK220.
+ 12. Modify PMTK886.
1.2.0 2017/04/17 1. ANX 5.1 release for GALILEO satellites.
+ 2. Add PMTK265.
+ 3. Removed PMTK335.
+ 4. Add PMTK458.
+ 5. Add PMTK461.
+
+

+License

+

Copyright Statement:

+

(C) 2005-2016 MediaTek Inc. All rights reserved.

+

This software/firmware and related documentation ("MediaTek Software") are protected under relevant copyright laws. The information contained herein is confidential and proprietary to MediaTek Inc. ("MediaTek") and/or its licensors. Without the prior written permission of MediaTek and/or its licensors, any reproduction, modification, use or disclosure of MediaTek Software, and information contained herein, in whole or in part, shall be strictly prohibited. You may only use, reproduce, modify, or distribute (as applicable) MediaTek Software if you have agreed to and been bound by the applicable license agreement with MediaTek ("License Agreement") and been granted explicit permission to do so within the License Agreement ("Permitted User"). If you are not a Permitted User, please cease any access or use of MediaTek Software immediately. BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES THAT MEDIATEK SOFTWARE RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.

+
+
+ + + + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/jquery.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/jquery.js" new file mode 100644 index 0000000..1f4d0b4 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/jquery.js" @@ -0,0 +1,68 @@ +/*! + * jQuery JavaScript Library v1.7.1 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Mon Nov 21 21:11:03 2011 -0500 + */ +(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
a";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="
";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
t
";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="
";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType;if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bCbA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},ac=a(av);ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
","
"]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1>");try{for(var bw=0,bv=this.length;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]===""&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length;if(bA>0){if(bv!=="border"){for(;bx)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b})}})(window);/*! + * jQuery UI 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI + */ +(function(a,d){a.ui=a.ui||{};if(a.ui.version){return}a.extend(a.ui,{version:"1.8.18",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(e,f){return typeof e==="number"?this.each(function(){var g=this;setTimeout(function(){a(g).focus();if(f){f.call(g)}},e)}):this._focus.apply(this,arguments)},scrollParent:function(){var e;if((a.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){e=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(a.curCSS(this,"position",1))&&(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}else{e=this.parents().filter(function(){return(/(auto|scroll)/).test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!e.length?a(document):e},zIndex:function(h){if(h!==d){return this.css("zIndex",h)}if(this.length){var f=a(this[0]),e,g;while(f.length&&f[0]!==document){e=f.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){g=parseInt(f.css("zIndex"),10);if(!isNaN(g)&&g!==0){return g}}f=f.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});a.each(["Width","Height"],function(g,e){var f=e==="Width"?["Left","Right"]:["Top","Bottom"],h=e.toLowerCase(),k={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};function j(m,l,i,n){a.each(f,function(){l-=parseFloat(a.curCSS(m,"padding"+this,true))||0;if(i){l-=parseFloat(a.curCSS(m,"border"+this+"Width",true))||0}if(n){l-=parseFloat(a.curCSS(m,"margin"+this,true))||0}});return l}a.fn["inner"+e]=function(i){if(i===d){return k["inner"+e].call(this)}return this.each(function(){a(this).css(h,j(this,i)+"px")})};a.fn["outer"+e]=function(i,l){if(typeof i!=="number"){return k["outer"+e].call(this,i)}return this.each(function(){a(this).css(h,j(this,i,true,l)+"px")})}});function c(g,e){var j=g.nodeName.toLowerCase();if("area"===j){var i=g.parentNode,h=i.name,f;if(!g.href||!h||i.nodeName.toLowerCase()!=="map"){return false}f=a("img[usemap=#"+h+"]")[0];return !!f&&b(f)}return(/input|select|textarea|button|object/.test(j)?!g.disabled:"a"==j?g.href||e:e)&&b(g)}function b(e){return !a(e).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.extend(a.expr[":"],{data:function(g,f,e){return !!a.data(g,e[3])},focusable:function(e){return c(e,!isNaN(a.attr(e,"tabindex")))},tabbable:function(g){var e=a.attr(g,"tabindex"),f=isNaN(e);return(f||e>=0)&&c(g,!f)}});a(function(){var e=document.body,f=e.appendChild(f=document.createElement("div"));f.offsetHeight;a.extend(f.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});a.support.minHeight=f.offsetHeight===100;a.support.selectstart="onselectstart" in f;e.removeChild(f).style.display="none"});a.extend(a.ui,{plugin:{add:function(f,g,j){var h=a.ui[f].prototype;for(var e in j){h.plugins[e]=h.plugins[e]||[];h.plugins[e].push([g,j[e]])}},call:function(e,g,f){var j=e.plugins[g];if(!j||!e.element[0].parentNode){return}for(var h=0;h0){return true}h[e]=1;g=(h[e]>0);h[e]=0;return g},isOverAxis:function(f,e,g){return(f>e)&&(f<(e+g))},isOver:function(j,f,i,h,e,g){return a.ui.isOverAxis(j,i,e)&&a.ui.isOverAxis(f,h,g)}})})(jQuery);/*! + * jQuery UI Widget 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Widget + */ +(function(b,d){if(b.cleanData){var c=b.cleanData;b.cleanData=function(f){for(var g=0,h;(h=f[g])!=null;g++){try{b(h).triggerHandler("remove")}catch(j){}}c(f)}}else{var a=b.fn.remove;b.fn.remove=function(e,f){return this.each(function(){if(!f){if(!e||b.filter(e,[this]).length){b("*",this).add([this]).each(function(){try{b(this).triggerHandler("remove")}catch(g){}})}}return a.call(b(this),e,f)})}}b.widget=function(f,h,e){var g=f.split(".")[0],j;f=f.split(".")[1];j=g+"-"+f;if(!e){e=h;h=b.Widget}b.expr[":"][j]=function(k){return !!b.data(k,f)};b[g]=b[g]||{};b[g][f]=function(k,l){if(arguments.length){this._createWidget(k,l)}};var i=new h();i.options=b.extend(true,{},i.options);b[g][f].prototype=b.extend(true,i,{namespace:g,widgetName:f,widgetEventPrefix:b[g][f].prototype.widgetEventPrefix||f,widgetBaseClass:j},e);b.widget.bridge(f,b[g][f])};b.widget.bridge=function(f,e){b.fn[f]=function(i){var g=typeof i==="string",h=Array.prototype.slice.call(arguments,1),j=this;i=!g&&h.length?b.extend.apply(null,[true,i].concat(h)):i;if(g&&i.charAt(0)==="_"){return j}if(g){this.each(function(){var k=b.data(this,f),l=k&&b.isFunction(k[i])?k[i].apply(k,h):k;if(l!==k&&l!==d){j=l;return false}})}else{this.each(function(){var k=b.data(this,f);if(k){k.option(i||{})._init()}else{b.data(this,f,new e(i,this))}})}return j}};b.Widget=function(e,f){if(arguments.length){this._createWidget(e,f)}};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(f,g){b.data(g,this.widgetName,this);this.element=b(g);this.options=b.extend(true,{},this.options,this._getCreateOptions(),f);var e=this;this.element.bind("remove."+this.widgetName,function(){e.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(f,g){var e=f;if(arguments.length===0){return b.extend({},this.options)}if(typeof f==="string"){if(g===d){return this.options[f]}e={};e[f]=g}this._setOptions(e);return this},_setOptions:function(f){var e=this;b.each(f,function(g,h){e._setOption(g,h)});return this},_setOption:function(e,f){this.options[e]=f;if(e==="disabled"){this.widget()[f?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",f)}return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(e,f,g){var j,i,h=this.options[e];g=g||{};f=b.Event(f);f.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase();f.target=this.element[0];i=f.originalEvent;if(i){for(j in i){if(!(j in f)){f[j]=i[j]}}}this.element.trigger(f,g);return !(b.isFunction(h)&&h.call(this.element[0],f,g)===false||f.isDefaultPrevented())}}})(jQuery);/*! + * jQuery UI Mouse 1.8.18 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Mouse + * + * Depends: + * jquery.ui.widget.js + */ +(function(b,c){var a=false;b(document).mouseup(function(d){a=false});b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var d=this;this.element.bind("mousedown."+this.widgetName,function(e){return d._mouseDown(e)}).bind("click."+this.widgetName,function(e){if(true===b.data(e.target,d.widgetName+".preventClickEvent")){b.removeData(e.target,d.widgetName+".preventClickEvent");e.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(f){if(a){return}(this._mouseStarted&&this._mouseUp(f));this._mouseDownEvent=f;var e=this,g=(f.which==1),d=(typeof this.options.cancel=="string"&&f.target.nodeName?b(f.target).closest(this.options.cancel).length:false);if(!g||d||!this._mouseCapture(f)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){e.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(f)&&this._mouseDelayMet(f)){this._mouseStarted=(this._mouseStart(f)!==false);if(!this._mouseStarted){f.preventDefault();return true}}if(true===b.data(f.target,this.widgetName+".preventClickEvent")){b.removeData(f.target,this.widgetName+".preventClickEvent")}this._mouseMoveDelegate=function(h){return e._mouseMove(h)};this._mouseUpDelegate=function(h){return e._mouseUp(h)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);f.preventDefault();a=true;return true},_mouseMove:function(d){if(b.browser.msie&&!(document.documentMode>=9)&&!d.button){return this._mouseUp(d)}if(this._mouseStarted){this._mouseDrag(d);return d.preventDefault()}if(this._mouseDistanceMet(d)&&this._mouseDelayMet(d)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,d)!==false);(this._mouseStarted?this._mouseDrag(d):this._mouseUp(d))}return !this._mouseStarted},_mouseUp:function(d){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;if(d.target==this._mouseDownEvent.target){b.data(d.target,this.widgetName+".preventClickEvent",true)}this._mouseStop(d)}return false},_mouseDistanceMet:function(d){return(Math.max(Math.abs(this._mouseDownEvent.pageX-d.pageX),Math.abs(this._mouseDownEvent.pageY-d.pageY))>=this.options.distance)},_mouseDelayMet:function(d){return this.mouseDelayMet},_mouseStart:function(d){},_mouseDrag:function(d){},_mouseStop:function(d){},_mouseCapture:function(d){return true}})})(jQuery);(function(c,d){c.widget("ui.resizable",c.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000},_create:function(){var f=this,k=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(k.aspectRatio),aspectRatio:k.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:k.helper||k.ghost||k.animate?k.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){this.element.wrap(c('
').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=k.handles||(!c(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var l=this.handles.split(",");this.handles={};for(var g=0;g
');if(/sw|se|ne|nw/.test(j)){h.css({zIndex:++k.zIndex})}if("se"==j){h.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[j]=".ui-resizable-"+j;this.element.append(h)}}this._renderAxis=function(q){q=q||this.element;for(var n in this.handles){if(this.handles[n].constructor==String){this.handles[n]=c(this.handles[n],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var o=c(this.handles[n],this.element),p=0;p=/sw|ne|nw|se|n|s/.test(n)?o.outerHeight():o.outerWidth();var m=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");q.css(m,p);this._proportionallyResize()}if(!c(this.handles[n]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!f.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}f.axis=i&&i[1]?i[1]:"se"}});if(k.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){if(k.disabled){return}c(this).removeClass("ui-resizable-autohide");f._handles.show()},function(){if(k.disabled){return}if(!f.resizing){c(this).addClass("ui-resizable-autohide");f._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var e=function(g){c(g).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){e(this.element);var f=this.element;f.after(this.originalElement.css({position:f.css("position"),width:f.outerWidth(),height:f.outerHeight(),top:f.css("top"),left:f.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);e(this.originalElement);return this},_mouseCapture:function(f){var g=false;for(var e in this.handles){if(c(this.handles[e])[0]==f.target){g=true}}return !this.options.disabled&&g},_mouseStart:function(g){var j=this.options,f=this.element.position(),e=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(e.is(".ui-draggable")||(/absolute/).test(e.css("position"))){e.css({position:"absolute",top:f.top,left:f.left})}this._renderProxy();var k=b(this.helper.css("left")),h=b(this.helper.css("top"));if(j.containment){k+=c(j.containment).scrollLeft()||0;h+=c(j.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:k,top:h};this.size=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalSize=this._helper?{width:e.outerWidth(),height:e.outerHeight()}:{width:e.width(),height:e.height()};this.originalPosition={left:k,top:h};this.sizeDiff={width:e.outerWidth()-e.width(),height:e.outerHeight()-e.height()};this.originalMousePosition={left:g.pageX,top:g.pageY};this.aspectRatio=(typeof j.aspectRatio=="number")?j.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var i=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",i=="auto"?this.axis+"-resize":i);e.addClass("ui-resizable-resizing");this._propagate("start",g);return true},_mouseDrag:function(e){var h=this.helper,g=this.options,m={},q=this,j=this.originalMousePosition,n=this.axis;var r=(e.pageX-j.left)||0,p=(e.pageY-j.top)||0;var i=this._change[n];if(!i){return false}var l=i.apply(this,[e,r,p]),k=c.browser.msie&&c.browser.version<7,f=this.sizeDiff;this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey){l=this._updateRatio(l,e)}l=this._respectSize(l,e);this._propagate("resize",e);h.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(l);this._trigger("resize",e,this.ui());return false},_mouseStop:function(h){this.resizing=false;var i=this.options,m=this;if(this._helper){var g=this._proportionallyResizeElements,e=g.length&&(/textarea/i).test(g[0].nodeName),f=e&&c.ui.hasScroll(g[0],"left")?0:m.sizeDiff.height,k=e?0:m.sizeDiff.width;var n={width:(m.helper.width()-k),height:(m.helper.height()-f)},j=(parseInt(m.element.css("left"),10)+(m.position.left-m.originalPosition.left))||null,l=(parseInt(m.element.css("top"),10)+(m.position.top-m.originalPosition.top))||null;if(!i.animate){this.element.css(c.extend(n,{top:l,left:j}))}m.helper.height(m.size.height);m.helper.width(m.size.width);if(this._helper&&!i.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",h);if(this._helper){this.helper.remove()}return false},_updateVirtualBoundaries:function(g){var j=this.options,i,h,f,k,e;e={minWidth:a(j.minWidth)?j.minWidth:0,maxWidth:a(j.maxWidth)?j.maxWidth:Infinity,minHeight:a(j.minHeight)?j.minHeight:0,maxHeight:a(j.maxHeight)?j.maxHeight:Infinity};if(this._aspectRatio||g){i=e.minHeight*this.aspectRatio;f=e.minWidth/this.aspectRatio;h=e.maxHeight*this.aspectRatio;k=e.maxWidth/this.aspectRatio;if(i>e.minWidth){e.minWidth=i}if(f>e.minHeight){e.minHeight=f}if(hl.width),s=a(l.height)&&i.minHeight&&(i.minHeight>l.height);if(h){l.width=i.minWidth}if(s){l.height=i.minHeight}if(t){l.width=i.maxWidth}if(m){l.height=i.maxHeight}var f=this.originalPosition.left+this.originalSize.width,p=this.position.top+this.size.height;var k=/sw|nw|w/.test(q),e=/nw|ne|n/.test(q);if(h&&k){l.left=f-i.minWidth}if(t&&k){l.left=f-i.maxWidth}if(s&&e){l.top=p-i.minHeight}if(m&&e){l.top=p-i.maxHeight}var n=!l.width&&!l.height;if(n&&!l.left&&l.top){l.top=null}else{if(n&&!l.top&&l.left){l.left=null}}return l},_proportionallyResize:function(){var k=this.options;if(!this._proportionallyResizeElements.length){return}var g=this.helper||this.element;for(var f=0;f');var e=c.browser.msie&&c.browser.version<7,g=(e?1:0),h=(e?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+h,height:this.element.outerHeight()+h,position:"absolute",left:this.elementOffset.left-g+"px",top:this.elementOffset.top-g+"px",zIndex:++i.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(g,f,e){return{width:this.originalSize.width+f}},w:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{left:i.left+f,width:g.width-f}},n:function(h,f,e){var j=this.options,g=this.originalSize,i=this.originalPosition;return{top:i.top+e,height:g.height-e}},s:function(g,f,e){return{height:this.originalSize.height+e}},se:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},sw:function(g,f,e){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[g,f,e]))},ne:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[g,f,e]))},nw:function(g,f,e){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[g,f,e]))}},_propagate:function(f,e){c.ui.plugin.call(this,f,[e,this.ui()]);(f!="resize"&&this._trigger(f,e,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});c.extend(c.ui.resizable,{version:"1.8.18"});c.ui.plugin.add("resizable","alsoResize",{start:function(f,g){var e=c(this).data("resizable"),i=e.options;var h=function(j){c(j).each(function(){var k=c(this);k.data("resizable-alsoresize",{width:parseInt(k.width(),10),height:parseInt(k.height(),10),left:parseInt(k.css("left"),10),top:parseInt(k.css("top"),10)})})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.parentNode){if(i.alsoResize.length){i.alsoResize=i.alsoResize[0];h(i.alsoResize)}else{c.each(i.alsoResize,function(j){h(j)})}}else{h(i.alsoResize)}},resize:function(g,i){var f=c(this).data("resizable"),j=f.options,h=f.originalSize,l=f.originalPosition;var k={height:(f.size.height-h.height)||0,width:(f.size.width-h.width)||0,top:(f.position.top-l.top)||0,left:(f.position.left-l.left)||0},e=function(m,n){c(m).each(function(){var q=c(this),r=c(this).data("resizable-alsoresize"),p={},o=n&&n.length?n:q.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];c.each(o,function(s,u){var t=(r[u]||0)+(k[u]||0);if(t&&t>=0){p[u]=t||null}});q.css(p)})};if(typeof(j.alsoResize)=="object"&&!j.alsoResize.nodeType){c.each(j.alsoResize,function(m,n){e(m,n)})}else{e(j.alsoResize)}},stop:function(e,f){c(this).removeData("resizable-alsoresize")}});c.ui.plugin.add("resizable","animate",{stop:function(i,n){var p=c(this).data("resizable"),j=p.options;var h=p._proportionallyResizeElements,e=h.length&&(/textarea/i).test(h[0].nodeName),f=e&&c.ui.hasScroll(h[0],"left")?0:p.sizeDiff.height,l=e?0:p.sizeDiff.width;var g={width:(p.size.width-l),height:(p.size.height-f)},k=(parseInt(p.element.css("left"),10)+(p.position.left-p.originalPosition.left))||null,m=(parseInt(p.element.css("top"),10)+(p.position.top-p.originalPosition.top))||null;p.element.animate(c.extend(g,m&&k?{top:m,left:k}:{}),{duration:j.animateDuration,easing:j.animateEasing,step:function(){var o={width:parseInt(p.element.css("width"),10),height:parseInt(p.element.css("height"),10),top:parseInt(p.element.css("top"),10),left:parseInt(p.element.css("left"),10)};if(h&&h.length){c(h[0]).css({width:o.width,height:o.height})}p._updateCache(o);p._propagate("resize",i)}})}});c.ui.plugin.add("resizable","containment",{start:function(f,r){var t=c(this).data("resizable"),j=t.options,l=t.element;var g=j.containment,k=(g instanceof c)?g.get(0):(/parent/.test(g))?l.parent().get(0):g;if(!k){return}t.containerElement=c(k);if(/document/.test(g)||g==document){t.containerOffset={left:0,top:0};t.containerPosition={left:0,top:0};t.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var n=c(k),i=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){i[p]=b(n.css("padding"+o))});t.containerOffset=n.offset();t.containerPosition=n.position();t.containerSize={height:(n.innerHeight()-i[3]),width:(n.innerWidth()-i[1])};var q=t.containerOffset,e=t.containerSize.height,m=t.containerSize.width,h=(c.ui.hasScroll(k,"left")?k.scrollWidth:m),s=(c.ui.hasScroll(k)?k.scrollHeight:e);t.parentData={element:k,left:q.left,top:q.top,width:h,height:s}}},resize:function(g,q){var t=c(this).data("resizable"),i=t.options,f=t.containerSize,p=t.containerOffset,m=t.size,n=t.position,r=t._aspectRatio||g.shiftKey,e={top:0,left:0},h=t.containerElement;if(h[0]!=document&&(/static/).test(h.css("position"))){e=p}if(n.left<(t._helper?p.left:0)){t.size.width=t.size.width+(t._helper?(t.position.left-p.left):(t.position.left-e.left));if(r){t.size.height=t.size.width/i.aspectRatio}t.position.left=i.helper?p.left:0}if(n.top<(t._helper?p.top:0)){t.size.height=t.size.height+(t._helper?(t.position.top-p.top):t.position.top);if(r){t.size.width=t.size.height*i.aspectRatio}t.position.top=t._helper?p.top:0}t.offset.left=t.parentData.left+t.position.left;t.offset.top=t.parentData.top+t.position.top;var l=Math.abs((t._helper?t.offset.left-e.left:(t.offset.left-e.left))+t.sizeDiff.width),s=Math.abs((t._helper?t.offset.top-e.top:(t.offset.top-p.top))+t.sizeDiff.height);var k=t.containerElement.get(0)==t.element.parent().get(0),j=/relative|absolute/.test(t.containerElement.css("position"));if(k&&j){l-=t.parentData.left}if(l+t.size.width>=t.parentData.width){t.size.width=t.parentData.width-l;if(r){t.size.height=t.size.width/t.aspectRatio}}if(s+t.size.height>=t.parentData.height){t.size.height=t.parentData.height-s;if(r){t.size.width=t.size.height*t.aspectRatio}}},stop:function(f,n){var q=c(this).data("resizable"),g=q.options,l=q.position,m=q.containerOffset,e=q.containerPosition,i=q.containerElement;var j=c(q.helper),r=j.offset(),p=j.outerWidth()-q.sizeDiff.width,k=j.outerHeight()-q.sizeDiff.height;if(q._helper&&!g.animate&&(/relative/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}if(q._helper&&!g.animate&&(/static/).test(i.css("position"))){c(this).css({left:r.left-e.left-m.left,width:p,height:k})}}});c.ui.plugin.add("resizable","ghost",{start:function(g,h){var e=c(this).data("resizable"),i=e.options,f=e.size;e.ghost=e.originalElement.clone();e.ghost.css({opacity:0.25,display:"block",position:"relative",height:f.height,width:f.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:"");e.ghost.appendTo(e.helper)},resize:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost){e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})}},stop:function(f,g){var e=c(this).data("resizable"),h=e.options;if(e.ghost&&e.helper){e.helper.get(0).removeChild(e.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(e,m){var p=c(this).data("resizable"),h=p.options,k=p.size,i=p.originalSize,j=p.originalPosition,n=p.axis,l=h._aspectRatio||e.shiftKey;h.grid=typeof h.grid=="number"?[h.grid,h.grid]:h.grid;var g=Math.round((k.width-i.width)/(h.grid[0]||1))*(h.grid[0]||1),f=Math.round((k.height-i.height)/(h.grid[1]||1))*(h.grid[1]||1);if(/^(se|s|e)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f}else{if(/^(ne)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f}else{if(/^(sw)$/.test(n)){p.size.width=i.width+g;p.size.height=i.height+f;p.position.left=j.left-g}else{p.size.width=i.width+g;p.size.height=i.height+f;p.position.top=j.top-f;p.position.left=j.left-g}}}}});var b=function(e){return parseInt(e,10)||0};var a=function(e){return !isNaN(parseInt(e,10))}})(jQuery);/*! + * jQuery hashchange event - v1.3 - 7/21/2010 + * http://benalman.com/projects/jquery-hashchange-plugin/ + * + * Copyright (c) 2010 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ +(function($,e,b){var c="hashchange",h=document,f,g=$.event.special,i=h.documentMode,d="on"+c in e&&(i===b||i>7);function a(j){j=j||location.href;return"#"+j.replace(/^[^#]*#?(.*)$/,"$1")}$.fn[c]=function(j){return j?this.bind(c,j):this.trigger(c)};$.fn[c].delay=50;g[c]=$.extend(g[c],{setup:function(){if(d){return false}$(f.start)},teardown:function(){if(d){return false}$(f.stop)}});f=(function(){var j={},p,m=a(),k=function(q){return q},l=k,o=k;j.start=function(){p||n()};j.stop=function(){p&&clearTimeout(p);p=b};function n(){var r=a(),q=o(m);if(r!==m){l(m=r,q);$(e).trigger(c)}else{if(q!==m){location.href=location.href.replace(/#.*/,"")+q}}p=setTimeout(n,$.fn[c].delay)}$.browser.msie&&!d&&(function(){var q,r;j.start=function(){if(!q){r=$.fn[c].src;r=r&&r+a();q=$(' + + +
+
+
Command Reference
+
+
+
Here is a list of all modules:
+
+ + +
 AppendixThis chapter shows some usefull table
 PMTK CommandPMTK command is a MediaTek proprietary GNSS data transfer protocol
+ + + + + + + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/modules.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/modules.js" new file mode 100644 index 0000000..584fbf7 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/modules.js" @@ -0,0 +1,5 @@ +var modules = +[ + [ "Appendix", "group__pmtk__appendix.html", null ], + [ "PMTK Command", "group__pmtk__command.html", "group__pmtk__command" ] +]; \ No newline at end of file diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/nav_f.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/nav_f.png" new file mode 100644 index 0000000..72a58a5 Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/nav_f.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/nav_g.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/nav_g.png" new file mode 100644 index 0000000..2093a23 Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/nav_g.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/nav_h.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/nav_h.png" new file mode 100644 index 0000000..33389b1 Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/nav_h.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/navtree.css" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/navtree.css" new file mode 100644 index 0000000..1a868b3 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/navtree.css" @@ -0,0 +1,143 @@ +#nav-tree .children_ul { + margin:0; + padding:4px; +} + +#nav-tree ul { + list-style:none outside none; + margin:0px; + padding:0px; +} + +#nav-tree li { + white-space:nowrap; + margin:0px; + padding:0px; +} + +#nav-tree .plus { + margin:0px; +} + +#nav-tree .selected { + background-image: url('tab_a.png'); + background-repeat:repeat-x; + color: #fff; + text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); +} + +#nav-tree img { + margin:0px; + padding:0px; + border:0px; + vertical-align: middle; +} + +#nav-tree a { + text-decoration:none; + padding:0px; + margin:0px; + outline:none; +} + +#nav-tree .label { + margin:0px; + padding:0px; + font: 12px 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; +} + +#nav-tree .label a { + padding:2px; +} + +#nav-tree .selected a { + text-decoration:none; + color:#fff; +} + +#nav-tree .children_ul { + margin:0px; + padding:0px; +} + +#nav-tree .item { + margin:0px; + padding:0px; +} + +#nav-tree { + padding: 0px 0px; + background-color: #FAFAFF; + font-size:14px; + overflow:auto; +} + +#doc-content { + overflow:auto; + display:block; + padding:0px; + margin:0px; + -webkit-overflow-scrolling : touch; /* iOS 5+ */ +} + +#side-nav { + padding:0 6px 0 0; + margin: 0px; + display:block; + position: absolute; + left: 0px; + width: 250px; +} + +.ui-resizable .ui-resizable-handle { + display:block; +} + +.ui-resizable-e { + background:url("splitbar.png") repeat scroll right center transparent; + cursor:e-resize; + height:100%; + right:0; + top:0; + width:6px; +} + +.ui-resizable-handle { + display:none; + font-size:0.1px; + position:absolute; + z-index:1; +} + +#nav-tree-contents { + margin: 6px 0px 0px 0px; +} + +#nav-tree { + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + -webkit-overflow-scrolling : touch; /* iOS 5+ */ +} + +#nav-sync { + position:absolute; + top:5px; + right:24px; + z-index:0; +} + +#nav-sync img { + opacity:0.3; +} + +#nav-sync img:hover { + opacity:0.9; +} + +@media print +{ + #nav-tree { display: none; } + div.ui-resizable-handle { display: none; position: relative; } +} + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/navtree.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/navtree.js" new file mode 100644 index 0000000..9df45a7 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/navtree.js" @@ -0,0 +1,523 @@ +var navTreeSubIndices = new Array(); + +function getData(varName) +{ + var i = varName.lastIndexOf('/'); + var n = i>=0 ? varName.substring(i+1) : varName; + return eval(n.replace(/\-/g,'_')); +} + +function stripPath(uri) +{ + return uri.substring(uri.lastIndexOf('/')+1); +} + +function stripPath2(uri) +{ + var i = uri.lastIndexOf('/'); + var s = uri.substring(i+1); + var m = uri.substring(0,i+1).match(/\/d\w\/d\w\w\/$/); + return m ? uri.substring(i-6) : s; +} + +function hashValue() +{ + return $(location).attr('hash').substring(1).replace(/[^\w\-]/g,''); +} + +function hashUrl() +{ + return '#'+hashValue(); +} + +function pathName() +{ + return $(location).attr('pathname').replace(/[^-A-Za-z0-9+&@#/%?=~_|!:,.;\(\)]/g, ''); +} + +function localStorageSupported() +{ + try { + return 'localStorage' in window && window['localStorage'] !== null && window.localStorage.getItem; + } + catch(e) { + return false; + } +} + + +function storeLink(link) +{ + if (!$("#nav-sync").hasClass('sync') && localStorageSupported()) { + window.localStorage.setItem('navpath',link); + } +} + +function deleteLink() +{ + if (localStorageSupported()) { + window.localStorage.setItem('navpath',''); + } +} + +function cachedLink() +{ + if (localStorageSupported()) { + return window.localStorage.getItem('navpath'); + } else { + return ''; + } +} + +function getScript(scriptName,func,show) +{ + var head = document.getElementsByTagName("head")[0]; + var script = document.createElement('script'); + script.id = scriptName; + script.type = 'text/javascript'; + script.onload = func; + script.src = scriptName+'.js'; + if ($.browser.msie && $.browser.version<=8) { + // script.onload does not work with older versions of IE + script.onreadystatechange = function() { + if (script.readyState=='complete' || script.readyState=='loaded') { + func(); if (show) showRoot(); + } + } + } + head.appendChild(script); +} + +function createIndent(o,domNode,node,level) +{ + var level=-1; + var n = node; + while (n.parentNode) { level++; n=n.parentNode; } + if (node.childrenData) { + var imgNode = document.createElement("img"); + imgNode.style.paddingLeft=(16*level).toString()+'px'; + imgNode.width = 16; + imgNode.height = 22; + imgNode.border = 0; + node.plus_img = imgNode; + node.expandToggle = document.createElement("a"); + node.expandToggle.href = "javascript:void(0)"; + node.expandToggle.onclick = function() { + if (node.expanded) { + $(node.getChildrenUL()).slideUp("fast"); + node.plus_img.src = node.relpath+"arrowright.png"; + node.expanded = false; + } else { + expandNode(o, node, false, false); + } + } + node.expandToggle.appendChild(imgNode); + domNode.appendChild(node.expandToggle); + imgNode.src = node.relpath+"arrowright.png"; + } else { + var span = document.createElement("span"); + span.style.display = 'inline-block'; + span.style.width = 16*(level+1)+'px'; + span.style.height = '22px'; + span.innerHTML = ' '; + domNode.appendChild(span); + } +} + +var animationInProgress = false; + +function gotoAnchor(anchor,aname,updateLocation) +{ + var pos, docContent = $('#doc-content'); + var ancParent = $(anchor.parent()); + if (ancParent.hasClass('memItemLeft') || + ancParent.hasClass('fieldname') || + ancParent.hasClass('fieldtype') || + ancParent.is(':header')) + { + pos = ancParent.position().top; + } else if (anchor.position()) { + pos = anchor.position().top; + } + if (pos) { + var dist = Math.abs(Math.min( + pos-docContent.offset().top, + docContent[0].scrollHeight- + docContent.height()-docContent.scrollTop())); + animationInProgress=true; + docContent.animate({ + scrollTop: pos + docContent.scrollTop() - docContent.offset().top + },Math.max(50,Math.min(500,dist)),function(){ + if (updateLocation) window.location.href=aname; + animationInProgress=false; + }); + } +} + +function newNode(o, po, text, link, childrenData, lastNode) +{ + var node = new Object(); + node.children = Array(); + node.childrenData = childrenData; + node.depth = po.depth + 1; + node.relpath = po.relpath; + node.isLast = lastNode; + + node.li = document.createElement("li"); + po.getChildrenUL().appendChild(node.li); + node.parentNode = po; + + node.itemDiv = document.createElement("div"); + node.itemDiv.className = "item"; + + node.labelSpan = document.createElement("span"); + node.labelSpan.className = "label"; + + createIndent(o,node.itemDiv,node,0); + node.itemDiv.appendChild(node.labelSpan); + node.li.appendChild(node.itemDiv); + + var a = document.createElement("a"); + node.labelSpan.appendChild(a); + node.label = document.createTextNode(text); + node.expanded = false; + a.appendChild(node.label); + if (link) { + var url; + if (link.substring(0,1)=='^') { + url = link.substring(1); + link = url; + } else { + url = node.relpath+link; + } + a.className = stripPath(link.replace('#',':')); + if (link.indexOf('#')!=-1) { + var aname = '#'+link.split('#')[1]; + var srcPage = stripPath(pathName()); + var targetPage = stripPath(link.split('#')[0]); + a.href = srcPage!=targetPage ? url : "javascript:void(0)"; + a.onclick = function(){ + storeLink(link); + if (!$(a).parent().parent().hasClass('selected')) + { + $('.item').removeClass('selected'); + $('.item').removeAttr('id'); + $(a).parent().parent().addClass('selected'); + $(a).parent().parent().attr('id','selected'); + } + var anchor = $(aname); + gotoAnchor(anchor,aname,true); + }; + } else { + a.href = url; + a.onclick = function() { storeLink(link); } + } + } else { + if (childrenData != null) + { + a.className = "nolink"; + a.href = "javascript:void(0)"; + a.onclick = node.expandToggle.onclick; + } + } + + node.childrenUL = null; + node.getChildrenUL = function() { + if (!node.childrenUL) { + node.childrenUL = document.createElement("ul"); + node.childrenUL.className = "children_ul"; + node.childrenUL.style.display = "none"; + node.li.appendChild(node.childrenUL); + } + return node.childrenUL; + }; + + return node; +} + +function showRoot() +{ + var headerHeight = $("#top").height(); + var footerHeight = $("#nav-path").height(); + var windowHeight = $(window).height() - headerHeight - footerHeight; + (function (){ // retry until we can scroll to the selected item + try { + var navtree=$('#nav-tree'); + navtree.scrollTo('#selected',0,{offset:-windowHeight/2}); + } catch (err) { + setTimeout(arguments.callee, 0); + } + })(); +} + +function expandNode(o, node, imm, showRoot) +{ + if (node.childrenData && !node.expanded) { + if (typeof(node.childrenData)==='string') { + var varName = node.childrenData; + getScript(node.relpath+varName,function(){ + node.childrenData = getData(varName); + expandNode(o, node, imm, showRoot); + }, showRoot); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } if (imm || ($.browser.msie && $.browser.version>8)) { + // somehow slideDown jumps to the start of tree for IE9 :-( + $(node.getChildrenUL()).show(); + } else { + $(node.getChildrenUL()).slideDown("fast"); + } + if (node.isLast) { + node.plus_img.src = node.relpath+"arrowdown.png"; + } else { + node.plus_img.src = node.relpath+"arrowdown.png"; + } + node.expanded = true; + } + } +} + +function glowEffect(n,duration) +{ + n.addClass('glow').delay(duration).queue(function(next){ + $(this).removeClass('glow');next(); + }); +} + +function highlightAnchor() +{ + var aname = hashUrl(); + var anchor = $(aname); + if (anchor.parent().attr('class')=='memItemLeft'){ + var rows = $('.memberdecls tr[class$="'+hashValue()+'"]'); + glowEffect(rows.children(),300); // member without details + } else if (anchor.parent().attr('class')=='fieldname'){ + glowEffect(anchor.parent().parent(),1000); // enum value + } else if (anchor.parent().attr('class')=='fieldtype'){ + glowEffect(anchor.parent().parent(),1000); // struct field + } else if (anchor.parent().is(":header")) { + glowEffect(anchor.parent(),1000); // section header + } else { + glowEffect(anchor.next(),1000); // normal member + } + gotoAnchor(anchor,aname,false); +} + +function selectAndHighlight(hash,n) +{ + var a; + if (hash) { + var link=stripPath(pathName())+':'+hash.substring(1); + a=$('.item a[class$="'+link+'"]'); + } + if (a && a.length) { + a.parent().parent().addClass('selected'); + a.parent().parent().attr('id','selected'); + highlightAnchor(); + } else if (n) { + $(n.itemDiv).addClass('selected'); + $(n.itemDiv).attr('id','selected'); + } + if ($('#nav-tree-contents .item:first').hasClass('selected')) { + $('#nav-sync').css('top','30px'); + } else { + $('#nav-sync').css('top','5px'); + } + showRoot(); +} + +function showNode(o, node, index, hash) +{ + if (node && node.childrenData) { + if (typeof(node.childrenData)==='string') { + var varName = node.childrenData; + getScript(node.relpath+varName,function(){ + node.childrenData = getData(varName); + showNode(o,node,index,hash); + },true); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + $(node.getChildrenUL()).css({'display':'block'}); + node.plus_img.src = node.relpath+"arrowdown.png"; + node.expanded = true; + var n = node.children[o.breadcrumbs[index]]; + if (index+11) hash = '#'+parts[1].replace(/[^\w\-]/g,''); + else hash=''; + } + if (hash.match(/^#l\d+$/)) { + var anchor=$('a[name='+hash.substring(1)+']'); + glowEffect(anchor.parent(),1000); // line number + hash=''; // strip line number anchors + } + var url=root+hash; + var i=-1; + while (NAVTREEINDEX[i+1]<=url) i++; + if (i==-1) { i=0; root=NAVTREE[0][1]; } // fallback: show index + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath) + } else { + getScript(relpath+'navtreeindex'+i,function(){ + navTreeSubIndices[i] = eval('NAVTREEINDEX'+i); + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath); + } + },true); + } +} + +function showSyncOff(n,relpath) +{ + n.html(''); +} + +function showSyncOn(n,relpath) +{ + n.html(''); +} + +function toggleSyncButton(relpath) +{ + var navSync = $('#nav-sync'); + if (navSync.hasClass('sync')) { + navSync.removeClass('sync'); + showSyncOff(navSync,relpath); + storeLink(stripPath2(pathName())+hashUrl()); + } else { + navSync.addClass('sync'); + showSyncOn(navSync,relpath); + deleteLink(); + } +} + +function initNavTree(toroot,relpath) +{ + var o = new Object(); + o.toroot = toroot; + o.node = new Object(); + o.node.li = document.getElementById("nav-tree-contents"); + o.node.childrenData = NAVTREE; + o.node.children = new Array(); + o.node.childrenUL = document.createElement("ul"); + o.node.getChildrenUL = function() { return o.node.childrenUL; }; + o.node.li.appendChild(o.node.childrenUL); + o.node.depth = 0; + o.node.relpath = relpath; + o.node.expanded = false; + o.node.isLast = true; + o.node.plus_img = document.createElement("img"); + o.node.plus_img.src = relpath+"arrowright.png"; + o.node.plus_img.width = 16; + o.node.plus_img.height = 22; + + if (localStorageSupported()) { + var navSync = $('#nav-sync'); + if (cachedLink()) { + showSyncOff(navSync,relpath); + navSync.removeClass('sync'); + } else { + showSyncOn(navSync,relpath); + } + navSync.click(function(){ toggleSyncButton(relpath); }); + } + + $(window).load(function(){ + navTo(o,toroot,hashUrl(),relpath); + showRoot(); + }); + + $(window).bind('hashchange', function(){ + if (window.location.hash && window.location.hash.length>1){ + var a; + if ($(location).attr('hash')){ + var clslink=stripPath(pathName())+':'+hashValue(); + a=$('.item a[class$="'+clslink.replace(/=0) window.location.hash=url.substr(i); + var _preventDefault = function(evt) { evt.preventDefault(); }; + $("#splitbar").bind("dragstart", _preventDefault).bind("selectstart", _preventDefault); + $(document).bind('touchmove',function(e){ + var device = navigator.userAgent.toLowerCase(); + var ios = device.match(/(iphone|ipod|ipad)/); + if (ios) { + try { + var target = e.target; + while (target) { + if ($(target).css('-webkit-overflow-scrolling')=='touch') return; + target = target.parentNode; + } + e.preventDefault(); + } catch(err) { + e.preventDefault(); + } + } + }); +} + + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_0.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_0.html" new file mode 100644 index 0000000..d54e0bd --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_0.html" @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_0.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_0.js" new file mode 100644 index 0000000..f0101be --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_0.js" @@ -0,0 +1,4 @@ +var searchData= +[ + ['appendix',['Appendix',['../group__pmtk__appendix.html',1,'']]] +]; diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_1.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_1.html" new file mode 100644 index 0000000..8cc6a1d --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_1.html" @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_1.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_1.js" new file mode 100644 index 0000000..7cf7879 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_1.js" @@ -0,0 +1,4 @@ +var searchData= +[ + ['introduction',['Introduction',['../index.html',1,'']]] +]; diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_2.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_2.html" new file mode 100644 index 0000000..d15ac65 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_2.html" @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_2.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_2.js" new file mode 100644 index 0000000..be2d2c1 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/all_2.js" @@ -0,0 +1,106 @@ +var searchData= +[ + ['pmtk_5fack',['PMTK_ACK',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beabf86ac7cc7d3b0ce907b0a86e6a1338b',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fget_5fflash_5fdata',['PMTK_API_GET_FLASH_DATA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea063d8815c8ee51cd08acda80daa1e81e',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fget_5fgnss_5foperat_5fmode',['PMTK_API_GET_GNSS_OPERAT_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beace569382848d8559a16fa090e8d56100',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fget_5fhdop_5fthreshold',['PMTK_API_GET_HDOP_THRESHOLD',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead7e27c02b08d6ff4296f7a67a00dfe26',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fget_5fpos_5fxyz',['PMTK_API_GET_POS_XYZ',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab139be3d7b4b2482f2838bac51db2b39',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fget_5fvel_5fxyz',['PMTK_API_GET_VEL_XYZ',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea32f454682a68a9c3bccef8e25b15b8ba',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fdatum',['PMTK_API_Q_DATUM',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea94e91e0b1e6fa7207f32a1f49bdf5c94',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fdatum_5fadvance',['PMTK_API_Q_DATUM_ADVANCE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead2312b41c26e764ef34621c560f9973c',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fdgps_5fmode',['PMTK_API_Q_DGPS_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea55bd5f9f60b4113329eef6c1ad3ed296',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fdr_5flimit',['PMTK_API_Q_DR_LIMIT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1ce00a71b2d49bed618e16eaf551cd9a',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5felev_5fmask',['PMTK_API_Q_ELEV_MASK',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa99559cfe61a412f1e302dc39021b879',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5feph_5fstatus',['PMTK_API_Q_EPH_STATUS',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea349fe122413c42817cdd46f0888a6c5f',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5ffix_5fctl',['PMTK_API_Q_FIX_CTL',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8d1f075aa6a35cbca97ca5fb7ac07fa1',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fhacc_5fmask',['PMTK_API_Q_HACC_MASK',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8a11d9cb5cca390770b0f6b6ffc64b5a',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fhigh_5fsensitivity_5ftracking_5fno_5ffix',['PMTK_API_Q_HIGH_SENSITIVITY_TRACKING_NO_FIX',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab3eae09a18fc5417f8b359d9efdfd235',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fmin_5fsnr',['PMTK_API_Q_MIN_SNR',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea05ed0801721f44c80238d29c18bf9a02',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fnmea_5foutput',['PMTK_API_Q_NMEA_OUTPUT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa932726f1937dfdd7955fbee8819489a',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5frtc_5ftime',['PMTK_API_Q_RTC_TIME',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa84af36afd8dbaa82b104bbf0b263592',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fsbas_5fenabled',['PMTK_API_Q_SBAS_ENABLED',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaf1a7e2d71a17c147d1ef007986a29cfb',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fdatum',['PMTK_API_SET_DATUM',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea467817db20c8c590ea5c065e5faa1f53',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fdatum_5fadvance',['PMTK_API_SET_DATUM_ADVANCE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaff110d710ff9d5961dd33c7291e5824d',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fdgps_5fmode',['PMTK_API_SET_DGPS_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea83e665f81bc20f6d8e425e0749f3f288',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fdr_5flimit',['PMTK_API_SET_DR_LIMIT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8782a9c367032850565b8d449225ddda',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5felev_5fmask',['PMTK_API_SET_ELEV_MASK',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaeb41c59cd96e6d16e343046893ff7442',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fflash_5fdata',['PMTK_API_SET_FLASH_DATA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9b4d921b1fe8ac8f59195773a81a9aa3',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fgnss_5fsearch_5fmode',['PMTK_API_SET_GNSS_SEARCH_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea2edaf5cac4aa4a2fc73b5312d7428b24',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fhacc_5fmask',['PMTK_API_SET_HACC_MASK',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaafb3f64364e21510313190785e3fc7d0',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fhdop_5fthreshold',['PMTK_API_SET_HDOP_THRESHOLD',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea377b4ea82070d970dbfa11b6cf426594',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fhigh_5fsensitivity_5ftracking_5fno_5ffix',['PMTK_API_SET_HIGH_SENSITIVITY_TRACKING_NO_FIX',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea3fb309c02edc5daf43592d9f2959928e',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fmin_5fsnr',['PMTK_API_SET_MIN_SNR',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8060ce5da125915a4b00f7aff4220889',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fnmea_5foutput',['PMTK_API_SET_NMEA_OUTPUT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9b58e4f853bd537a8d44fe1021c57bb1',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fpll',['PMTK_API_SET_PLL',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9873165a5537dafa3b4c57dbea50d258',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fpps',['PMTK_API_SET_PPS',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beafab5347f328ae50a3b524cad27b2be8d',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fsbas_5fenabled',['PMTK_API_SET_SBAS_ENABLED',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea153232faf17c74620043aa97852fbf93',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fstatic_5fnavi_5fthd',['PMTK_API_SET_STATIC_NAVI_THD',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea144340c8d86359dce90bcdc73a1c3f47',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fstop_5fqzss',['PMTK_API_SET_STOP_QZSS',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa8d6e40f333aff7e4435f88809042ac8',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fsupport_5fqzss_5fnmea',['PMTK_API_SET_SUPPORT_QZSS_NMEA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8ddbdbf2649933cc970f831500dfe66f',1,'Mtk_Packet.h']]], + ['pmtk_5fcmd_5fclear_5fepo',['PMTK_CMD_CLEAR_EPO',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea7cff33d092ea4b69a868898082a9383d',1,'Mtk_Packet.h']]], + ['pmtk_5fcmd_5fcold_5fstart',['PMTK_CMD_COLD_START',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea815b92d27ea9a9adb14e4dbf2c6eb939',1,'Mtk_Packet.h']]], + ['pmtk_5fcmd_5ffull_5fcold_5fstart',['PMTK_CMD_FULL_COLD_START',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea48aff60bb41ea828e9ccaf810f3f47f9',1,'Mtk_Packet.h']]], + ['pmtk_5fcmd_5fhot_5fstart',['PMTK_CMD_HOT_START',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea3ace760b44e085e0142fef46f1837e0d',1,'Mtk_Packet.h']]], + ['pmtk_5fcmd_5fstandby_5fmode',['PMTK_CMD_STANDBY_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea466830c3723b4afc4ffaa5d389f528c3',1,'Mtk_Packet.h']]], + ['pmtk_5fcmd_5fwarm_5fstart',['PMTK_CMD_WARM_START',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea7bd230a1d411831e909a6bdeaec2f7eb',1,'Mtk_Packet.h']]], + ['pmtk_20command',['PMTK Command',['../group__pmtk__command.html',1,'']]], + ['pmtk_5fdt_5fdata_5fport',['PMTK_DT_DATA_PORT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae96a7db722c3fbaececd2c8d9a45b19c',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fdatum',['PMTK_DT_DATUM',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab85d515c5cb70af97c6afb7f15e225b2',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fdgps_5fmode',['PMTK_DT_DGPS_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea08e334f61a3facbee28df70210d878d3',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fepo_5finfo',['PMTK_DT_EPO_INFO',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea6b852645bdf9e0680bb45017559105e5',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5ffix_5fctl',['PMTK_DT_FIX_CTL',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9c0c1ca48067fdd105f70e04487ff701',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fflash_5fdata',['PMTK_DT_FLASH_DATA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae4a762e079462ab42723d0052ad9c5b4',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fhacc_5fmask',['PMTK_DT_HACC_MASK',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea807d8bf7605b87d790f4593f06dbb2f6',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fhigh_5fsensitivity_5ftracking_5fno_5ffix',['PMTK_DT_HIGH_SENSITIVITY_TRACKING_NO_FIX',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beabadd7524424255f446ccfd0a37b1df97',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fnmea_5foutput',['PMTK_DT_NMEA_OUTPUT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab2b4ec0b0540e9fc51bc8a839d44c8ff',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fpos',['PMTK_DT_POS',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea00bfa74b9ab4be1cb538d6720808c007',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5frelease',['PMTK_DT_RELEASE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beac6d9aff834a28ac4feddf34a66102a43',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5frtc_5ftime',['PMTK_DT_RTC_TIME',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea6732848b6864eda4c0bf2d6e665ebeb9',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fsbas_5fenabled',['PMTK_DT_SBAS_ENABLED',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae99971090e79d0b006294059e32301b0',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fsv_5fepo',['PMTK_DT_SV_EPO',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1397b023e0d48ec75adabef05a22e061',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5futc',['PMTK_DT_UTC',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1f021ebe90b969144edb422d2e41d62d',1,'Mtk_Packet.h']]], + ['pmtk_5feasy_5fenable',['PMTK_EASY_ENABLE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea2ac3e95cf254fb53202aa90270d17492',1,'Mtk_Packet.h']]], + ['pmtk_5ffr_5fmode',['PMTK_FR_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1552640a94f244c1a0c27e14bafdd426',1,'Mtk_Packet.h']]], + ['pmtk_5flocus_5fconfig',['PMTK_LOCUS_CONFIG',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea69756339c6d97ad458e3ccadc60e3059',1,'Mtk_Packet.h']]], + ['pmtk_5flocus_5ferase_5fflash',['PMTK_LOCUS_ERASE_FLASH',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea37e936f37aef1900a7e5a87fddbf8861',1,'Mtk_Packet.h']]], + ['pmtk_5flocus_5flog_5fnow',['PMTK_LOCUS_LOG_NOW',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab7a9a31d9329df65b587ae512e1e6a14',1,'Mtk_Packet.h']]], + ['pmtk_5flocus_5fquery_5fstatus',['PMTK_LOCUS_QUERY_STATUS',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaf8f88476f893e2e7445714372c99b6f3',1,'Mtk_Packet.h']]], + ['pmtk_5flocus_5fstop_5flogger',['PMTK_LOCUS_STOP_LOGGER',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaca811436d2d5072939d0f5cee493231c',1,'Mtk_Packet.h']]], + ['pmtk_5fpkt_5ftype_5ft',['PMTK_PKT_TYPE_T',['../group__pmtk__command.html#ga6012e5fa857099f0e5fd61bb6d1f84be',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5favailable_5fsv_5falm',['PMTK_Q_AVAILABLE_SV_ALM',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae8b254db5898fe8f36f6f650d81cb0d1',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5favailable_5fsv_5feph',['PMTK_Q_AVAILABLE_SV_EPH',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab0a80b268936db695d5a7ccff70e10bf',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5fbds_5fkep',['PMTK_Q_BDS_KEP',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea6dc3a9739c6f1928716ee2c97e28204b',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5fdata_5fport',['PMTK_Q_DATA_PORT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead90684782d20bd184adebce214da0fb7',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5fepo_5finfo',['PMTK_Q_EPO_INFO',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea3f53bb52d96bb7739b2c6cf17d05c268',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5fgps_5fiono',['PMTK_Q_GPS_IONO',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9c90d1ead04106ba8d52a532d9e0cb14',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5fgps_5fkep',['PMTK_Q_GPS_KEP',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea72e57a8d23a2f9d09d2c9685cb93d9c7',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5flocus_5fdata',['PMTK_Q_LOCUS_DATA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea2625b3468647086a44ea53b5e7b58288',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5frelease',['PMTK_Q_RELEASE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaf8a05f41e01df87665ca9237aa9f416e',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5futc_5fcorrection_5fdata',['PMTK_Q_UTC_CORRECTION_DATA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead7650c8cb304121491fdf61bc284c036',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5faic_5fcmd',['PMTK_SET_AIC_CMD',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beabbbb799ada6d27a16cb6a9e7fabcc0fd',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fal_5fdee_5fcfg',['PMTK_SET_AL_DEE_CFG',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea5d520ba1d9f1b61bcce90b521632c32d',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fdata_5fport',['PMTK_SET_DATA_PORT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9e91e2fdcbc35d2cb5e9c9fe9f564e98',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fglp_5fmode',['PMTK_SET_GLP_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa23a5c6e8e35b989498e6b6b101731e7',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fhigh_5faccuracy',['PMTK_SET_HIGH_ACCURACY',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea56cefa0d6551ed89dc1974929c35a875',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fnmea_5fbaudrate',['PMTK_SET_NMEA_BAUDRATE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1c16678ddc76189e4215f65893655821',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fnmea_5fdecimal_5fprecision',['PMTK_SET_NMEA_DECIMAL_PRECISION',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9e2fbd7c984e5e6e082b3825b060ca00',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5foutput_5fdebug',['PMTK_SET_OUTPUT_DEBUG',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8371d87a4fab64e97e5a53200fa6cda2',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5foutput_5ffmt',['PMTK_SET_OUTPUT_FMT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beac94b5ff1087757868d8afeff20c011fa',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fperiodic_5fmode',['PMTK_SET_PERIODIC_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8789b7bc5c5abad0ab627ad50aba79d4',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fpos_5ffix',['PMTK_SET_POS_FIX',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaf38eaf459a6e12d9579a52ea433d2b3b',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fpps_5fconfig_5fcmd',['PMTK_SET_PPS_CONFIG_CMD',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea2855fd322f2e27500a2844b7776c1061',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fsync_5fpps_5fnmea',['PMTK_SET_SYNC_PPS_NMEA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaec48bc94e3f15bdf3f9eda6d76fbd7ab',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5ftiming_5fproduct',['PMTK_SET_TIMING_PRODUCT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1265f33d4aba1384f11ef5872119f573',1,'Mtk_Packet.h']]], + ['pmtk_5fsys_5fmsg',['PMTK_SYS_MSG',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa957fa7398464443cff5412f35fd0611',1,'Mtk_Packet.h']]], + ['pmtk_5ftest',['PMTK_TEST',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea684eb8a711e4201f6de6aa5067100f21',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fall',['PMTK_TEST_ALL',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea19e1adb3e180af8c09c84c63ae9e789f',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fall_5facq',['PMTK_TEST_ALL_ACQ',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae2dbe959ff5bc2dcd3dc71a92d5c053c',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fall_5fbitsync',['PMTK_TEST_ALL_BITSYNC',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa93754c9b38d52d93c691c0ab53a7b7d',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fall_5fsignal',['PMTK_TEST_ALL_SIGNAL',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead90d6c9f7c3e751fd1cab1b92187bfb0',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5ffinish',['PMTK_TEST_FINISH',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea037ee569708e29066d04d6b24a589998',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fjamming',['PMTK_TEST_JAMMING',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea86e6074288800bb3626e16e735dcc6f8',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fjamming_5fdetection',['PMTK_TEST_JAMMING_DETECTION',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea42011586fa1fca5a3643cac6b05b60c0',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fstop',['PMTK_TEST_STOP',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea7bc54655b91905cd5de5770adef0b58e',1,'Mtk_Packet.h']]], + ['pmtk_5ftxt_5fmsg',['PMTK_TXT_MSG',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea3c5bcc16f2cb139831b0c05d7e77d4d3',1,'Mtk_Packet.h']]], + ['ptmk_5fpmtklsc_5fstn_5foutput',['PTMK_PMTKLSC_STN_OUTPUT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beadd3af74a2c6d9ea8a5411dfdb51e93a4',1,'Mtk_Packet.h']]] +]; diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/close.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/close.png" new file mode 100644 index 0000000..9342d3d Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/close.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/enums_0.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/enums_0.html" new file mode 100644 index 0000000..aba8d79 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/enums_0.html" @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/enums_0.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/enums_0.js" new file mode 100644 index 0000000..c98e337 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/enums_0.js" @@ -0,0 +1,4 @@ +var searchData= +[ + ['pmtk_5fpkt_5ftype_5ft',['PMTK_PKT_TYPE_T',['../group__pmtk__command.html#ga6012e5fa857099f0e5fd61bb6d1f84be',1,'Mtk_Packet.h']]] +]; diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/enumvalues_0.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/enumvalues_0.html" new file mode 100644 index 0000000..83192d3 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/enumvalues_0.html" @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/enumvalues_0.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/enumvalues_0.js" new file mode 100644 index 0000000..2d0cea9 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/enumvalues_0.js" @@ -0,0 +1,104 @@ +var searchData= +[ + ['pmtk_5fack',['PMTK_ACK',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beabf86ac7cc7d3b0ce907b0a86e6a1338b',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fget_5fflash_5fdata',['PMTK_API_GET_FLASH_DATA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea063d8815c8ee51cd08acda80daa1e81e',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fget_5fgnss_5foperat_5fmode',['PMTK_API_GET_GNSS_OPERAT_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beace569382848d8559a16fa090e8d56100',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fget_5fhdop_5fthreshold',['PMTK_API_GET_HDOP_THRESHOLD',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead7e27c02b08d6ff4296f7a67a00dfe26',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fget_5fpos_5fxyz',['PMTK_API_GET_POS_XYZ',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab139be3d7b4b2482f2838bac51db2b39',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fget_5fvel_5fxyz',['PMTK_API_GET_VEL_XYZ',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea32f454682a68a9c3bccef8e25b15b8ba',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fdatum',['PMTK_API_Q_DATUM',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea94e91e0b1e6fa7207f32a1f49bdf5c94',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fdatum_5fadvance',['PMTK_API_Q_DATUM_ADVANCE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead2312b41c26e764ef34621c560f9973c',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fdgps_5fmode',['PMTK_API_Q_DGPS_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea55bd5f9f60b4113329eef6c1ad3ed296',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fdr_5flimit',['PMTK_API_Q_DR_LIMIT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1ce00a71b2d49bed618e16eaf551cd9a',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5felev_5fmask',['PMTK_API_Q_ELEV_MASK',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa99559cfe61a412f1e302dc39021b879',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5feph_5fstatus',['PMTK_API_Q_EPH_STATUS',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea349fe122413c42817cdd46f0888a6c5f',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5ffix_5fctl',['PMTK_API_Q_FIX_CTL',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8d1f075aa6a35cbca97ca5fb7ac07fa1',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fhacc_5fmask',['PMTK_API_Q_HACC_MASK',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8a11d9cb5cca390770b0f6b6ffc64b5a',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fhigh_5fsensitivity_5ftracking_5fno_5ffix',['PMTK_API_Q_HIGH_SENSITIVITY_TRACKING_NO_FIX',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab3eae09a18fc5417f8b359d9efdfd235',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fmin_5fsnr',['PMTK_API_Q_MIN_SNR',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea05ed0801721f44c80238d29c18bf9a02',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fnmea_5foutput',['PMTK_API_Q_NMEA_OUTPUT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa932726f1937dfdd7955fbee8819489a',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5frtc_5ftime',['PMTK_API_Q_RTC_TIME',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa84af36afd8dbaa82b104bbf0b263592',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fq_5fsbas_5fenabled',['PMTK_API_Q_SBAS_ENABLED',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaf1a7e2d71a17c147d1ef007986a29cfb',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fdatum',['PMTK_API_SET_DATUM',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea467817db20c8c590ea5c065e5faa1f53',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fdatum_5fadvance',['PMTK_API_SET_DATUM_ADVANCE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaff110d710ff9d5961dd33c7291e5824d',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fdgps_5fmode',['PMTK_API_SET_DGPS_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea83e665f81bc20f6d8e425e0749f3f288',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fdr_5flimit',['PMTK_API_SET_DR_LIMIT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8782a9c367032850565b8d449225ddda',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5felev_5fmask',['PMTK_API_SET_ELEV_MASK',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaeb41c59cd96e6d16e343046893ff7442',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fflash_5fdata',['PMTK_API_SET_FLASH_DATA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9b4d921b1fe8ac8f59195773a81a9aa3',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fgnss_5fsearch_5fmode',['PMTK_API_SET_GNSS_SEARCH_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea2edaf5cac4aa4a2fc73b5312d7428b24',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fhacc_5fmask',['PMTK_API_SET_HACC_MASK',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaafb3f64364e21510313190785e3fc7d0',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fhdop_5fthreshold',['PMTK_API_SET_HDOP_THRESHOLD',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea377b4ea82070d970dbfa11b6cf426594',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fhigh_5fsensitivity_5ftracking_5fno_5ffix',['PMTK_API_SET_HIGH_SENSITIVITY_TRACKING_NO_FIX',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea3fb309c02edc5daf43592d9f2959928e',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fmin_5fsnr',['PMTK_API_SET_MIN_SNR',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8060ce5da125915a4b00f7aff4220889',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fnmea_5foutput',['PMTK_API_SET_NMEA_OUTPUT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9b58e4f853bd537a8d44fe1021c57bb1',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fpll',['PMTK_API_SET_PLL',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9873165a5537dafa3b4c57dbea50d258',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fpps',['PMTK_API_SET_PPS',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beafab5347f328ae50a3b524cad27b2be8d',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fsbas_5fenabled',['PMTK_API_SET_SBAS_ENABLED',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea153232faf17c74620043aa97852fbf93',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fstatic_5fnavi_5fthd',['PMTK_API_SET_STATIC_NAVI_THD',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea144340c8d86359dce90bcdc73a1c3f47',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fstop_5fqzss',['PMTK_API_SET_STOP_QZSS',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa8d6e40f333aff7e4435f88809042ac8',1,'Mtk_Packet.h']]], + ['pmtk_5fapi_5fset_5fsupport_5fqzss_5fnmea',['PMTK_API_SET_SUPPORT_QZSS_NMEA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8ddbdbf2649933cc970f831500dfe66f',1,'Mtk_Packet.h']]], + ['pmtk_5fcmd_5fclear_5fepo',['PMTK_CMD_CLEAR_EPO',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea7cff33d092ea4b69a868898082a9383d',1,'Mtk_Packet.h']]], + ['pmtk_5fcmd_5fcold_5fstart',['PMTK_CMD_COLD_START',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea815b92d27ea9a9adb14e4dbf2c6eb939',1,'Mtk_Packet.h']]], + ['pmtk_5fcmd_5ffull_5fcold_5fstart',['PMTK_CMD_FULL_COLD_START',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea48aff60bb41ea828e9ccaf810f3f47f9',1,'Mtk_Packet.h']]], + ['pmtk_5fcmd_5fhot_5fstart',['PMTK_CMD_HOT_START',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea3ace760b44e085e0142fef46f1837e0d',1,'Mtk_Packet.h']]], + ['pmtk_5fcmd_5fstandby_5fmode',['PMTK_CMD_STANDBY_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea466830c3723b4afc4ffaa5d389f528c3',1,'Mtk_Packet.h']]], + ['pmtk_5fcmd_5fwarm_5fstart',['PMTK_CMD_WARM_START',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea7bd230a1d411831e909a6bdeaec2f7eb',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fdata_5fport',['PMTK_DT_DATA_PORT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae96a7db722c3fbaececd2c8d9a45b19c',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fdatum',['PMTK_DT_DATUM',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab85d515c5cb70af97c6afb7f15e225b2',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fdgps_5fmode',['PMTK_DT_DGPS_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea08e334f61a3facbee28df70210d878d3',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fepo_5finfo',['PMTK_DT_EPO_INFO',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea6b852645bdf9e0680bb45017559105e5',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5ffix_5fctl',['PMTK_DT_FIX_CTL',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9c0c1ca48067fdd105f70e04487ff701',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fflash_5fdata',['PMTK_DT_FLASH_DATA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae4a762e079462ab42723d0052ad9c5b4',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fhacc_5fmask',['PMTK_DT_HACC_MASK',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea807d8bf7605b87d790f4593f06dbb2f6',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fhigh_5fsensitivity_5ftracking_5fno_5ffix',['PMTK_DT_HIGH_SENSITIVITY_TRACKING_NO_FIX',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beabadd7524424255f446ccfd0a37b1df97',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fnmea_5foutput',['PMTK_DT_NMEA_OUTPUT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab2b4ec0b0540e9fc51bc8a839d44c8ff',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fpos',['PMTK_DT_POS',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea00bfa74b9ab4be1cb538d6720808c007',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5frelease',['PMTK_DT_RELEASE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beac6d9aff834a28ac4feddf34a66102a43',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5frtc_5ftime',['PMTK_DT_RTC_TIME',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea6732848b6864eda4c0bf2d6e665ebeb9',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fsbas_5fenabled',['PMTK_DT_SBAS_ENABLED',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae99971090e79d0b006294059e32301b0',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5fsv_5fepo',['PMTK_DT_SV_EPO',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1397b023e0d48ec75adabef05a22e061',1,'Mtk_Packet.h']]], + ['pmtk_5fdt_5futc',['PMTK_DT_UTC',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1f021ebe90b969144edb422d2e41d62d',1,'Mtk_Packet.h']]], + ['pmtk_5feasy_5fenable',['PMTK_EASY_ENABLE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea2ac3e95cf254fb53202aa90270d17492',1,'Mtk_Packet.h']]], + ['pmtk_5ffr_5fmode',['PMTK_FR_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1552640a94f244c1a0c27e14bafdd426',1,'Mtk_Packet.h']]], + ['pmtk_5flocus_5fconfig',['PMTK_LOCUS_CONFIG',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea69756339c6d97ad458e3ccadc60e3059',1,'Mtk_Packet.h']]], + ['pmtk_5flocus_5ferase_5fflash',['PMTK_LOCUS_ERASE_FLASH',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea37e936f37aef1900a7e5a87fddbf8861',1,'Mtk_Packet.h']]], + ['pmtk_5flocus_5flog_5fnow',['PMTK_LOCUS_LOG_NOW',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab7a9a31d9329df65b587ae512e1e6a14',1,'Mtk_Packet.h']]], + ['pmtk_5flocus_5fquery_5fstatus',['PMTK_LOCUS_QUERY_STATUS',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaf8f88476f893e2e7445714372c99b6f3',1,'Mtk_Packet.h']]], + ['pmtk_5flocus_5fstop_5flogger',['PMTK_LOCUS_STOP_LOGGER',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaca811436d2d5072939d0f5cee493231c',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5favailable_5fsv_5falm',['PMTK_Q_AVAILABLE_SV_ALM',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae8b254db5898fe8f36f6f650d81cb0d1',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5favailable_5fsv_5feph',['PMTK_Q_AVAILABLE_SV_EPH',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beab0a80b268936db695d5a7ccff70e10bf',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5fbds_5fkep',['PMTK_Q_BDS_KEP',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea6dc3a9739c6f1928716ee2c97e28204b',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5fdata_5fport',['PMTK_Q_DATA_PORT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead90684782d20bd184adebce214da0fb7',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5fepo_5finfo',['PMTK_Q_EPO_INFO',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea3f53bb52d96bb7739b2c6cf17d05c268',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5fgps_5fiono',['PMTK_Q_GPS_IONO',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9c90d1ead04106ba8d52a532d9e0cb14',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5fgps_5fkep',['PMTK_Q_GPS_KEP',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea72e57a8d23a2f9d09d2c9685cb93d9c7',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5flocus_5fdata',['PMTK_Q_LOCUS_DATA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea2625b3468647086a44ea53b5e7b58288',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5frelease',['PMTK_Q_RELEASE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaf8a05f41e01df87665ca9237aa9f416e',1,'Mtk_Packet.h']]], + ['pmtk_5fq_5futc_5fcorrection_5fdata',['PMTK_Q_UTC_CORRECTION_DATA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead7650c8cb304121491fdf61bc284c036',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5faic_5fcmd',['PMTK_SET_AIC_CMD',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beabbbb799ada6d27a16cb6a9e7fabcc0fd',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fal_5fdee_5fcfg',['PMTK_SET_AL_DEE_CFG',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea5d520ba1d9f1b61bcce90b521632c32d',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fdata_5fport',['PMTK_SET_DATA_PORT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9e91e2fdcbc35d2cb5e9c9fe9f564e98',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fglp_5fmode',['PMTK_SET_GLP_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa23a5c6e8e35b989498e6b6b101731e7',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fhigh_5faccuracy',['PMTK_SET_HIGH_ACCURACY',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea56cefa0d6551ed89dc1974929c35a875',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fnmea_5fbaudrate',['PMTK_SET_NMEA_BAUDRATE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1c16678ddc76189e4215f65893655821',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fnmea_5fdecimal_5fprecision',['PMTK_SET_NMEA_DECIMAL_PRECISION',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea9e2fbd7c984e5e6e082b3825b060ca00',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5foutput_5fdebug',['PMTK_SET_OUTPUT_DEBUG',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8371d87a4fab64e97e5a53200fa6cda2',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5foutput_5ffmt',['PMTK_SET_OUTPUT_FMT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beac94b5ff1087757868d8afeff20c011fa',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fperiodic_5fmode',['PMTK_SET_PERIODIC_MODE',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea8789b7bc5c5abad0ab627ad50aba79d4',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fpos_5ffix',['PMTK_SET_POS_FIX',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaf38eaf459a6e12d9579a52ea433d2b3b',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fpps_5fconfig_5fcmd',['PMTK_SET_PPS_CONFIG_CMD',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea2855fd322f2e27500a2844b7776c1061',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5fsync_5fpps_5fnmea',['PMTK_SET_SYNC_PPS_NMEA',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaec48bc94e3f15bdf3f9eda6d76fbd7ab',1,'Mtk_Packet.h']]], + ['pmtk_5fset_5ftiming_5fproduct',['PMTK_SET_TIMING_PRODUCT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea1265f33d4aba1384f11ef5872119f573',1,'Mtk_Packet.h']]], + ['pmtk_5fsys_5fmsg',['PMTK_SYS_MSG',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa957fa7398464443cff5412f35fd0611',1,'Mtk_Packet.h']]], + ['pmtk_5ftest',['PMTK_TEST',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea684eb8a711e4201f6de6aa5067100f21',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fall',['PMTK_TEST_ALL',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea19e1adb3e180af8c09c84c63ae9e789f',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fall_5facq',['PMTK_TEST_ALL_ACQ',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beae2dbe959ff5bc2dcd3dc71a92d5c053c',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fall_5fbitsync',['PMTK_TEST_ALL_BITSYNC',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beaa93754c9b38d52d93c691c0ab53a7b7d',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fall_5fsignal',['PMTK_TEST_ALL_SIGNAL',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bead90d6c9f7c3e751fd1cab1b92187bfb0',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5ffinish',['PMTK_TEST_FINISH',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea037ee569708e29066d04d6b24a589998',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fjamming',['PMTK_TEST_JAMMING',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea86e6074288800bb3626e16e735dcc6f8',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fjamming_5fdetection',['PMTK_TEST_JAMMING_DETECTION',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea42011586fa1fca5a3643cac6b05b60c0',1,'Mtk_Packet.h']]], + ['pmtk_5ftest_5fstop',['PMTK_TEST_STOP',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea7bc54655b91905cd5de5770adef0b58e',1,'Mtk_Packet.h']]], + ['pmtk_5ftxt_5fmsg',['PMTK_TXT_MSG',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84bea3c5bcc16f2cb139831b0c05d7e77d4d3',1,'Mtk_Packet.h']]], + ['ptmk_5fpmtklsc_5fstn_5foutput',['PTMK_PMTKLSC_STN_OUTPUT',['../group__pmtk__command.html#gga6012e5fa857099f0e5fd61bb6d1f84beadd3af74a2c6d9ea8a5411dfdb51e93a4',1,'Mtk_Packet.h']]] +]; diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/groups_0.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/groups_0.html" new file mode 100644 index 0000000..95cee43 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/groups_0.html" @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/groups_0.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/groups_0.js" new file mode 100644 index 0000000..f0101be --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/groups_0.js" @@ -0,0 +1,4 @@ +var searchData= +[ + ['appendix',['Appendix',['../group__pmtk__appendix.html',1,'']]] +]; diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/groups_1.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/groups_1.html" new file mode 100644 index 0000000..979ea3d --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/groups_1.html" @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/groups_1.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/groups_1.js" new file mode 100644 index 0000000..ab5bdac --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/groups_1.js" @@ -0,0 +1,4 @@ +var searchData= +[ + ['pmtk_20command',['PMTK Command',['../group__pmtk__command.html',1,'']]] +]; diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/mag_sel.png" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/mag_sel.png" new file mode 100644 index 0000000..81f6040 Binary files /dev/null and "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/mag_sel.png" differ diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/nomatches.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/nomatches.html" new file mode 100644 index 0000000..b1ded27 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/nomatches.html" @@ -0,0 +1,12 @@ + + + + + + + +
+
No Matches
+
+ + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/pages_0.html" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/pages_0.html" new file mode 100644 index 0000000..0db7267 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/pages_0.html" @@ -0,0 +1,26 @@ + + + + + + + + + +
+
Loading...
+
+ +
Searching...
+
No Matches
+ +
+ + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/pages_0.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/pages_0.js" new file mode 100644 index 0000000..7cf7879 --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/pages_0.js" @@ -0,0 +1,4 @@ +var searchData= +[ + ['introduction',['Introduction',['../index.html',1,'']]] +]; diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/search.css" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/search.css" new file mode 100644 index 0000000..4d7612f --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/search.css" @@ -0,0 +1,271 @@ +/*---------------- Search Box */ + +#FSearchBox { + float: left; +} + +#MSearchBox { + white-space : nowrap; + position: absolute; + float: none; + display: inline; + margin-top: 8px; + right: 0px; + width: 170px; + z-index: 102; + background-color: white; +} + +#MSearchBox .left +{ + display:block; + position:absolute; + left:10px; + width:20px; + height:19px; + background:url('search_l.png') no-repeat; + background-position:right; +} + +#MSearchSelect { + display:block; + position:absolute; + width:20px; + height:19px; +} + +.left #MSearchSelect { + left:4px; +} + +.right #MSearchSelect { + right:5px; +} + +#MSearchField { + display:block; + position:absolute; + height:19px; + background:url('search_m.png') repeat-x; + border:none; + width:111px; + margin-left:20px; + padding-left:4px; + color: #909090; + outline: none; + font: 9pt Arial, Verdana, sans-serif; +} + +#FSearchBox #MSearchField { + margin-left:15px; +} + +#MSearchBox .right { + display:block; + position:absolute; + right:10px; + top:0px; + width:20px; + height:19px; + background:url('search_r.png') no-repeat; + background-position:left; +} + +#MSearchClose { + display: none; + position: absolute; + top: 4px; + background : none; + border: none; + margin: 0px 4px 0px 0px; + padding: 0px 0px; + outline: none; +} + +.left #MSearchClose { + left: 6px; +} + +.right #MSearchClose { + right: 2px; +} + +.MSearchBoxActive #MSearchField { + color: #000000; +} + +/*---------------- Search filter selection */ + +#MSearchSelectWindow { + display: none; + position: absolute; + left: 0; top: 0; + border: 1px solid #90A5CE; + background-color: #F9FAFC; + z-index: 1; + padding-top: 4px; + padding-bottom: 4px; + -moz-border-radius: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +.SelectItem { + font: 8pt Arial, Verdana, sans-serif; + padding-left: 2px; + padding-right: 12px; + border: 0px; +} + +span.SelectionMark { + margin-right: 4px; + font-family: monospace; + outline-style: none; + text-decoration: none; +} + +a.SelectItem { + display: block; + outline-style: none; + color: #000000; + text-decoration: none; + padding-left: 6px; + padding-right: 12px; +} + +a.SelectItem:focus, +a.SelectItem:active { + color: #000000; + outline-style: none; + text-decoration: none; +} + +a.SelectItem:hover { + color: #FFFFFF; + background-color: #3D578C; + outline-style: none; + text-decoration: none; + cursor: pointer; + display: block; +} + +/*---------------- Search results window */ + +iframe#MSearchResults { + width: 60ex; + height: 15em; +} + +#MSearchResultsWindow { + display: none; + position: absolute; + left: 0; top: 0; + border: 1px solid #000; + background-color: #EEF1F7; +} + +/* ----------------------------------- */ + + +#SRIndex { + clear:both; + padding-bottom: 15px; +} + +.SREntry { + font-size: 10pt; + padding-left: 1ex; +} + +.SRPage .SREntry { + font-size: 8pt; + padding: 1px 5px; +} + +body.SRPage { + margin: 5px 2px; +} + +.SRChildren { + padding-left: 3ex; padding-bottom: .5em +} + +.SRPage .SRChildren { + display: none; +} + +.SRSymbol { + font-weight: bold; + color: #425E97; + font-family: Arial, Verdana, sans-serif; + text-decoration: none; + outline: none; +} + +a.SRScope { + display: block; + color: #425E97; + font-family: Arial, Verdana, sans-serif; + text-decoration: none; + outline: none; +} + +a.SRSymbol:focus, a.SRSymbol:active, +a.SRScope:focus, a.SRScope:active { + text-decoration: underline; +} + +span.SRScope { + padding-left: 4px; +} + +.SRPage .SRStatus { + padding: 2px 5px; + font-size: 8pt; + font-style: italic; +} + +.SRResult { + display: none; +} + +DIV.searchresults { + margin-left: 10px; + margin-right: 10px; +} + +/*---------------- External search page results */ + +.searchresult { + background-color: #F0F3F8; +} + +.pages b { + color: white; + padding: 5px 5px 3px 5px; + background-image: url("../tab_a.png"); + background-repeat: repeat-x; + text-shadow: 0 1px 1px #000000; +} + +.pages { + line-height: 17px; + margin-left: 4px; + text-decoration: none; +} + +.hl { + font-weight: bold; +} + +#searchresults { + margin-bottom: 20px; +} + +.searchpages { + margin-top: 10px; +} + diff --git "a/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/search.js" "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/search.js" new file mode 100644 index 0000000..dedce3b --- /dev/null +++ "b/doc/MTK GPS command\350\265\204\346\226\231/MT33xx_GNSS_PMTK_Users_Guide/search/search.js" @@ -0,0 +1,791 @@ +function convertToId(search) +{ + var result = ''; + for (i=0;i do a search + { + this.Search(); + } + } + + this.OnSearchSelectKey = function(evt) + { + var e = (evt) ? evt : window.event; // for IE + if (e.keyCode==40 && this.searchIndex0) // Up + { + this.searchIndex--; + this.OnSelectItem(this.searchIndex); + } + else if (e.keyCode==13 || e.keyCode==27) + { + this.OnSelectItem(this.searchIndex); + this.CloseSelectionWindow(); + this.DOMSearchField().focus(); + } + return false; + } + + // --------- Actions + + // Closes the results window. + this.CloseResultsWindow = function() + { + this.DOMPopupSearchResultsWindow().style.display = 'none'; + this.DOMSearchClose().style.display = 'none'; + this.Activate(false); + } + + this.CloseSelectionWindow = function() + { + this.DOMSearchSelectWindow().style.display = 'none'; + } + + // Performs a search. + this.Search = function() + { + this.keyTimeout = 0; + + // strip leading whitespace + var searchValue = this.DOMSearchField().value.replace(/^ +/, ""); + + var code = searchValue.toLowerCase().charCodeAt(0); + var idxChar = searchValue.substr(0, 1).toLowerCase(); + if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) // surrogate pair + { + idxChar = searchValue.substr(0, 2); + } + + var resultsPage; + var resultsPageWithSearch; + var hasResultsPage; + + var idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar); + if (idx!=-1) + { + var hexCode=idx.toString(16); + resultsPage = this.resultsPath + '/' + indexSectionNames[this.searchIndex] + '_' + hexCode + '.html'; + resultsPageWithSearch = resultsPage+'?'+escape(searchValue); + hasResultsPage = true; + } + else // nothing available for this search term + { + resultsPage = this.resultsPath + '/nomatches.html'; + resultsPageWithSearch = resultsPage; + hasResultsPage = false; + } + + window.frames.MSearchResults.location = resultsPageWithSearch; + var domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow(); + + if (domPopupSearchResultsWindow.style.display!='block') + { + var domSearchBox = this.DOMSearchBox(); + this.DOMSearchClose().style.display = 'inline'; + if (this.insideFrame) + { + var domPopupSearchResults = this.DOMPopupSearchResults(); + domPopupSearchResultsWindow.style.position = 'relative'; + domPopupSearchResultsWindow.style.display = 'block'; + var width = document.body.clientWidth - 8; // the -8 is for IE :-( + domPopupSearchResultsWindow.style.width = width + 'px'; + domPopupSearchResults.style.width = width + 'px'; + } + else + { + var domPopupSearchResults = this.DOMPopupSearchResults(); + var left = getXPos(domSearchBox) + 150; // domSearchBox.offsetWidth; + var top = getYPos(domSearchBox) + 20; // domSearchBox.offsetHeight + 1; + domPopupSearchResultsWindow.style.display = 'block'; + left -= domPopupSearchResults.offsetWidth; + domPopupSearchResultsWindow.style.top = top + 'px'; + domPopupSearchResultsWindow.style.left = left + 'px'; + } + } + + this.lastSearchValue = searchValue; + this.lastResultsPage = resultsPage; + } + + // -------- Activation Functions + + // Activates or deactivates the search panel, resetting things to + // their default values if necessary. + this.Activate = function(isActive) + { + if (isActive || // open it + this.DOMPopupSearchResultsWindow().style.display == 'block' + ) + { + this.DOMSearchBox().className = 'MSearchBoxActive'; + + var searchField = this.DOMSearchField(); + + if (searchField.value == this.searchLabel) // clear "Search" term upon entry + { + searchField.value = ''; + this.searchActive = true; + } + } + else if (!isActive) // directly remove the panel + { + this.DOMSearchBox().className = 'MSearchBoxInactive'; + this.DOMSearchField().value = this.searchLabel; + this.searchActive = false; + this.lastSearchValue = '' + this.lastResultsPage = ''; + } + } +} + +// ----------------------------------------------------------------------- + +// The class that handles everything on the search results page. +function SearchResults(name) +{ + // The number of matches from the last run of . + this.lastMatchCount = 0; + this.lastKey = 0; + this.repeatOn = false; + + // Toggles the visibility of the passed element ID. + this.FindChildElement = function(id) + { + var parentElement = document.getElementById(id); + var element = parentElement.firstChild; + + while (element && element!=parentElement) + { + if (element.nodeName == 'DIV' && element.className == 'SRChildren') + { + return element; + } + + if (element.nodeName == 'DIV' && element.hasChildNodes()) + { + element = element.firstChild; + } + else if (element.nextSibling) + { + element = element.nextSibling; + } + else + { + do + { + element = element.parentNode; + } + while (element && element!=parentElement && !element.nextSibling); + + if (element && element!=parentElement) + { + element = element.nextSibling; + } + } + } + } + + this.Toggle = function(id) + { + var element = this.FindChildElement(id); + if (element) + { + if (element.style.display == 'block') + { + element.style.display = 'none'; + } + else + { + element.style.display = 'block'; + } + } + } + + // Searches for the passed string. If there is no parameter, + // it takes it from the URL query. + // + // Always returns true, since other documents may try to call it + // and that may or may not be possible. + this.Search = function(search) + { + if (!search) // get search word from URL + { + search = window.location.search; + search = search.substring(1); // Remove the leading '?' + search = unescape(search); + } + + search = search.replace(/^ +/, ""); // strip leading spaces + search = search.replace(/ +$/, ""); // strip trailing spaces + search = search.toLowerCase(); + search = convertToId(search); + + var resultRows = document.getElementsByTagName("div"); + var matches = 0; + + var i = 0; + while (i < resultRows.length) + { + var row = resultRows.item(i); + if (row.className == "SRResult") + { + var rowMatchName = row.id.toLowerCase(); + rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_' + + if (search.length<=rowMatchName.length && + rowMatchName.substr(0, search.length)==search) + { + row.style.display = 'block'; + matches++; + } + else + { + row.style.display = 'none'; + } + } + i++; + } + document.getElementById("Searching").style.display='none'; + if (matches == 0) // no results + { + document.getElementById("NoMatches").style.display='block'; + } + else // at least one result + { + document.getElementById("NoMatches").style.display='none'; + } + this.lastMatchCount = matches; + return true; + } + + // return the first item with index index or higher that is visible + this.NavNext = function(index) + { + var focusItem; + while (1) + { + var focusName = 'Item'+index; + focusItem = document.getElementById(focusName); + if (focusItem && focusItem.parentNode.parentNode.style.display=='block') + { + break; + } + else if (!focusItem) // last element + { + break; + } + focusItem=null; + index++; + } + return focusItem; + } + + this.NavPrev = function(index) + { + var focusItem; + while (1) + { + var focusName = 'Item'+index; + focusItem = document.getElementById(focusName); + if (focusItem && focusItem.parentNode.parentNode.style.display=='block') + { + break; + } + else if (!focusItem) // last element + { + break; + } + focusItem=null; + index--; + } + return focusItem; + } + + this.ProcessKeys = function(e) + { + if (e.type == "keydown") + { + this.repeatOn = false; + this.lastKey = e.keyCode; + } + else if (e.type == "keypress") + { + if (!this.repeatOn) + { + if (this.lastKey) this.repeatOn = true; + return false; // ignore first keypress after keydown + } + } + else if (e.type == "keyup") + { + this.lastKey = 0; + this.repeatOn = false; + } + return this.lastKey!=0; + } + + this.Nav = function(evt,itemIndex) + { + var e = (evt) ? evt : window.event; // for IE + if (e.keyCode==13) return true; + if (!this.ProcessKeys(e)) return false; + + if (this.lastKey==38) // Up + { + var newIndex = itemIndex-1; + var focusItem = this.NavPrev(newIndex); + if (focusItem) + { + var child = this.FindChildElement(focusItem.parentNode.parentNode.id); + if (child && child.style.display == 'block') // children visible + { + var n=0; + var tmpElem; + while (1) // search for last child + { + tmpElem = document.getElementById('Item'+newIndex+'_c'+n); + if (tmpElem) + { + focusItem = tmpElem; + } + else // found it! + { + break; + } + n++; + } + } + } + if (focusItem) + { + focusItem.focus(); + } + else // return focus to search field + { + parent.document.getElementById("MSearchField").focus(); + } + } + else if (this.lastKey==40) // Down + { + var newIndex = itemIndex+1; + var focusItem; + var item = document.getElementById('Item'+itemIndex); + var elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem && elem.style.display == 'block') // children visible + { + focusItem = document.getElementById('Item'+itemIndex+'_c0'); + } + if (!focusItem) focusItem = this.NavNext(newIndex); + if (focusItem) focusItem.focus(); + } + else if (this.lastKey==39) // Right + { + var item = document.getElementById('Item'+itemIndex); + var elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem) elem.style.display = 'block'; + } + else if (this.lastKey==37) // Left + { + var item = document.getElementById('Item'+itemIndex); + var elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem) elem.style.display = 'none'; + } + else if (this.lastKey==27) // Escape + { + parent.searchBox.CloseResultsWindow(); + parent.document.getElementById("MSearchField").focus(); + } + else if (this.lastKey==13) // Enter + { + return true; + } + return false; + } + + this.NavChild = function(evt,itemIndex,childIndex) + { + var e = (evt) ? evt : window.event; // for IE + if (e.keyCode==13) return true; + if (!this.ProcessKeys(e)) return false; + + if (this.lastKey==38) // Up + { + if (childIndex>0) + { + var newIndex = childIndex-1; + document.getElementById('Item'+itemIndex+'_c'+newIndex).focus(); + } + else // already at first child, jump to parent + { + document.getElementById('Item'+itemIndex).focus(); + } + } + else if (this.lastKey==40) // Down + { + var newIndex = childIndex+1; + var elem = document.getElementById('Item'+itemIndex+'_c'+newIndex); + if (!elem) // last child, jump to parent next parent + { + elem = this.NavNext(itemIndex+1); + } + if (elem) + { + elem.focus(); + } + } + else if (this.lastKey==27) // Escape + { + parent.searchBox.CloseResultsWindow(); + parent.document.getElementById("MSearchField").focus(); + } + else if (this.lastKey==13) // Enter + { + return true; + } + return false; + } +} + +function setKeyActions(elem,action) +{ + elem.setAttribute('onkeydown',action); + elem.setAttribute('onkeypress',action); + elem.setAttribute('onkeyup',action); +} + +function setClassAttr(elem,attr) +{ + elem.setAttribute('class',attr); + elem.setAttribute('className',attr); +} + +function createResults() +{ + var results = document.getElementById("SRResults"); + for (var e=0; e +#include +#include +#include +#include +#include +#include + +#define CAS_AGPS_SERVER "www.gnss-aide.com" +#define CAS_AGPS_PORT 2621 +#define USER_NAME "freetrial" +#define PASS_WORD "123456" +#define LAT 30.11 +#define LON 120.21 + +int main(int argc, char **argv) +{ + printf("AGPS demo.\n"); + int sockfd, n, counter; + int portno = CAS_AGPS_PORT; + struct sockaddr_in serv_addr; + struct hostent *server; + char message[128]; + int agps_buffer_length; + char agps_buffer[8 * 1024]; + char buffer[1024]; + char *p; + + printf("Create a socket.\n"); + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0){ + printf("ERROR, opening socket.\n"); + return 0; + } + + printf("Get agps server by name.\n"); + server = gethostbyname(CAS_AGPS_SERVER); + if (server == NULL){ + printf("ERROR, no such host.\n"); + return 0; + } + + printf("Copy agps server information to socket address struct\n"); + memset((char *) &serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + memcpy((char *) &serv_addr.sin_addr.s_addr, + (char *) server->h_addr, + server->h_length); + serv_addr.sin_port = htons(portno); + + printf("Connect to agps server.\n"); + if (connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { + printf("ERROR, cannot connect to server.\n"); + return 0; + } + + printf("Build agps message.\n"); + sprintf(message, "user=%s;pwd=%s;lat=%.1f;lon=%.1f;", USER_NAME, PASS_WORD, LAT, LON); + printf("Message: %s\n", message); + + printf("Send message to agps server.\n"); + n = write(sockfd, message, strlen(message)); + if (n < 0) { + printf("ERROR, writing to socket.\n"); + return 0; + } + + printf("Wait for server transferring agps data.\n"); + p = agps_buffer; + agps_buffer_length = 0; + for (counter = 0; counter < 100; counter++) { + n = read(sockfd, buffer, 1024); + if (n < 0) { + printf("ERROR, reading from socket.\n"); + return 0; + } + else if (n == 0 ) { + printf("All agps data are received.\nTotal bytes: %d\n", agps_buffer_length); + break; + } + else { + //~ printf("\nLength: %d\n\n%s", n, buffer); + printf("Received %d bytes from agps server.\n", n); + memcpy(p, buffer, n); + p += n; + agps_buffer_length += n; + } + } + + close(sockfd); + + // The code below is for DEBUG purpose + if (0) { + printf("Demostrate agps_buffer, agps_buffer_length = %d.\n\n", agps_buffer_length); + int row = 0; + int col = 0; + for (counter = 0; counter < agps_buffer_length; counter++) { + unsigned char c = agps_buffer[counter]; + + if (row < 3) { + printf("%c", c); + } + else { + printf("%02X ", c); + col += 1; + if (col >= 20) { + printf("\n"); + col = 0; + } + } + if (c == '\n') { + row += 1; + } + } + } + + printf("\n\n"); + printf("Now, you can send these data to gnss module through tty.\n"); + printf("Using code like:\nwrite(tty_fd, agps_buffer, agps_buffer_length);\n"); + + return 0; +} + diff --git "a/doc/\344\270\255\347\247\221\345\276\256AT6558/casicAgnssAidIni.c" "b/doc/\344\270\255\347\247\221\345\276\256AT6558/casicAgnssAidIni.c" new file mode 100644 index 0000000..daa8c9a --- /dev/null +++ "b/doc/\344\270\255\347\247\221\345\276\256AT6558/casicAgnssAidIni.c" @@ -0,0 +1,133 @@ +#include +#include +#include + +/************************************************************ +ƣisLeapYear +ܣжϡжϹһ򣬰겻İ +룺yearж +1, ꣬0꣨ƽ꣩ +************************************************************/ +int isLeapYear(int year) +{ + if ((year & 0x3) != 0) + { // year4ıһƽ + return 0; + } + else if ((year % 400) == 0) + { // year400ı + return 1; + } + else if ((year % 100) == 0) + { // year100ı + return 0; + } + else + { // year4ı + return 1; + } +} +/************************************************************************* +ƣ gregorian2SvTime +ܣ ʱʽת, ҪUTC + ʱʽdzʱʽʱ䣻 + תʱʽGPSʱʽʱʾGPSʱ1980.1.6 + GPSʱûʱ䣬ʱǾ + 2016ֵ17 +룺 pDateTime, ṹָ룬ʱʽʱ + pAidIni, ṹָ룬ʱʱʱʽ +*************************************************************************/ +void gregorian2SvTime(DATETIME_STR *pDateTime, AID_INI_STR *pAidIni) +{ + int DayMonthTable[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + int i, dn, wn; + double tod, tow; + + // ʱ + tod = pDateTime->hour * 3600 + pDateTime->minute * 60 + pDateTime->second + pDateTime->ms / 1000.0; + + // οʱ: 1980.1.6 + dn = pDateTime->day; + // -> + for (i = 1980; i < (pDateTime->year); i++) + { + if (isLeapYear(i)) + { + dn += 366; + } + else + { + dn += 365; + } + } + dn -= 6; + // -> + if (isLeapYear(pDateTime->year)) + { + DayMonthTable[1] = 29; + } + for (i = 1; i < pDateTime->month; i++) + { + dn += DayMonthTable[i-1]; + } + + // +ʱ + wn = (dn / 7); // + tow = (dn % 7) * 86400 + tod + 17; // ʱ䣬 + + if (tow >= 604800) + { + wn++; + tow -= 604800; + } + + pAidIni->wn = wn; + pAidIni->tow = tow; +} +/************************************************************************* +ƣcasicAgnssAidIni +ܣѸλú͸ʱרõݸʽϢʽ +룺dateTimeʱ䣬Ч־1Ч + lla, γȱ־Ч־1Ч +aidIniMsg[66]ַ飬Ϣݰȹ̶ +*************************************************************************/ +void casicAgnssAidIni(DATETIME_STR dateTime, POS_LLA_STR lla, char aidIniMsg[66]) +{ + AID_INI_STR aidIni; + int ckSum, i; + int *pDataBuff = (int*)&aidIni; + + gregorian2SvTime(&dateTime, &aidIni); + + aidIni.df = 0; + aidIni.xOrLat = lla.lat; + aidIni.yOrLon = lla.lon; + aidIni.zOrAlt = lla.alt; + aidIni.fAcc = 0; + aidIni.posAcc = 0; + aidIni.tAcc = 0; + aidIni.timeSource = 0; + + aidIni.flags = 0x20; // λøʽLLAʽ߶ЧƵʺλþȹЧ + aidIni.flags = aidIni.flags | ((lla.valid == 1) << 0); // BIT0λЧ־ + aidIni.flags = aidIni.flags | ((dateTime.valid == 1) << 1); // BIT1ʱЧ־ + + // ݴ + ckSum = 0x010B0038;//ֽڱڴĵ͵ַУСģʽ + for (i = 0; i < 14; i++) + { + ckSum += pDataBuff[i]; + } + + aidIniMsg[0] = 0xBA; + aidIniMsg[1] = 0xCE; + aidIniMsg[2] = 0x38; // LENGTH + aidIniMsg[3] = 0x00; + aidIniMsg[4] = 0x0B; // CLASS ID + aidIniMsg[5] = 0x01; // MESSAGE ID + + memcpy(&aidIniMsg[6], (char*)(&aidIni), 56); + memcpy(&aidIniMsg[62], (char*)(&ckSum), 4); + + return; +} \ No newline at end of file diff --git "a/doc/\344\270\255\347\247\221\345\276\256AT6558/casicAgnssAidIni.h" "b/doc/\344\270\255\347\247\221\345\276\256AT6558/casicAgnssAidIni.h" new file mode 100644 index 0000000..22cea10 --- /dev/null +++ "b/doc/\344\270\255\347\247\221\345\276\256AT6558/casicAgnssAidIni.h" @@ -0,0 +1,92 @@ +/************************************************************ +п΢޹˾ο̣ο +AGNSSʹòοԶʱھģӦã÷ԴοͻԼ޸Ĵ룡 + +1Ӧն˶ʱAGNSSݡֻݾͿԡ + +ӦնAGNSSݵݸʽʾ: +cmd=eph;user=xxxxx;pwd=xxxxxx;lat=47.28;lon=8.56;pacc=1000; +ģʽΪeph, AGNSSṩ, UTC͵Ϣ + +AGNSSлݰݳΪEPHݰݰЧ2Сʱ + +2ӦնͨGSMģ飨ͨţȡʱλ +ע⣺õʱUTCʱ䣬ʱҪȥ8Сʱ +һͨGSMģȡվCELL IDҪתΪγȺ;Ϣ + +رģӦն޷ȡȷUTCʱ䣬԰ʱ־ΪЧDATETIME_STRṹеvalidֶΣ +Ӧն޷ȡȷλãҲ԰λñ־ΪЧPOS_LLA_STRṹеvalidֶΣ + +ӦնԼijʼϢݰݳΪINIݰݰЧڣǰЧ + +3ηINIݰEPHݰ +INIݰÿģ飬عݰҷ͸ģ顣 +EPHݰʱAGNSSȡÿģ飬EPHݰ + +ע⣺Ϊ˸õܣȷINIݰ + +4ʱλóӰ챱ģĶλٶȡ +ȷĸϢܣ +ЧĸϢһܣ +ĸϢܣ + +5ʵ˹INIݰֻʵҪĹܣο +AID_INIʽοCASICЭֲᡣ + +*************************************************************/ + +#ifndef CASIC_AGNSS_AIDINI_H +#define CASIC_AGNSS_AIDINI_H + +// λýṹ +typedef struct +{ + double lat; // γȣʾγʾγ + double lon; // ȣʾʾ + double alt; // ߶ȣ߶޷ȡΪ0 + int valid; + +} POS_LLA_STR; + +// ʱṹ(ע⣺UTCʱ䣡뱱ʱ8СʱIJ࣬Ҫֱʹñʱ䣡) +// 籱ʱ2016.5.8,10:34:23ôUTCʱӦ2016.5.8,02:34:23 +// 籱ʱ2016.5.8,03:34:23ôUTCʱӦ2016.5.7,19:34:23 +typedef struct +{ + int valid; // ʱЧ־1=ЧЧ + int year; + int month; + int day; + int hour; + int minute; + int second; + float ms; + +} DATETIME_STR; + +// Ϣλãʱ䣬Ƶʣ +typedef struct +{ + double xOrLat, yOrLon, zOrAlt; + double tow; + float df; + float posAcc; + float tAcc; + float fAcc; + unsigned int res; + unsigned short int wn; + unsigned char timeSource; + unsigned char flags; + +} AID_INI_STR; + +/************************************************************************* +ƣcasicAgnssAidIni +ܣѸλú͸ʱרõݸʽϢʽ +룺dateTimeʱ䣬Ч־1Ч + lla, γȱ־Ч־1Ч +aidIniMsg[66]ַ飬Ϣݰȹ̶ +*************************************************************************/ +void casicAgnssAidIni(DATETIME_STR dateTime, POS_LLA_STR lla, char aidIniMsg[66]); + +#endif diff --git "a/doc/\344\270\255\347\247\221\345\276\256AT6558/main.cpp" "b/doc/\344\270\255\347\247\221\345\276\256AT6558/main.cpp" new file mode 100644 index 0000000..4a906a2 --- /dev/null +++ "b/doc/\344\270\255\347\247\221\345\276\256AT6558/main.cpp" @@ -0,0 +1,257 @@ +#include +#include +#include +#include +#include "casicAgnssAidIni.c" + +#define SERVER "www.gnss-aide.com" +#define PORT 2621 + +#define TTY_NAME "COM9" +#define BAUD_RATE 9600 + +#define AID_INI_LENGTH 66 +#define MAX_AGNSS_DATA 4096 +#define EXPIRED_SECONDS 3600 + +#define USERNAME "freetrial" +#define PASSWORD "123456" + +static char requestString[128]; +static int downloadTimestamp = 0; +static char agnssData[MAX_AGNSS_DATA]; +static int agnssDataSize = 0; +static char aidIniMsg[AID_INI_LENGTH]; + +static double roughLat = 30.5; +static double roughLon = 120.5; +static double roughAlt = 0; + +static int receiverPowerup = 1; + +int get_current_timestamp() { + return QDateTime::currentDateTimeUtc().toMSecsSinceEpoch() / 1000; +} + +int agnss_required() { + return receiverPowerup; +} + +int agnss_data_expired() { + int currentTimestamp = get_current_timestamp(); + if (abs(currentTimestamp - downloadTimestamp) >= EXPIRED_SECONDS) { + printf("AGNSS data is expired.\n"); + return 1; + } + else { + printf("AGNSS data is still valid.\n"); + return 0; + } +} + +int str_to_int(char *str, int size) { + int n = 0; + for (int i = 0; i < size; i++) { + char c = str[i]; + if (c >= '0' && c <= '9') { + n = 10 * n + c - '0'; + } + } + return n; +} + +int agnss_data_count_length(char *data, int size) { + int count = 0; + int flag = 0; + for (int i = 0; i < size; i++) { + if ((unsigned char)data[i] == 0xBA) { + flag = 1; + } + if (flag) { + count += 1; + } + } + return count; +} + +#define AGNSS_DATA_FIRST_LINE "AGNSS data from CASIC." +#define AGNSS_DATA_SECOND_LINE "DataLength: " +int agnss_data_check_length(char *data, int size) { + printf("Run AGNSS data length check.\n"); + int lineCounter = 0; + char line[64]; + memset(line, 0, sizeof(line)); + char *p = line; + int length = 0; + for (int i = 0; i < size; i++) { + *p = data[i]; + if (*p == '\n') { + printf("Current line: %s", line); + if (lineCounter == 0) { + if (memcmp(line, AGNSS_DATA_FIRST_LINE, strlen(AGNSS_DATA_FIRST_LINE))) { + printf("Error: wrong AGNSS data first line.\n"); + return 0; + } + printf("This is the first line!\n"); + } + else if (lineCounter == 1) { + if (memcmp(line, AGNSS_DATA_SECOND_LINE, strlen(AGNSS_DATA_SECOND_LINE))) { + printf("Error: wrong AGNSS data second line.\n"); + return 0; + } + printf("This is the second line!\n"); + + length = str_to_int(line, p - line); + printf("Raw agnss data length in data is: %d.\n", length); + break; + } + memset(line, 0, sizeof(line)); + p = line; + lineCounter += 1; + } + else { + p += 1; + } + if (p - line >= 64) { + printf("Error: line length out of range.\n"); + return 0; + } + } + + int countLength = agnss_data_count_length(data, size); + printf("Raw agnss data length by count is: %d.\n", countLength); + if (length != 0 && countLength == length) { + printf("AGNSS data length check PASSED.\n"); + return 1; + } + printf("AGNSS data length check FAILED.\n"); + return 0; +} + +int agnss_data_download() { + printf("Download AGNSS data from server.\n"); + QTcpSocket socket; + socket.setReadBufferSize(1024); + printf("Try connect to server...\n"); + socket.connectToHost(SERVER, PORT); + if (socket.waitForConnected()) { + printf("Connect to the host: %s:%d\n", SERVER, PORT); + + sprintf(requestString, "user=%s;pwd=%s;cmd=eph;", USERNAME, PASSWORD); + socket.write(requestString, strlen(requestString)); + socket.waitForBytesWritten(); + printf("Send request message: %s\n", requestString); + + char *p = agnssData; + while (socket.waitForReadyRead()) { + int size = qMin((int)socket.bytesAvailable(), (int)(MAX_AGNSS_DATA - (p - agnssData))); + int n = socket.read(p, size); + printf("Receive %d bytes from server.\n", n); + if (n > 0) { + p += n; + if ((p - agnssData) >= MAX_AGNSS_DATA) { + break; + } + } + } + agnssDataSize = p - agnssData; + if (agnssDataSize > 0) { + printf("Receive %d bytes agnss data TOTAL.\n", agnssDataSize); + printf("*********************\n"); + printf("%s", agnssData); + printf("\n"); + printf("*********************\n"); + + if (agnss_data_check_length(agnssData, agnssDataSize)) { + downloadTimestamp = get_current_timestamp(); + return 1; + } + } + else { + printf("Error: no data download from agnss server.\n"); + } + } + else { + printf("Error: can not connect to agnss server.\n"); + } + return 0; +} + +void get_current_datetime(DATETIME_STR *datetime) { + printf("Get current date time form system.\n"); + QDateTime dt = QDateTime::currentDateTimeUtc(); + // system utc time -> DATETIME_STR + datetime->valid = 1; + datetime->year = dt.date().year(); + datetime->month = dt.date().month(); + datetime->day = dt.date().day(); + datetime->hour = dt.time().hour(); + datetime->minute = dt.time().minute(); + datetime->second = dt.time().second(); + datetime->ms = 0; +} + +void get_rough_lla(POS_LLA_STR *lla) { + printf("Get rough LLA from cell id or bluetooth or wifi...\n"); + lla->valid = 1; + lla->lon = roughLon; + lla->lat = roughLat; + lla->alt = roughAlt; +} + +void create_aid_ini_message(char *aidIniMsg) { + printf("Create AID INI message.\n"); + // create time and location message + + DATETIME_STR datetime; + get_current_datetime(&datetime); + + // create position struct + POS_LLA_STR lla; + get_rough_lla(&lla); + + casicAgnssAidIni(datetime, lla, aidIniMsg); +} + +void agnss_data_send() { + printf("Send agnss data to device.\n"); + QSerialPort serial; + serial.setPortName(TTY_NAME); + serial.setBaudRate(BAUD_RATE); + if (serial.open(QSerialPort::ReadWrite) ) { + printf("Open serial port: %s\n", TTY_NAME); + // create aid ini message + create_aid_ini_message(aidIniMsg); + // send aid ini message + serial.write(aidIniMsg, AID_INI_LENGTH); + serial.waitForBytesWritten(1000); + printf("Send AID INI message.\n"); + + // send eph message + serial.write(agnssData, agnssDataSize); + serial.waitForBytesWritten(3000); + printf("Send GPS EPH messages.\n"); + serial.close(); + } + else { + printf("Error: can not open serial port: %s.\n", TTY_NAME); + } +} + +int main(int argc, char *argv[]) +{ + QCoreApplication app(argc, argv); + printf("Hello AGNSS!\n"); + while (1) { + if (agnss_data_expired()) { + agnss_data_download(); + } + + if (agnss_required()) { + agnss_data_send(); + } + printf("Press any key to continue.\n"); + getchar(); + } + return app.exec(); +} diff --git "a/doc/\344\270\255\347\247\221\345\276\256AT6558/\344\270\255\347\247\221\345\276\256AGNSS\346\234\215\345\212\241\347\232\204\345\256\242\346\210\267\347\253\257\345\256\236\347\216\260\346\226\271\346\263\225.pdf" "b/doc/\344\270\255\347\247\221\345\276\256AT6558/\344\270\255\347\247\221\345\276\256AGNSS\346\234\215\345\212\241\347\232\204\345\256\242\346\210\267\347\253\257\345\256\236\347\216\260\346\226\271\346\263\225.pdf" new file mode 100644 index 0000000..4c6c726 Binary files /dev/null and "b/doc/\344\270\255\347\247\221\345\276\256AT6558/\344\270\255\347\247\221\345\276\256AGNSS\346\234\215\345\212\241\347\232\204\345\256\242\346\210\267\347\253\257\345\256\236\347\216\260\346\226\271\346\263\225.pdf" differ diff --git "a/doc/\344\270\255\347\247\221\345\276\256AT6558/\345\272\224\347\224\250\346\211\213\345\206\214\357\274\232AGNSS\345\274\200\345\217\221\345\217\202\350\200\203\346\226\271\346\241\210.docx" "b/doc/\344\270\255\347\247\221\345\276\256AT6558/\345\272\224\347\224\250\346\211\213\345\206\214\357\274\232AGNSS\345\274\200\345\217\221\345\217\202\350\200\203\346\226\271\346\241\210.docx" new file mode 100644 index 0000000..36a6cba Binary files /dev/null and "b/doc/\344\270\255\347\247\221\345\276\256AT6558/\345\272\224\347\224\250\346\211\213\345\206\214\357\274\232AGNSS\345\274\200\345\217\221\345\217\202\350\200\203\346\226\271\346\241\210.docx" differ diff --git "a/doc/\344\270\255\347\247\221\345\276\256AT6558/\346\235\255\345\267\236\344\270\255\347\247\221\345\276\256AGNSS\345\270\220\345\217\267\347\224\263\350\257\267\346\265\201\347\250\213_to\345\256\242\346\210\267.pdf" "b/doc/\344\270\255\347\247\221\345\276\256AT6558/\346\235\255\345\267\236\344\270\255\347\247\221\345\276\256AGNSS\345\270\220\345\217\267\347\224\263\350\257\267\346\265\201\347\250\213_to\345\256\242\346\210\267.pdf" new file mode 100644 index 0000000..2b7423b Binary files /dev/null and "b/doc/\344\270\255\347\247\221\345\276\256AT6558/\346\235\255\345\267\236\344\270\255\347\247\221\345\276\256AGNSS\345\270\220\345\217\267\347\224\263\350\257\267\346\265\201\347\250\213_to\345\256\242\346\210\267.pdf" differ diff --git "a/doc/\344\270\255\347\247\221\345\276\256GPS\350\257\255\345\217\245.txt" "b/doc/\344\270\255\347\247\221\345\276\256GPS\350\257\255\345\217\245.txt" new file mode 100644 index 0000000..2b8f7eb --- /dev/null +++ "b/doc/\344\270\255\347\247\221\345\276\256GPS\350\257\255\345\217\245.txt" @@ -0,0 +1,293 @@ +$GPTXT,01,01,02,MA=CASIC*27 +$GPTXT,01,01,02,IC=AT6558-5N-32-1C510800*48 +$GPTXT,01,01,02,SW=URANUS5,V5.1.0.0*1F +$GPTXT,01,01,02,TB=2018-04-18,10:28:16*40 +$GPTXT,01,01,02,MO=GB*77 +$GNGGA,080452.042,,,,,0,00,25.5,,,,,,*77 +$GNGLL,,,,,080452.042,V,M*6A +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,1*01 +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 +$GPGSV,3,1,10,01,29,175,,07,43,325,,08,66,357,,09,35,255,,0*6F +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,,23,32,214,,0*66 +$GPGSV,3,3,10,26,08,084,,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080452.042,V,,,,,,,190319,,,M,V*24 +$GNVTG,,,,,,,,,M*2D +$GNZDA,080452.042,19,03,2019,00,00*44 +何\0 \0\0何\0\0\0\0 \0何\0\0\0\0 \0$GNGGA,080453.042,,,,,0,00,25.5,,,,,,*76 +$GNGLL,,,,,080453.042,V,M*6B +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,1*01 +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 +$GPGSV,3,1,10,01,29,175,,07,43,325,,08,66,357,,09,35,255,,0*6F +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,,23,32,214,,0*66 +$GPGSV,3,3,10,26,08,084,,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080453.042,V,,,,,,,190319,,,M,V*25 +$GNVTG,,,,,,,,,M*2D +$GNZDA,080453.042,19,03,2019,00,00*45 +$GPTXT,01,01,01,ANTENNA OPEN*25 +何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0$GNGGA,080454.042,,,,,0,00,25.5,,,,,,*71 +$GNGLL,,,,,080454.042,V,M*6C +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,1*01 +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 +$GPGSV,3,1,10,01,29,175,,07,43,325,37,08,66,357,28,09,35,255,,0*61 +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,,23,32,214,31,0*64 +$GPGSV,3,3,10,26,08,084,,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080454.042,V,,,,,,,190319,,,M,V*22 +$GNVTG,,,,,,,,,M*2D +$GNZDA,080454.042,19,03,2019,00,00*42 +$GPTXT,01,01,01,ANTENNA OPEN*25 +何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0何\0\0\0\0 \0$GNGGA,080455.042,,,,,0,00,25.5,,,,,,*70 +$GNGLL,,,,,080455.042,V,M*6D +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,1*01 +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 +$GPGSV,3,1,10,01,29,175,,07,43,325,36,08,66,357,28,09,35,255,,0*60 +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,,23,32,214,31,0*64 +$GPGSV,3,3,10,26,08,084,,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080455.042,V,,,,,,,190319,,,M,V*23 +$GNVTG,,,,,,,,,M*2D +$GNZDA,080455.042,19,03,2019,00,00*43 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080456.042,,,,,0,00,25.5,,,,,,*73 +$GNGLL,,,,,080456.042,V,M*6E +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,1*01 +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 +$GPGSV,3,1,10,01,29,175,,07,43,325,36,08,66,357,28,09,35,255,,0*60 +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,,23,32,214,31,0*64 +$GPGSV,3,3,10,26,08,084,,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080456.042,V,,,,,,,190319,,,M,V*20 +$GNVTG,,,,,,,,,M*2D +$GNZDA,080456.042,19,03,2019,00,00*40 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080457.042,,,,,0,00,25.5,,,,,,*72 +$GNGLL,,,,,080457.042,V,M*6F +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,1*01 +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 +$GPGSV,3,1,10,01,29,175,,07,43,325,35,08,66,357,27,09,35,255,,0*6C +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,,23,32,214,31,0*64 +$GPGSV,3,3,10,26,08,084,,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080457.042,V,,,,,,,190319,,,M,V*21 +$GNVTG,,,,,,,,,M*2D +$GNZDA,080457.042,19,03,2019,00,00*41 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080458.042,,,,,0,00,25.5,,,,,,*7D +$GNGLL,,,,,080458.042,V,M*60 +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,1*01 +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 +$GPGSV,3,1,10,01,29,175,,07,43,325,31,08,66,357,27,09,35,255,,0*68 +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,,23,32,214,31,0*64 +$GPGSV,3,3,10,26,08,084,,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080458.042,V,,,,,,,190319,,,M,V*2E +$GNVTG,,,,,,,,,M*2D +$GNZDA,080458.042,19,03,2019,00,00*4E +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080459.042,,,,,0,00,25.5,,,,,,*7C +$GNGLL,,,,,080459.042,V,M*61 +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,1*01 +$GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 +$GPGSV,3,1,10,01,29,175,24,07,43,325,31,08,66,357,23,09,35,255,,0*6A +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,,23,32,214,27,0*63 +$GPGSV,3,3,10,26,08,084,25,27,37,030,,0*61 +$BDGSV,1,1,00,0*74 +$GNRMC,080459.042,V,,,,,,,190319,,,M,V*2F +$GNVTG,,,,,,,,,M*2D +$GNZDA,080459.042,19,03,2019,00,00*4F +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080500.001,2232.52086,N,11357.15590,E,6,06,1.3,3.1,M,-3.4,M,,*54 +$GNGLL,2232.52086,N,11357.15590,E,080500.001,A,E*4E +$GNGSA,A,3,01,07,08,18,23,26,,,,,,,2.5,1.3,2.1,1*35 +$GNGSA,A,3,,,,,,,,,,,,,2.5,1.3,2.1,4*32 +$GPGSV,3,1,10,01,29,175,21,07,43,325,31,08,66,357,23,09,35,255,,0*6F +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,23,23,31,214,27,0*61 +$GPGSV,3,3,10,26,08,084,25,27,37,030,,0*61 +$BDGSV,1,1,00,0*74 +$GNRMC,080500.001,A,2232.52086,N,11357.15590,E,0.93,0.00,190319,,,E,V*0A +$GNVTG,0.00,T,,M,0.93,N,1.72,K,E*29 +$GNZDA,080500.001,19,03,2019,00,00*45 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080501.002,2232.52086,N,11357.15565,E,1,06,1.3,3.0,M,-3.4,M,,*5A +$GNGLL,2232.52086,N,11357.15565,E,080501.002,A,A*42 +$GNGSA,A,3,01,07,08,18,23,26,,,,,,,2.5,1.3,2.1,1*35 +$GNGSA,A,3,,,,,,,,,,,,,2.5,1.3,2.1,4*32 +$GPGSV,3,1,10,01,29,175,21,07,43,325,31,08,66,357,23,09,35,255,,0*6F +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,20,23,31,214,27,0*62 +$GPGSV,3,3,10,26,08,084,23,27,37,030,,0*67 +$BDGSV,1,1,00,0*74 +$GNRMC,080501.002,A,2232.52086,N,11357.15565,E,0.58,0.00,190319,,,A,V*01 +$GNVTG,0.00,T,,M,0.58,N,1.07,K,A*28 +$GNZDA,080501.002,19,03,2019,00,00*47 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080502.000,2232.52078,N,11357.15534,E,1,06,1.3,2.9,M,-3.4,M,,*56 +$GNGLL,2232.52078,N,11357.15534,E,080502.000,A,A*46 +$GNGSA,A,3,01,07,08,18,23,26,,,,,,,2.5,1.3,2.1,1*35 +$GNGSA,A,3,,,,,,,,,,,,,2.5,1.3,2.1,4*32 +$GPGSV,3,1,10,01,29,175,21,07,43,325,32,08,66,357,23,09,35,255,,0*6C +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,20,23,31,214,25,0*60 +$GPGSV,3,3,10,26,08,084,23,27,37,030,,0*67 +$BDGSV,1,1,00,0*74 +$GNRMC,080502.000,A,2232.52078,N,11357.15534,E,0.88,0.00,190319,,,A,V*08 +$GNVTG,0.00,T,,M,0.88,N,1.63,K,A*27 +$GNZDA,080502.000,19,03,2019,00,00*46 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GPTXT,01,01,02,SW=URANUS5,V5.1.0.0*1F +$GNGGA,080503.000,2232.52053,N,11357.15493,E,1,06,1.3,2.7,M,-3.4,M,,*5C +$GNGLL,2232.52053,N,11357.15493,E,080503.000,A,A*42 +$GNGSA,A,3,01,07,08,18,23,26,,,,,,,2.5,1.3,2.1,1*35 +$GNGSA,A,3,,,,,,,,,,,,,2.5,1.3,2.1,4*32 +$GPGSV,3,1,10,01,29,175,21,07,43,325,32,08,66,357,23,09,35,255,,0*6C +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,20,23,31,214,25,0*60 +$GPGSV,3,3,10,26,08,084,23,27,37,030,,0*67 +$BDGSV,1,1,00,0*74 +$GNRMC,080503.000,A,2232.52053,N,11357.15493,E,0.85,0.00,190319,,,A,V*01 +$GNVTG,0.00,T,,M,0.85,N,1.58,K,A*22 +$GNZDA,080503.000,19,03,2019,00,00*47 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080504.000,2232.51894,N,11357.15388,E,1,06,1.3,5.6,M,-3.4,M,,*50 +$GNGLL,2232.51894,N,11357.15388,E,080504.000,A,A*48 +$GNGSA,A,3,01,07,08,18,23,26,,,,,,,2.4,1.3,2.1,1*34 +$GNGSA,A,3,,,,,,,,,,,,,2.4,1.3,2.1,4*33 +$GPGSV,3,1,10,01,29,175,21,07,43,325,32,08,66,357,23,09,35,255,,0*6C +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,20,23,31,214,25,0*60 +$GPGSV,3,3,10,26,08,084,23,27,37,030,,0*67 +$BDGSV,1,1,00,0*74 +$GNRMC,080504.000,A,2232.51894,N,11357.15388,E,0.83,0.00,190319,,,A,V*0D +$GNVTG,0.00,T,,M,0.83,N,1.54,K,A*28 +$GNZDA,080504.000,19,03,2019,00,00*40 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080505.000,2232.51849,N,11357.15356,E,1,06,1.3,5.7,M,-3.4,M,,*53 +$GNGLL,2232.51849,N,11357.15356,E,080505.000,A,A*4A +$GNGSA,A,3,01,07,08,18,23,26,,,,,,,2.4,1.3,2.1,1*34 +$GNGSA,A,3,,,,,,,,,,,,,2.4,1.3,2.1,4*33 +$GPGSV,3,1,10,01,29,175,21,07,43,325,32,08,66,357,23,09,35,255,,0*6C +$GPGSV,3,2,10,11,55,192,,16,25,061,,18,48,149,20,23,31,214,25,0*60 +$GPGSV,3,3,10,26,08,084,23,27,37,030,,0*67 +$BDGSV,1,1,00,0*74 +$GNRMC,080505.000,A,2232.51849,N,11357.15356,E,0.74,0.00,190319,,,A,V*07 +$GNVTG,0.00,T,,M,0.74,N,1.36,K,A*24 +$GNZDA,080505.000,19,03,2019,00,00*41 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080506.000,2232.51968,N,11357.15391,E,1,07,1.2,5.3,M,-3.4,M,,*5D +$GNGLL,2232.51968,N,11357.15391,E,080506.000,A,A*40 +$GNGSA,A,3,01,07,08,11,18,23,26,,,,,,2.3,1.2,1.9,1*39 +$GNGSA,A,3,,,,,,,,,,,,,2.3,1.2,1.9,4*3E +$GPGSV,3,1,10,01,29,175,17,07,43,325,32,08,66,357,23,09,35,255,,0*69 +$GPGSV,3,2,10,11,55,192,21,16,25,061,,18,48,149,20,23,31,214,25,0*63 +$GPGSV,3,3,10,26,08,084,23,27,37,030,,0*67 +$BDGSV,1,1,00,0*74 +$GNRMC,080506.000,A,2232.51968,N,11357.15391,E,0.63,0.00,190319,,,A,V*0B +$GNVTG,0.00,T,,M,0.63,N,1.16,K,A*20 +$GNZDA,080506.000,19,03,2019,00,00*42 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080507.000,2232.52008,N,11357.15379,E,1,07,1.2,4.5,M,-3.4,M,,*51 +$GNGLL,2232.52008,N,11357.15379,E,080507.000,A,A*4B +$GNGSA,A,3,01,07,08,11,18,23,26,,,,,,2.3,1.2,1.9,1*39 +$GNGSA,A,3,,,,,,,,,,,,,2.3,1.2,1.9,4*3E +$GPGSV,3,1,10,01,29,175,17,07,43,325,30,08,66,357,23,09,35,255,,0*6B +$GPGSV,3,2,10,11,55,192,21,16,25,061,,18,48,149,20,23,31,214,25,0*63 +$GPGSV,3,3,10,26,08,084,23,27,37,030,,0*67 +$BDGSV,1,1,00,0*74 +$GNRMC,080507.000,A,2232.52008,N,11357.15379,E,0.61,0.00,190319,,,A,V*02 +$GNVTG,0.00,T,,M,0.61,N,1.12,K,A*26 +$GNZDA,080507.000,19,03,2019,00,00*43 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080508.000,2232.52018,N,11357.15364,E,1,07,1.2,3.8,M,-3.4,M,,*59 +$GNGLL,2232.52018,N,11357.15364,E,080508.000,A,A*49 +$GNGSA,A,3,01,07,08,11,18,23,26,,,,,,2.3,1.2,1.9,1*39 +$GNGSA,A,3,,,,,,,,,,,,,2.3,1.2,1.9,4*3E +$GPGSV,3,1,10,01,29,175,17,07,43,325,30,08,66,357,23,09,35,255,,0*6B +$GPGSV,3,2,10,11,55,192,21,16,25,061,,18,48,149,20,23,31,214,25,0*63 +$GPGSV,3,3,10,26,08,084,22,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080508.000,A,2232.52018,N,11357.15364,E,0.61,0.00,190319,,,A,V*00 +$GNVTG,0.00,T,,M,0.61,N,1.12,K,A*26 +$GNZDA,080508.000,19,03,2019,00,00*4C +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080509.000,2232.52028,N,11357.15350,E,1,07,1.2,3.2,M,-3.4,M,,*56 +$GNGLL,2232.52028,N,11357.15350,E,080509.000,A,A*4C +$GNGSA,A,3,01,07,08,11,18,23,26,,,,,,2.3,1.2,1.9,1*39 +$GNGSA,A,3,,,,,,,,,,,,,2.3,1.2,1.9,4*3E +$GPGSV,3,1,10,01,29,175,17,07,43,325,30,08,66,357,23,09,35,255,,0*6B +$GPGSV,3,2,10,11,55,192,21,16,25,061,,18,48,149,20,23,31,214,26,0*60 +$GPGSV,3,3,10,26,08,084,22,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080509.000,A,2232.52028,N,11357.15350,E,0.61,0.00,190319,,,A,V*05 +$GNVTG,0.00,T,,M,0.61,N,1.12,K,A*26 +$GNZDA,080509.000,19,03,2019,00,00*4D +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080510.040,2232.52019,N,11357.15330,E,1,07,1.2,2.2,M,-3.4,M,,*5F +$GNGLL,2232.52019,N,11357.15330,E,080510.040,A,A*44 +$GNGSA,A,3,01,07,08,11,18,23,26,,,,,,2.3,1.2,1.9,1*39 +$GNGSA,A,3,,,,,,,,,,,,,2.3,1.2,1.9,4*3E +$GPGSV,3,1,10,01,29,175,17,07,43,325,30,08,66,357,23,09,35,255,,0*6B +$GPGSV,3,2,10,11,55,192,21,16,25,061,,18,48,149,20,23,31,214,29,0*6F +$GPGSV,3,3,10,26,08,084,22,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080510.040,A,2232.52019,N,11357.15330,E,0.69,0.00,190319,,,A,V*05 +$GNVTG,0.00,T,,M,0.69,N,1.27,K,A*28 +$GNZDA,080510.040,19,03,2019,00,00*41 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080511.000,2232.52058,N,11357.15334,E,1,07,1.2,1.8,M,-3.4,M,,*52 +$GNGLL,2232.52058,N,11357.15334,E,080511.000,A,A*40 +$GNGSA,A,3,01,07,08,11,18,23,26,,,,,,2.3,1.2,1.9,1*39 +$GNGSA,A,3,,,,,,,,,,,,,2.3,1.2,1.9,4*3E +$GPGSV,3,1,10,01,29,175,20,07,43,325,30,08,66,357,23,09,35,255,,0*6F +$GPGSV,3,2,10,11,55,192,21,16,25,061,,18,48,149,20,23,31,214,29,0*6F +$GPGSV,3,3,10,26,08,084,22,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080511.000,A,2232.52058,N,11357.15334,E,0.59,0.00,190319,,,A,V*02 +$GNVTG,0.00,T,,M,0.59,N,1.10,K,A*2F +$GNZDA,080511.000,19,03,2019,00,00*44 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080512.000,2232.52097,N,11357.15339,E,1,07,1.2,1.6,M,-3.4,M,,*51 +$GNGLL,2232.52097,N,11357.15339,E,080512.000,A,A*4D +$GNGSA,A,3,01,07,08,11,18,23,26,,,,,,2.3,1.2,1.9,1*39 +$GNGSA,A,3,,,,,,,,,,,,,2.3,1.2,1.9,4*3E +$GPGSV,3,1,10,01,29,175,20,07,43,325,30,08,66,357,26,09,35,254,,0*6B +$GPGSV,3,2,10,11,55,192,21,16,25,061,,18,48,149,19,23,31,214,29,0*65 +$GPGSV,3,3,10,26,08,084,22,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080512.000,A,2232.52097,N,11357.15339,E,0.49,0.00,190319,,,A,V*0E +$GNVTG,0.00,T,,M,0.49,N,0.91,K,A*26 +$GNZDA,080512.000,19,03,2019,00,00*47 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080513.000,2232.52155,N,11357.15371,E,1,07,1.2,1.5,M,-3.4,M,,*50 +$GNGLL,2232.52155,N,11357.15371,E,080513.000,A,A*4F +$GNGSA,A,3,01,07,08,11,18,23,26,,,,,,2.3,1.2,1.9,1*39 +$GNGSA,A,3,,,,,,,,,,,,,2.3,1.2,1.9,4*3E +$GPGSV,3,1,10,01,29,175,20,07,43,325,30,08,66,357,26,09,35,254,,0*6B +$GPGSV,3,2,10,11,55,192,21,16,25,061,,18,48,149,19,23,31,214,27,0*6B +$GPGSV,3,3,10,26,08,084,22,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080513.000,A,2232.52155,N,11357.15371,E,0.00,0.00,190319,,,A,V*01 +$GNVTG,0.00,T,,M,0.00,N,0.00,K,A*23 +$GNZDA,080513.000,19,03,2019,00,00*46 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080514.000,2232.52216,N,11357.15398,E,1,07,1.2,1.3,M,-3.4,M,,*52 +$GNGLL,2232.52216,N,11357.15398,E,080514.000,A,A*4B +$GNGSA,A,3,01,07,08,11,18,23,26,,,,,,2.3,1.2,1.9,1*39 +$GNGSA,A,3,,,,,,,,,,,,,2.3,1.2,1.9,4*3E +$GPGSV,3,1,10,01,29,175,20,07,43,325,31,08,66,357,28,09,35,254,,0*64 +$GPGSV,3,2,10,11,55,192,22,16,25,061,,18,48,149,19,23,31,214,27,0*68 +$GPGSV,3,3,10,26,08,084,22,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080514.000,A,2232.52216,N,11357.15398,E,0.00,0.00,190319,,,A,V*05 +$GNVTG,0.00,T,,M,0.00,N,0.00,K,A*23 +$GNZDA,080514.000,19,03,2019,00,00*41 +$GPTXT,01,01,01,ANTENNA OPEN*25 +$GNGGA,080515.000,2232.52321,N,11357.15413,E,1,07,1.2,0.8,M,-3.4,M,,*58 +$GNGLL,2232.52321,N,11357.15413,E,080515.000,A,A*4B +$GNGSA,A,3,01,07,08,11,18,23,26,,,,,,2.3,1.2,1.9,1*39 +$GNGSA,A,3,,,,,,,,,,,,,2.3,1.2,1.9,4*3E +$GPGSV,3,1,10,01,29,175,22,07,43,325,31,08,66,357,28,09,35,254,,0*66 +$GPGSV,3,2,10,11,55,192,22,16,25,061,,18,48,149,19,23,31,214,27,0*68 +$GPGSV,3,3,10,26,08,084,22,27,37,030,,0*66 +$BDGSV,1,1,00,0*74 +$GNRMC,080515.000,A,2232.52321,N,11357.15413,E,0.00,0.00,190319,,,A,V*05 +$GNVTG,0.00,T,,M,0.00,N,0.00,K,A*23 +$GNZDA,080515.000,19,03,2019,00,00*40 +$GPTXT,01,01,01,ANTENNA OPEN*25 diff --git "a/doc/\345\212\237\350\203\275\347\211\271\346\200\247\350\257\264\346\230\216.xlsx" "b/doc/\345\212\237\350\203\275\347\211\271\346\200\247\350\257\264\346\230\216.xlsx" new file mode 100644 index 0000000..a43ba9c Binary files /dev/null and "b/doc/\345\212\237\350\203\275\347\211\271\346\200\247\350\257\264\346\230\216.xlsx" differ diff --git "a/doc/\346\263\260\346\226\227GPS\350\257\255\345\217\245.txt" "b/doc/\346\263\260\346\226\227GPS\350\257\255\345\217\245.txt" new file mode 100644 index 0000000..ce2104c --- /dev/null +++ "b/doc/\346\263\260\346\226\227GPS\350\257\255\345\217\245.txt" @@ -0,0 +1,752 @@ +\0$TDINF,Techtotop Multi-GNSS Receiver*63 +$TDINF,T3,RomFw,1.1(48),Aug 12 2016 16:57:35*02 +$TDINF,GNSS=BDS+GPS,ANT=Disable*6D +$GNRMC,,V,,,,,,,,,,N,V*37 +$GNGGA,,,,,,0,00,99.9,,,,,,*6F +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,1,1,00,0*65 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,,V,,,,,,,,,,N,V*37 +$GNGGA,,,,,,0,00,99.9,,,,,,*6F +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,1,1,00,0*65 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,,V,,,,,,,,,,N,V*37 +$GNGGA,,,,,,0,00,99.9,,,,,,*6F +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,1,1,00,0*65 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +#>\0 $GNRMC,,V,,,,,,,,,,N,V*37 +$GNGGA,,,,,,0,00,99.9,,,,,,*6F +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,1,1,00,0*65 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +#>\0 +#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<$GNRMC,081236.00,V,,,,,,,190319,,,N,V*14 +$GNGGA,081236.00,,,,,0,00,99.9,,,,,,*4F +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,001,,0*6B +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<$GNRMC,081237.00,V,,,,,,,190319,,,N,V*15 +$GNGGA,081237.00,,,,,0,00,99.9,,,,,,*4E +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,001,,0*6B +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<$GNRMC,081238.00,V,,,,,,,190319,,,N,V*1A +$GNGGA,081238.00,,,,,0,00,99.9,,,,,,*41 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,001,,0*6B +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<#>\0!)<$GNRMC,081239.00,V,,,,,,,190319,,,N,V*1B +$GNGGA,081239.00,,,,,0,00,99.9,,,,,,*40 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081240.00,V,,,,,,,190319,,,N,V*15 +$GNGGA,081240.00,,,,,0,00,99.9,,,,,,*4E +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081241.00,V,,,,,,,190319,,,N,V*14 +$GNGGA,081241.00,,,,,0,00,99.9,,,,,,*4F +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081242.00,V,,,,,,,190319,,,N,V*17 +$GNGGA,081242.00,,,,,0,00,99.9,,,,,,*4C +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081243.00,V,,,,,,,190319,,,N,V*16 +$GNGGA,081243.00,,,,,0,00,99.9,,,,,,*4D +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081244.00,V,,,,,,,190319,,,N,V*11 +$GNGGA,081244.00,,,,,0,00,99.9,,,,,,*4A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081245.00,V,,,,,,,190319,,,N,V*10 +$GNGGA,081245.00,,,,,0,00,99.9,,,,,,*4B +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081246.00,V,,,,,,,190319,,,N,V*13 +$GNGGA,081246.00,,,,,0,00,99.9,,,,,,*48 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081247.00,V,,,,,,,190319,,,N,V*12 +$GNGGA,081247.00,,,,,0,00,99.9,,,,,,*49 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081248.00,V,,,,,,,190319,,,N,V*1D +$GNGGA,081248.00,,,,,0,00,99.9,,,,,,*46 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081249.00,V,,,,,,,190319,,,N,V*1C +$GNGGA,081249.00,,,,,0,00,99.9,,,,,,*47 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081250.00,V,,,,,,,190319,,,N,V*14 +$GNGGA,081250.00,,,,,0,00,99.9,,,,,,*4F +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081251.00,V,,,,,,,190319,,,N,V*15 +$GNGGA,081251.00,,,,,0,00,99.9,,,,,,*4E +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081252.00,V,,,,,,,190319,,,N,V*16 +$GNGGA,081252.00,,,,,0,00,99.9,,,,,,*4D +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081253.00,V,,,,,,,190319,,,N,V*17 +$GNGGA,081253.00,,,,,0,00,99.9,,,,,,*4C +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081254.00,V,,,,,,,190319,,,N,V*10 +$GNGGA,081254.00,,,,,0,00,99.9,,,,,,*4B +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081255.00,V,,,,,,,190319,,,N,V*11 +$GNGGA,081255.00,,,,,0,00,99.9,,,,,,*4A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081256.00,V,,,,,,,190319,,,N,V*12 +$GNGGA,081256.00,,,,,0,00,99.9,,,,,,*49 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081257.00,V,,,,,,,190319,,,N,V*13 +$GNGGA,081257.00,,,,,0,00,99.9,,,,,,*48 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081258.00,V,,,,,,,190319,,,N,V*1C +$GNGGA,081258.00,,,,,0,00,99.9,,,,,,*47 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081259.00,V,,,,,,,190319,,,N,V*1D +$GNGGA,081259.00,,,,,0,00,99.9,,,,,,*46 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081300.00,V,,,,,,,190319,,,N,V*10 +$GNGGA,081300.00,,,,,0,00,99.9,,,,,,*4B +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,46,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081301.00,V,,,,,,,190319,,,N,V*11 +$GNGGA,081301.00,,,,,0,00,99.9,,,,,,*4A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081302.00,V,,,,,,,190319,,,N,V*12 +$GNGGA,081302.00,,,,,0,00,99.9,,,,,,*49 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081303.00,V,,,,,,,190319,,,N,V*13 +$GNGGA,081303.00,,,,,0,00,99.9,,,,,,*48 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,064,,18,51,145,,0*67 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081304.00,V,,,,,,,190319,,,N,V*14 +$GNGGA,081304.00,,,,,0,00,99.9,,,,,,*4F +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,064,,18,51,145,,0*67 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081305.00,V,,,,,,,190319,,,N,V*15 +$GNGGA,081305.00,,,,,0,00,99.9,,,,,,*4E +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,51,145,,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081306.00,V,,,,,,,190319,,,N,V*16 +$GNGGA,081306.00,,,,,0,00,99.9,,,,,,*4D +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081307.00,V,,,,,,,190319,,,N,V*17 +$GNGGA,081307.00,,,,,0,00,99.9,,,,,,*4C +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081308.00,V,,,,,,,190319,,,N,V*18 +$GNGGA,081308.00,,,,,0,00,99.9,,,,,,*43 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081309.00,V,,,,,,,190319,,,N,V*19 +$GNGGA,081309.00,,,,,0,00,99.9,,,,,,*42 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081310.00,V,,,,,,,190319,,,N,V*11 +$GNGGA,081310.00,,,,,0,00,99.9,,,,,,*4A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,031,,0*65 +$GPGSV,4,4,14,28,02,284,,30,14,320,,0*61 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081311.00,V,,,,,,,190319,,,N,V*10 +$GNGGA,081311.00,,,,,0,00,99.9,,,,,,*4B +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081312.00,V,,,,,,,190319,,,N,V*13 +$GNGGA,081312.00,,,,,0,00,99.9,,,,,,*48 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081313.00,V,,,,,,,190319,,,N,V*12 +$GNGGA,081313.00,,,,,0,00,99.9,,,,,,*49 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081314.00,V,,,,,,,190319,,,N,V*15 +$GNGGA,081314.00,,,,,0,00,99.9,,,,,,*4E +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081315.00,V,,,,,,,190319,,,N,V*14 +$GNGGA,081315.00,,,,,0,00,99.9,,,,,,*4F +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081316.00,V,,,,,,,190319,,,N,V*17 +$GNGGA,081316.00,,,,,0,00,99.9,,,,,,*4C +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081317.00,V,,,,,,,190319,,,N,V*16 +$GNGGA,081317.00,,,,,0,00,99.9,,,,,,*4D +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081318.00,V,,,,,,,190319,,,N,V*19 +$GNGGA,081318.00,,,,,0,00,99.9,,,,,,*42 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081319.00,V,,,,,,,190319,,,N,V*18 +$GNGGA,081319.00,,,,,0,00,99.9,,,,,,*43 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,32,174,,04,32,271,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081320.00,V,,,,,,,190319,,,N,V*12 +$GNGGA,081320.00,,,,,0,00,99.9,,,,,,*49 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,33,174,,04,32,271,,07,47,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081321.00,V,,,,,,,190319,,,N,V*13 +$GNGGA,081321.00,,,,,0,00,99.9,,,,,,*48 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,33,174,,04,32,271,,07,47,325,,08,63,002,,0*68 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081322.00,V,,,,,,,190319,,,N,V*10 +$GNGGA,081322.00,,,,,0,00,99.9,,,,,,*4B +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,33,174,,04,32,270,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081323.00,V,,,,,,,190319,,,N,V*11 +$GNGGA,081323.00,,,,,0,00,99.9,,,,,,*4A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,33,174,,04,32,270,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,34,250,,11,59,192,,16,24,065,,18,52,145,,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081324.00,V,,,,,,,190319,,,N,V*16 +$GNGGA,081324.00,,,,,0,00,99.9,,,,,,*4D +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,33,174,,04,32,270,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,33,250,,11,59,192,,16,24,065,,18,52,145,,0*62 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081325.00,V,,,,,,,190319,,,N,V*17 +$GNGGA,081325.00,,,,,0,00,99.9,,,,,,*4C +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,33,174,,04,32,270,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,33,250,,11,59,192,,16,24,065,,18,52,145,,0*62 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,,27,34,032,,0*66 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081326.00,V,,,,,,,190319,,,N,V*14 +$GNGGA,081326.00,,,,,0,00,99.9,,,,,,*4F +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,33,174,,04,32,270,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,33,250,,11,59,192,,16,24,065,,18,52,145,,0*62 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,29,27,34,032,,0*6D +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081327.00,V,,,,,,,190319,,,N,V*15 +$GNGGA,081327.00,,,,,0,00,99.9,,,,,,*4E +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,33,174,,04,32,270,,07,47,325,,08,63,002,,0*69 +$GPGSV,4,2,14,09,33,250,,11,59,192,,16,24,065,,18,52,145,,0*62 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,29,27,34,032,,0*6D +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081328.00,V,,,,,,,190319,,,N,V*1A +$GNGGA,081328.00,,,,,0,00,99.9,,,,,,*41 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,33,174,27,04,32,270,,07,47,325,,08,63,002,17,0*6A +$GPGSV,4,2,14,09,33,250,,11,59,192,,16,24,065,,18,52,145,,0*62 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,30,27,34,032,,0*65 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081329.00,V,,,,,,,190319,,,N,V*1B +$GNGGA,081329.00,,,,,0,00,99.9,,,,,,*40 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,33,174,22,04,32,270,,07,47,325,29,08,63,002,16,0*65 +$GPGSV,4,2,14,09,33,250,,11,59,192,23,16,24,065,,18,52,145,,0*63 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,30,27,34,032,,0*65 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081330.00,V,,,,,,,190319,,,N,V*13 +$GNGGA,081330.00,,,,,0,00,99.9,,,,,,*48 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,33,174,19,04,32,270,,07,47,325,31,08,63,002,17,0*65 +$GPGSV,4,2,14,09,33,250,23,11,59,192,21,16,24,065,,18,52,145,,0*60 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,30,27,34,032,,0*65 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081331.00,V,,,,,,,190319,,,N,V*12 +$GNGGA,081331.00,,,,,0,00,99.9,,,,,,*49 +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,33,174,17,04,32,270,,07,47,325,31,08,63,002,16,0*6A +$GPGSV,4,2,14,09,33,250,20,11,59,192,20,16,24,065,,18,52,145,,0*62 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,29,27,34,032,,0*6D +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081332.00,V,,,,,,,190319,,,N,V*11 +$GNGGA,081332.00,,,,,0,00,99.9,,,,,,*4A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +$GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,4*0F +$GPGSV,4,1,14,01,33,174,,04,32,270,,07,47,325,30,08,63,002,15,0*6E +$GPGSV,4,2,14,09,33,250,17,11,59,192,21,16,24,065,,18,52,145,23,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,29,27,34,032,,0*6D +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081333.81,V,,,,,,,190319,,,N,V*19 +$GNGGA,081333.81,,,,,0,00,1.66,,,,,,*4A +$GNGSA,A,1,,,,,,,,,,,,,1.92,1.66,0.96,1*07 +$GNGSA,A,1,,,,,,,,,,,,,1.92,1.66,0.96,4*02 +$GPGSV,4,1,14,01,33,174,,04,32,270,,07,47,325,30,08,63,002,15,0*6E +$GPGSV,4,2,14,09,33,250,17,11,59,192,21,16,24,065,,18,52,145,22,0*67 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,29,27,34,032,,0*6D +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081334.00,V,,,,,,,190319,,,N,V*17 +$GNGGA,081334.00,,,,,0,00,2.57,,,,,,*45 +$GNGSA,A,1,,,,,,,,,,,,,4.44,2.57,3.61,1*03 +$GNGSA,A,1,,,,,,,,,,,,,4.44,2.57,3.61,4*06 +$GPGSV,4,1,14,01,33,174,,04,32,270,,07,47,325,30,08,63,002,14,0*6F +$GPGSV,4,2,14,09,33,250,16,11,59,192,21,16,24,065,,18,52,145,21,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,29,27,34,032,,0*6D +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081335.02,V,,,,,,,190319,,,N,V*14 +$GNGGA,081335.02,,,,,0,00,2.57,,,,,,*46 +$GNGSA,A,1,,,,,,,,,,,,,4.44,2.57,3.61,1*03 +$GNGSA,A,1,,,,,,,,,,,,,4.44,2.57,3.61,4*06 +$GPGSV,4,1,14,01,33,174,,04,32,270,,07,47,325,31,08,63,002,12,0*68 +$GPGSV,4,2,14,09,33,250,14,11,59,192,21,16,24,065,,18,52,145,20,0*66 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,29,27,34,032,26,0*69 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081335.97,V,,,,,,,190319,,,N,V*18 +$GNGGA,081335.97,,,,,0,00,2.57,,,,,,*4A +$GNGSA,A,1,,,,,,,,,,,,,4.44,2.57,3.61,1*03 +$GNGSA,A,1,,,,,,,,,,,,,4.44,2.57,3.61,4*06 +$GPGSV,4,1,14,01,33,174,28,04,32,270,,07,47,325,31,08,62,002,11,0*60 +$GPGSV,4,2,14,09,33,250,13,11,59,192,22,16,24,065,24,18,52,145,18,0*6F +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,29,27,34,032,24,0*6B +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081336.97,V,,,,,,,190319,,,N,V*1B +$GNGGA,081336.97,,,,,0,00,1.76,,,,,,*49 +$GNGSA,A,1,,,,,,,,,,,,,3.06,1.76,2.50,1*01 +$GNGSA,A,1,,,,,,,,,,,,,3.06,1.76,2.50,4*04 +$GPGSV,4,1,14,01,33,174,27,04,32,270,,07,47,325,31,08,62,002,14,0*6A +$GPGSV,4,2,14,09,33,250,13,11,59,192,21,16,24,065,21,18,52,145,18,0*69 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,29,27,34,032,23,0*6C +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,,,,,,,,N*2E +$GNRMC,081338.00,A,2232.52464,N,11357.12356,E,0.877,,190319,,,A,V*1C +$GNGGA,081338.00,2232.52464,N,11357.12356,E,1,07,1.64,-83.7,M,-2.4,M,,*4F +$GNGSA,A,3,01,27,26,07,08,11,18,,,,,,2.97,1.64,2.48,1*06 +$GNGSA,A,3,,,,,,,,,,,,,2.97,1.64,2.48,4*05 +$GPGSV,4,1,14,01,33,174,28,04,32,270,19,07,47,325,31,08,62,002,15,0*6C +$GPGSV,4,2,14,09,33,250,15,11,59,192,21,16,24,065,18,18,52,145,18,0*65 +$GPGSV,4,3,14,22,03,163,,23,29,211,,26,06,087,29,27,34,032,23,0*6C +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,T,,M,0.877,N,1.624,K,A*34 +$GNRMC,081339.00,A,2232.52531,N,11357.12191,E,0.156,,190319,,,A,V*1F +$GNGGA,081339.00,2232.52531,N,11357.12191,E,1,07,1.64,-85.6,M,-2.4,M,,*41 +$GNGSA,A,3,01,27,26,07,08,11,18,,,,,,2.97,1.64,2.48,1*06 +$GNGSA,A,3,,,,,,,,,,,,,2.97,1.64,2.48,4*05 +$GPGSV,4,1,14,01,33,174,28,04,32,270,18,07,47,325,31,08,62,002,18,0*60 +$GPGSV,4,2,14,09,33,250,14,11,59,192,21,16,24,065,17,18,52,145,19,0*6A +$GPGSV,4,3,14,22,03,163,15,23,29,211,,26,06,087,29,27,34,032,22,0*69 +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,T,,M,0.156,N,0.289,K,A*3C +$GNRMC,081340.00,A,2232.52200,N,11357.11214,E,0.804,,190319,,,A,V*17 +$GNGGA,081340.00,2232.52200,N,11357.11214,E,1,08,1.52,-106.6,M,-2.4,M,,*77 +$GNGSA,A,3,01,27,26,07,08,16,11,18,,,,,2.88,1.52,2.45,1*07 +$GNGSA,A,3,,,,,,,,,,,,,2.88,1.52,2.45,4*03 +$GPGSV,4,1,14,01,33,174,28,04,32,270,17,07,47,325,32,08,62,002,19,0*6D +$GPGSV,4,2,14,09,33,250,,11,59,192,21,16,24,065,15,18,52,145,19,0*6D +$GPGSV,4,3,14,22,03,163,13,23,29,211,,26,06,087,29,27,34,032,22,0*6F +$GPGSV,4,4,14,28,02,285,,30,14,320,,0*60 +$BDGSV,1,1,00,0*74 +$GNVTG,,T,,M,0.804,N,1.489,K,A*35 +#>%\0T3,RomFw,1.1(48),Aug 12 2016 16:57:35普$GNRMC,081341.00,A,2232.52104,N,11357.11085,E,0.878,,190319,,,A,V*10 +$GNGGA,081341.00,2232.52104,N,11357.11085,E,1,07,1.64,-110.4,M,-2.4,M,,*74 +$GNGSA,A,3,01,27,26,07,08,11,18,,,,,,2.97,1.64,2.48,1*06 +$GNGSA,A,3,,,,,,,,,,,,,2.97,1.64,2.48,4*05 +$GPGSV,4,1,14,01,33,174,27,04,32,270,17,07,47,325,32,08,62,002,21,0*69 +$GPGSV,4,2,14,09,33,250,20,11,59,192,20,16,24,065,14,18,52,145,18,0*6E +$GPGSV,4,3,14,22,03,163,13,23,29,211,,26,06,087,29,27,34,032,20,0*6D +$GPGSV,4,4,14,28,02,285,,30,14,320,13,0*62 +$BDGSV,1,1,00,0*74 +$GNVTG,,T,,M,0.878,N,1.625,K,A*3A +$GNRMC,081342.00,A,2232.51933,N,11357.10703,E,1.318,69.34,190319,,,A,V*3E +$GNGGA,081342.00,2232.51933,N,11357.10703,E,1,08,1.52,-120.3,M,-2.4,M,,*7E +$GNGSA,A,3,01,27,26,07,08,16,11,18,,,,,2.89,1.52,2.45,1*06 +$GNGSA,A,3,,,,,,,,,,,,,2.89,1.52,2.45,4*02 +$GPGSV,4,1,14,01,33,174,26,04,32,270,17,07,47,325,31,08,62,002,22,0*68 +$GPGSV,4,2,14,09,33,250,19,11,59,192,19,16,24,065,12,18,52,145,17,0*67 +$GPGSV,4,3,14,22,03,163,13,23,29,211,,26,06,087,29,27,34,032,20,0*6D +$GPGSV,4,4,14,28,02,285,,30,14,320,13,0*62 +$BDGSV,1,1,00,0*74 +$GNVTG,69.34,T,,M,1.318,N,2.442,K,A*10 +$GNRMC,081343.00,A,2232.51797,N,11357.10473,E,1.701,,190319,,,A,V*11 +$GNGGA,081343.00,2232.51797,N,11357.10473,E,1,08,1.52,-127.0,M,-2.4,M,,*7F +$GNGSA,A,3,01,27,26,07,08,16,11,18,,,,,2.89,1.52,2.45,1*06 +$GNGSA,A,3,,,,,,,,,,,,,2.89,1.52,2.45,4*02 +$GPGSV,4,1,14,01,33,174,24,04,32,270,16,07,47,325,30,08,62,002,22,0*6A +$GPGSV,4,2,14,09,33,250,17,11,59,192,17,16,24,065,15,18,52,145,16,0*61 +$GPGSV,4,3,14,22,03,163,15,23,28,211,,26,06,087,28,27,34,032,19,0*61 +$GPGSV,4,4,14,28,02,285,17,30,14,320,13,0*64 +$BDGSV,1,1,00,0*74 +$GNVTG,,T,,M,1.701,N,3.151,K,A*3C +$GNRMC,081344.00,A,2232.51715,N,11357.10308,E,1.930,,190319,,,A,V*1B +$GNGGA,081344.00,2232.51715,N,11357.10308,E,1,07,1.82,-133.3,M,-2.4,M,,*7D +$GNGSA,A,3,01,27,26,07,08,16,11,,,,,,3.56,1.82,3.06,1*07 +$GNGSA,A,3,,,,,,,,,,,,,3.56,1.82,3.06,4*0A +$GPGSV,4,1,14,01,33,174,24,04,32,270,16,07,47,325,30,08,62,002,22,0*6A +$GPGSV,4,2,14,09,33,250,15,11,59,192,16,16,24,065,14,18,52,145,,0*64 +$GPGSV,4,3,14,22,03,163,14,23,28,211,21,26,06,087,28,27,34,032,20,0*69 +$GPGSV,4,4,14,28,02,285,17,30,14,320,,0*66 +$BDGSV,1,1,00,0*74 +$GNVTG,,T,,M,1.930,N,3.574,K,A*33 +$GNRMC,081345.00,A,2232.51744,N,11357.10523,E,1.823,,190319,,,A,V*12 +$GNGGA,081345.00,2232.51744,N,11357.10523,E,1,07,1.19,-129.8,M,-2.4,M,,*75 +$GNGSA,A,3,01,27,26,07,08,09,11,,,,,,2.35,1.19,2.02,1*0A +$GNGSA,A,3,,,,,,,,,,,,,2.35,1.19,2.02,4*09 +$GPGSV,4,1,15,01,33,174,25,04,32,270,15,07,47,325,30,08,62,002,24,0*6F +$GPGSV,4,2,15,09,33,250,13,11,59,192,16,16,24,065,14,18,52,145,17,0*65 +$GPGSV,4,3,15,22,03,163,13,23,28,211,21,26,06,087,27,27,34,032,21,0*61 +$GPGSV,4,4,15,28,02,285,16,30,14,320,,50,46,122,27,0*55 +$BDGSV,1,1,00,0*74 +$GNVTG,,T,,M,1.823,N,3.375,K,A*37 +$GNRMC,081346.00,A,2232.51792,N,11357.10694,E,2.117,,190319,,,A,V*18 +$GNGGA,081346.00,2232.51792,N,11357.10694,E,1,07,1.19,-127.4,M,-2.4,M,,*70 +$GNGSA,A,3,01,27,26,07,08,09,11,,,,,,2.35,1.19,2.02,1*0A +$GNGSA,A,3,,,,,,,,,,,,,2.35,1.19,2.02,4*09 +$GPGSV,4,1,14,01,33,174,25,04,32,270,15,07,47,325,29,08,62,002,25,0*67 +$GPGSV,4,2,14,09,33,250,14,11,59,192,17,16,24,065,16,18,52,145,16,0*61 +$GPGSV,4,3,14,22,03,163,13,23,28,211,22,26,06,087,28,27,34,032,23,0*6E +$GPGSV,4,4,14,28,02,285,15,30,14,320,,0*64 +$BDGSV,1,1,00,0*74 +$GNVTG,,T,,M,2.117,N,3.920,K,A*30 +$GNRMC,081347.00,A,2232.51905,N,11357.10992,E,2.353,,190319,,,A,V*12 +$GNGGA,081347.00,2232.51905,N,11357.10992,E,1,08,1.13,-121.3,M,-2.4,M,,*7C +$GNGSA,A,3,01,27,23,26,07,08,09,11,,,,,2.22,1.13,1.92,1*0D +$GNGSA,A,3,,,,,,,,,,,,,2.22,1.13,1.92,4*0F +$GPGSV,4,1,14,01,33,174,23,04,32,270,15,07,47,325,27,08,62,002,24,0*6E +$GPGSV,4,2,14,09,33,250,11,11,59,192,17,16,24,065,16,18,52,145,15,0*67 +$GPGSV,4,3,14,22,03,163,14,23,28,211,20,26,06,087,26,27,34,032,21,0*67 +$GPGSV,4,4,14,28,02,285,15,30,14,320,,0*64 +$BDGSV,1,1,00,0*74 +$GNVTG,,T,,M,2.353,N,4.358,K,A*30 diff --git "a/doc/\346\263\260\346\226\227TD1030/TD-SDBP_V2.3\350\257\264\346\230\216\344\271\246(AGNSS).pdf" "b/doc/\346\263\260\346\226\227TD1030/TD-SDBP_V2.3\350\257\264\346\230\216\344\271\246(AGNSS).pdf" new file mode 100644 index 0000000..f5ec5ed Binary files /dev/null and "b/doc/\346\263\260\346\226\227TD1030/TD-SDBP_V2.3\350\257\264\346\230\216\344\271\246(AGNSS).pdf" differ diff --git "a/doc/\346\263\260\346\226\227TD1030/TD1030\350\276\223\345\205\245\350\276\223\345\207\272\345\205\267\344\275\223\346\214\207\344\273\244.pdf" "b/doc/\346\263\260\346\226\227TD1030/TD1030\350\276\223\345\205\245\350\276\223\345\207\272\345\205\267\344\275\223\346\214\207\344\273\244.pdf" new file mode 100644 index 0000000..3917940 Binary files /dev/null and "b/doc/\346\263\260\346\226\227TD1030/TD1030\350\276\223\345\205\245\350\276\223\345\207\272\345\205\267\344\275\223\346\214\207\344\273\244.pdf" differ diff --git "a/doc/\346\263\260\346\226\227TD1030/tdagnss.c" "b/doc/\346\263\260\346\226\227TD1030/tdagnss.c" new file mode 100644 index 0000000..6396f85 --- /dev/null +++ "b/doc/\346\263\260\346\226\227TD1030/tdagnss.c" @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define HOST "agnss.techtotop.com" + +int main() { + int nfd,sfd; + int i=0,j=0; + char temp[1024]={0}; + char data[8192]={0}; + struct sockaddr_in addr; + struct termios options; + struct hostent *p; + char *ip; + char *dev = "/dev/ttyS0"; + + nfd = socket(AF_INET, SOCK_STREAM, 0); + p = gethostbyname(HOST); + ip = inet_ntoa(*(struct in_addr *)p->h_addr_list[0]); + + bzero(&addr,sizeof(struct sockaddr_in)); + addr.sin_family=AF_INET; + addr.sin_addr.s_addr = inet_addr(ip); + addr.sin_port=htons(9011); + + connect(nfd,(struct sockaddr *)(&addr), sizeof(struct sockaddr)); + + write(nfd, "all", 3); + + while(1) { + i=read(nfd,temp,1024); + if(0==i) + break; + memcpy(data+j,temp,i); + j+=i; + } + + close(nfd); + + sfd=open(dev,O_RDWR|O_NOCTTY|O_NDELAY); + + tcgetattr(sfd, &options); + cfsetispeed(&options, B9600); + cfsetospeed(&options, B9600); + options.c_cflag |= (CLOCAL | CREAD); + options.c_cflag &= ~PARENB; + options.c_cflag &= ~CSTOPB; + options.c_cflag &= ~CSIZE; + options.c_cflag |= CS8; + options.c_cflag &= ~CRTSCTS; + options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + options.c_iflag &= ~(IXON | IXOFF | IXANY); + options.c_oflag &= ~OPOST; + + tcflush(sfd,TCIFLUSH); + tcsetattr(sfd, TCSANOW, &options); + + write(sfd,data,j); + + close(sfd); + +// FILE *fp=fopen("data","wb"); +// fwrite(data,j,1,fp); +// fclose(fp); + + return 0; +} + diff --git "a/doc/\346\263\260\346\226\227TD1030/tdagnss.py" "b/doc/\346\263\260\346\226\227TD1030/tdagnss.py" new file mode 100644 index 0000000..a2ff559 --- /dev/null +++ "b/doc/\346\263\260\346\226\227TD1030/tdagnss.py" @@ -0,0 +1,25 @@ +#!/usr/bin/env python +import socket +socket.setdefaulttimeout(5) +c = socket.socket() +c.connect(('agnss.techtotop.com',9011)) +c.send('all') +temp = '' +data = '' +while True: + temp = c.recv(1024) + if not len(temp): + break + else: + data += temp + +#f=open('data','wb') +#print >>f,data +#f.close() +import serial +tty = serial.Serial() +tty.port = 'COM1' +tty.baudrate = 9600 +tty.open() +tty.write(data) +tty.close() diff --git "a/doc/\346\263\260\346\226\227TD1030/\346\263\260\346\226\227A-GNSS\346\226\271\346\241\210\347\224\250\346\210\267\346\211\213\345\206\214V1.5.pdf" "b/doc/\346\263\260\346\226\227TD1030/\346\263\260\346\226\227A-GNSS\346\226\271\346\241\210\347\224\250\346\210\267\346\211\213\345\206\214V1.5.pdf" new file mode 100644 index 0000000..bf242d2 Binary files /dev/null and "b/doc/\346\263\260\346\226\227TD1030/\346\263\260\346\226\227A-GNSS\346\226\271\346\241\210\347\224\250\346\210\267\346\211\213\345\206\214V1.5.pdf" differ diff --git "a/doc/\350\260\267\347\261\263JT808\351\203\250\346\240\207\351\200\232\350\256\257\345\215\217\350\256\256V1.3(\347\262\276\347\256\200\347\211\210)_2019-03-23.pdf" "b/doc/\350\260\267\347\261\263JT808\351\203\250\346\240\207\351\200\232\350\256\257\345\215\217\350\256\256V1.3(\347\262\276\347\256\200\347\211\210)_2019-03-23.pdf" new file mode 100644 index 0000000..427f461 Binary files /dev/null and "b/doc/\350\260\267\347\261\263JT808\351\203\250\346\240\207\351\200\232\350\256\257\345\215\217\350\256\256V1.3(\347\262\276\347\256\200\347\211\210)_2019-03-23.pdf" differ diff --git "a/doc/\350\260\267\347\261\263\345\265\214\345\205\245\345\274\217\347\274\226\347\240\201\350\247\204\350\214\203.pdf" "b/doc/\350\260\267\347\261\263\345\265\214\345\205\245\345\274\217\347\274\226\347\240\201\350\247\204\350\214\203.pdf" new file mode 100644 index 0000000..79b6920 Binary files /dev/null and "b/doc/\350\260\267\347\261\263\345\265\214\345\205\245\345\274\217\347\274\226\347\240\201\350\247\204\350\214\203.pdf" differ diff --git "a/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/7670_260996_STK8BA50-R Datasheet v1.5.pdf" "b/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/7670_260996_STK8BA50-R Datasheet v1.5.pdf" new file mode 100644 index 0000000..4887255 Binary files /dev/null and "b/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/7670_260996_STK8BA50-R Datasheet v1.5.pdf" differ diff --git "a/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/BST-BMA253-DS000-01.pdf" "b/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/BST-BMA253-DS000-01.pdf" new file mode 100644 index 0000000..99ef7d6 Binary files /dev/null and "b/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/BST-BMA253-DS000-01.pdf" differ diff --git "a/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/DS_da213_Wearable.pdf" "b/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/DS_da213_Wearable.pdf" new file mode 100644 index 0000000..da6bab4 Binary files /dev/null and "b/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/DS_da213_Wearable.pdf" differ diff --git "a/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/SC7A20\350\257\264\346\230\216\344\271\246_0.91(\345\270\246\345\257\204\345\255\230\345\231\250\346\217\217\350\277\260).pdf" "b/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/SC7A20\350\257\264\346\230\216\344\271\246_0.91(\345\270\246\345\257\204\345\255\230\345\231\250\346\217\217\350\277\260).pdf" new file mode 100644 index 0000000..7afa15f Binary files /dev/null and "b/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/SC7A20\350\257\264\346\230\216\344\271\246_0.91(\345\270\246\345\257\204\345\255\230\345\231\250\346\217\217\350\277\260).pdf" differ diff --git "a/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/STK8BA50-S Preliminary Datasheet v0.9.4.pdf" "b/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/STK8BA50-S Preliminary Datasheet v0.9.4.pdf" new file mode 100644 index 0000000..bac3bb2 Binary files /dev/null and "b/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/STK8BA50-S Preliminary Datasheet v0.9.4.pdf" differ diff --git "a/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/\347\237\275\345\210\233STK8BA50-S\302\240Datasheet\302\240v1.0.pdf" "b/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/\347\237\275\345\210\233STK8BA50-S\302\240Datasheet\302\240v1.0.pdf" new file mode 100644 index 0000000..6e38d03 Binary files /dev/null and "b/doc/\350\277\220\345\212\250\344\274\240\346\204\237\345\231\250\350\265\204\346\226\231/\347\237\275\345\210\233STK8BA50-S\302\240Datasheet\302\240v1.0.pdf" differ diff --git "a/doc/\351\200\232\344\277\241\345\215\217\350\256\256V1.1.pdf" "b/doc/\351\200\232\344\277\241\345\215\217\350\256\256V1.1.pdf" new file mode 100644 index 0000000..58b7a51 Binary files /dev/null and "b/doc/\351\200\232\344\277\241\345\215\217\350\256\256V1.1.pdf" differ diff --git a/filecreat.pl b/filecreat.pl new file mode 100644 index 0000000..bcfc639 --- /dev/null +++ b/filecreat.pl @@ -0,0 +1,385 @@ +#!/usr/bin/perl +use Cwd; +use File::Copy; + +my $dir = getcwd; + +my $mark = "VERSION_NUMBER"; + +my $mark_oem_code = "UPDATE_OEM_CODE"; + +my $mark_dev_id = "UPDATE_DEVICE_CODE"; + +my $version; + +my $checksum; + +my $getverflag = 0; + +my $cfile = $dir."/inc/config_service.h"; + +my $ofile = $dir."/output/GmAppMain.ex"; + +my $bfile = $dir."/output/GmAppMain.bin"; + +my $release = $dir."/release"; + +my $mfile; + +sub set_zero_to_file{ + + my $t_handle = $_[0]; + + my $t_len = $_[1]; + + my $zero = "00"; + + my $set_buf = pack("H*",$zero); + + if($t_len > 0) + { + for(my $cnt = 0; $cnt < $t_len ; $cnt++) + { + syswrite($t_handle,$set_buf,1); + } + } + + +} + +#my $dir = getcwd; + +my $build_ofile = $dir."/build/GmAppMain.ex"; + +my $build_bfile = $dir."/build/GmAppMain.bin"; + +my $out_ofile = $dir."/output/GmAppMain.ex"; + +my $out_bfile = $dir."/output/GmAppMain.bin"; + +my $update_file = $dir."/output/GMAppMain.m"; + +my $output_dir = $dir."/output"; + +my $oem_ofset = 0x31A69; + +#my @upd_oem = (0,0,0,0,0,0); +my $upd_oem; + +my $devid_fset = 0x31A7A; + +#my @upd_devid = (0,0,0,0,0); +my $upd_devid; + +my @upd_checksum = (0,0,0,0,0,0,0,0,0,0); + +#my @upd_bootchecksum = (0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0,0); +my $upd_bootchecksum = "FFFFFFFF"; + +my $ver_ofset = 0x315B7; + +#my @upd_version = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); +my $upd_version; + +my $checksum = 0; + +if(-e $output_dir) +{ + +} +else +{ + mkdir $output_dir; +} + +if(-e $cfile){ + printf "$cfile is exit!!\r\n"; +}else{ + exit; +} + +open(VERNO,"<".$cfile) or die $cfile."无法打开",$!; + +@lines = ; + +my @l2_split; + +foreach $line (@lines) +{ + @l_split = split(" ",$line); + + if($l_split[1] eq $mark) + { + @l2_split = split("\"",$l_split[2]); + + printf "\r\n\version $l2_split[1]\r\n"; + + $version = $l2_split[1]; + + $upd_version = $l2_split[1]; + + $getverflg = 1; + + } + + if($l_split[1] eq $mark_oem_code) + { + @l2_split = split("\"",$l_split[2]); + + printf "OEM ".$l2_split[1]; + + $upd_oem = $l2_split[1]; + } + + if($l_split[1] eq $mark_dev_id) + { + @l2_split = split("\"",$l_split[2]); + + $upd_devid = substr($l2_split[1],8); + + printf "\r\n\dev id $upd_devid\r\n"; + + last; + } + + +} + +close(VERNO) || die "无法关闭文件"; + + +copy($build_bfile,$out_bfile)||warn "could not copy file : $!"; + +copy($build_ofile,$out_ofile)||warn "could not copy file : $!"; + +if(!-e $out_bfile) +{ + printf "$out_bfile not exit!!"; + die; +} + +if(!-e $out_ofile) +{ + printf "$out_ofile not exit!!"; + die; +} + + +open (BINHANDLE,$out_bfile) || die "无目标文件,$!"; + +binmode(BINHANDLE); + +$checksum = 0; + +my $read_len = 1; + +my $index = 0; + +my $bin_hex = 0; + +my $bin = 0; + +my $buf = 0; + +my $arry_cnt = 0; + + +$index = 0; + +while($read_len > 0) +{ + + $read_len = sysread(BINHANDLE,$buf,1); + + if($read_len >0) + { + $bin_hex = unpack("H*",$buf); + + $bin = hex($bin_hex); + + #$file_byte = sprintf("%x",$bin^0x0F); + + #syswrite(UPDATEHAN,pack("h*",$file_byte),1); + + $checksum = $checksum + $bin; + + $index++; + + } + + +} + +my $checksum_hex = uc(sprintf("%x",$checksum)); + + +close BINHANDLE; + +#close UPDATEHAN; + +open (UPDATEHAN,">$update_file"); + +open (BINHANDLE,$out_bfile) || die "无目标文件,$!"; + +binmode(BINHANDLE); + +binmode(UPDATEHAN); + +syswrite(UPDATEHAN,$upd_oem,length($upd_oem)); + +set_zero_to_file(UPDATEHAN,6-length($upd_oem)); + +syswrite(UPDATEHAN,$upd_devid,length($upd_devid));#6-length($upd_oem) + +set_zero_to_file(UPDATEHAN,5-length($upd_devid)); + +syswrite(UPDATEHAN,$upd_version,length($upd_version)); + +set_zero_to_file(UPDATEHAN,20-length($upd_version)); + +syswrite(UPDATEHAN,$checksum_hex,length($checksum_hex)); + +set_zero_to_file(UPDATEHAN,10-length($checksum_hex)); + +syswrite(UPDATEHAN,$upd_bootchecksum,length($upd_bootchecksum)); + +set_zero_to_file(UPDATEHAN,10-length($upd_bootchecksum)); + +for(my $len_cnt = 4 ; $len_cnt > 0 ; $len_cnt--) +{ + my $len_byte = ($index >> (($len_cnt - 1)*8))&0xFF; + + my $len_string = sprintf("%x",$len_byte); + + if($len_cnt == 1) + { + syswrite(UPDATEHAN,pack("H*",$len_string),1); + } + else + { + syswrite(UPDATEHAN,pack("h*",$len_string),1); + } + +} + +set_zero_to_file(UPDATEHAN,73); + +$read_len = 1; + +while($read_len > 0) +{ + + $read_len = sysread(BINHANDLE,$buf,1); + + if($read_len >0) + { + $bin_hex = unpack("H*",$buf); + + $bin = hex($bin_hex); + + $file_byte = sprintf("%x",$bin^0x0F); + + if($bin < 0x10) + { + syswrite(UPDATEHAN,pack("h*",$file_byte),1); + } + else + { + syswrite(UPDATEHAN,pack("H*",$file_byte),1); + } + + + #$checksum = $checksum + $bin; + + #$index++; + + } + + +} + +close UPDATEHAN; + +close BINHANDLE; + +my $new_name = "(".$checksum_hex.")"; + +rename($update_file,$dir."/output/".$new_name."GMAppMain.m"); + +#rename($out_ofile,$dir."/output/".$new_name."GMAppMain.ex"); + +#rename($out_bfile,$dir."/output/".$new_name."GMAppMain.bin"); + +my @allfiles=glob($dir."/output/*"); + + +if($getverflg == 0) +{ + exit; +} + +foreach $file (@allfiles){ + + #printf $file."\r\n"; + + @l1_file = split(/\./,$file); + + #printf $l1_file[1]."\r\n"; + + if($l1_file[1] eq "m") + { + @l2_file = split(/\(/,$l1_file[0]); + + #printf $l2_file[1]."\r\n"; + + if($l2_file[1]) + { + @l3_file = split(/\)/,$l2_file[1]); + + #printf $l3_file[0]."\r\n"; + + $checksum = "(".$l3_file[0].")"; + + $mfile = $file; + + last; + } + } +} + +($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(); +$year = $year + 1900; +$mon = $mon + 1; +#$now = $year.$mon.$mday.$hour.$min.$sec; +$now = sprintf("%d%02d%02d%02d%02d%02d",$year,$mon,$mday,$hour,$min,$sec); +if(-e $release){ + +}else{ + mkdir $release +} + +$newversom_dir = $release."/".$version."_".$now; + +mkdir $newversom_dir; + +if(-e $ofile){ + #copy $ofile,$dir."/output/".$checksum.$version.".ex"; + copy $ofile,$newversom_dir."/".$checksum.$version.".ex"; +}else{ + printf "ofile not exit!\r\n"; +} + +if(-e $mfile){ + #rename $mfile,$dir."/output/".$checksum.$version.".m"; + copy $mfile,$newversom_dir."/".$checksum.$version.".m"; +}else{ + printf "mfile not exit!\r\n"; +} + +if(-e $bfile){ + copy $bfile,$newversom_dir."/".$checksum.$version.".bin"; +}else{ + print "bfile not exit!\r\n" +} + + diff --git a/inc/C_H/Unicodexdcl.h b/inc/C_H/Unicodexdcl.h new file mode 100644 index 0000000..92b92af --- /dev/null +++ b/inc/C_H/Unicodexdcl.h @@ -0,0 +1,985 @@ +/***************************************************************************** +* Copyright Statement: +* -------------------- +* This software is protected by Copyright and the information contained +* herein is confidential. The software may not be copied and the information +* contained herein may not be used or disclosed except with the written +* permission of MediaTek Inc. (C) 2005 +* +* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES +* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") +* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON +* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. +* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE +* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR +* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH +* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO +* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S +* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. +* +* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE +* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, +* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, +* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO +* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +* +* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE +* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF +* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND +* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER +* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). +* +*****************************************************************************/ + +/******************************************************************************* + * Filename: + * --------- + * Unicodexdcl.h + * + * Project: + * -------- + * MAUI + * + * Description: + * ------------ + * + * + * Author: + * ------- + * + * + *============================================================================== + * HISTORY + * Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! + *------------------------------------------------------------------------------ + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + * removed! + * removed! + * removed! + * + *------------------------------------------------------------------------------ + * Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! + *============================================================================== + *******************************************************************************/ + +/** + * Copyright Notice + * ?2002 - 2003, Pixtel Communications, Inc., 1489 43rd Ave. W., + * Vancouver, B.C. V6M 4K8 Canada. All Rights Reserved. + * (It is illegal to remove this copyright notice from this software or any + * portion of it) + */ + +/************************************************************** + FILENAME : Unicodexdcl.h + PURPOSE : Gives the current build settings. + REMARKS : Manish + AUTHOR : Pixtel Engineers + DATE : . + **************************************************************/ + +#ifndef _UNICODEXDCL_H_ +#define _UNICODEXDCL_H_ + +#include "MMIDataType.h" +#include "kal_non_specific_general_types.h" +/* the application include this header to get related API */ +/* DOM-NOT_FOR_SDK-BEGIN */ +/***************************************************************************** + * FUNCTION + * mmi_wc_to_ucs2 + * DESCRIPTION + * convert unicode to UCS2 encoding + * PARAMETERS + * unicode : [IN] Value to be encoded + * charLength : [OUT] The length of the character + * arrOut : [OUT] The output character + * RETURNS + * U8 -> Status, 0 is failed, 1 is success. + *****************************************************************************/ +extern U8 mmi_wc_to_ucs2(U16 unicode, U8 *charLength, U8 *arrOut); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2_to_wc + * DESCRIPTION + * convert UCS2 encoded scheme to unicode + * PARAMETERS + * pUnicode : [IN] array containing UCS2 encoded characters + * arr : [IN] unicode equivalent + * RETURNS + * U8 -> Status, 0 is failed, 1 is success. + *****************************************************************************/ +extern U8 mmi_ucs2_to_wc(PU16 pUnicode, PU8 arrOut); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2strlen + * DESCRIPTION + * Gives the length of UCS2 encoded string + * PARAMETERS + * arrOut : [IN] array containing UCS2 encoded characters + * RETURNS + * S32-> Status + *****************************************************************************/ +extern S32 mmi_ucs2strlen(const CHAR *arrOut); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2cmp + * DESCRIPTION + * compares two strings + * PARAMETERS + * string1 : [IN] String1 + * string2 : [OUT] String2 + * RETURNS + * <0 - string1 less than string2 + * 0 - string1 identical to string2 + * >0 - string1 greater than string2 + *****************************************************************************/ +extern S32 mmi_ucs2cmp(const CHAR *string1, const CHAR *string2); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2cpy + * DESCRIPTION + * copies the one UCS2 encoded string to other + * PARAMETERS + * strDestination : [OUT] Destination string + * strSource : [IN] source string + * RETURNS + * CHAR * -> pointer to destination string or NULL + *****************************************************************************/ +extern CHAR *mmi_ucs2cpy(CHAR *strDestination, const CHAR *strSource); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2ncmp + * DESCRIPTION + * The function is used for compare UCS2 characters of two strings. Size is + * the character number not the byte numbers. + * PARAMETERS + * string1 : [IN] UCS2 string1 + * string2 : [IN] UCS2 string2 + * count : [IN] Number in character (not byte) + * RETURNS + * <0 - string1 less than string2 + * 0 - string1 identical to string2 + * >0 - string1 greater than string2 + *****************************************************************************/ +extern S32 mmi_ucs2ncmp(const CHAR *string1, const CHAR *string2, U32 count); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2ncpy + * DESCRIPTION + * The function is used for copy UCS2 characters of one string to another. + * If size is less than the length of strSource, a null character is still + * appended automatically to strDestination. If size is greater than the + * length of strSource, strDestination is padding with null characters up + * to length size. The function behavior is a little bit different from strncpy. + * PARAMETERS + * strDestination : [OUT] StrDest-> Destination string + * strSource : [IN] Source string + * size : [IN] The size that needs to copy. + * RETURNS + * CHAR * -> pointer to destination string or NULL + *****************************************************************************/ +extern CHAR *mmi_ucs2ncpy(CHAR *strDestination, const CHAR *strSource, U32 size); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2cat + * DESCRIPTION + * The function is used for append strSource to strDestination and terminate + * the resulting string with a null character. + * PARAMETERS + * strDestination : [OUT] Destination string + * strSource : [IN] Source string + * RETURNS + * Return the destination string + *****************************************************************************/ +extern CHAR *mmi_ucs2cat(CHAR *strDestination, const CHAR *strSource); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2ncat + * DESCRIPTION + * The function is used for append the first size characters of strSource + * to strDestination and terminate the resulting string with a null character. + * PARAMETERS + * strDestination : [OUT] UCS2 destination string + * strSource : [IN] UCS2 source string + * size : [IN] Size in character (not byte) + * RETURNS + * Return the destination string + *****************************************************************************/ +extern CHAR *mmi_ucs2ncat(CHAR *strDestination, const CHAR *strSource, U32 size); + + +/***************************************************************************** + * FUNCTION + * mmi_ucs2trim_left + * DESCRIPTION + * Skip over the TrimChars from the begin character. + * PARAMETERS + * strSrc : [IN] The source string. + * TrimChars : [IN] The trim chars. + * RETURNS + * Return the result string. + *****************************************************************************/ +extern CHAR *mmi_ucs2trim_left(const CHAR *strSrc, const CHAR *TrimChars); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2find + * DESCRIPTION + * Search for the break_chars and store how many chars have been read over to reach + * the desired break_char in read_length. + * PARAMETERS + * strSrc : [IN] The source string. + * break_chars : [IN] The break_chars. + * read_length : [OUT] The number of chars to reach the break_char. + * direction : [IN] 1: sesarch forward ; -1: search backward. + * RETURNS + * 1: found the break_chars ; -1: searched over the whole strSrc and do not fing the break_chars + *****************************************************************************/ +extern S32 mmi_ucs2find(const CHAR *strSrc, const CHAR *break_chars, S32 *read_length, S16 direction); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2toi + * DESCRIPTION + * to parse over a int number, including positive and negative signs (+,-). + * PARAMETERS + * strSrc : [IN] The source string. + * out_num : [OUT] The ourput number. + * read_length : [OUT] The read string length. + * RETURNS + * 1: parse successfully ; -1: parse number fail. + *****************************************************************************/ +extern S32 mmi_ucs2toi(const CHAR *strSrc, S32 *out_num, S32 *read_length); + +/***************************************************************************** + * FUNCTION + * mmi_asc_to_ucs2 + * DESCRIPTION + * The function is used for convert ANSII string to UCS2 string. The caller + * need to make sure the pOutBuffer size must have enough space or the function + * causes the memory corruption. The function will add the terminated character + * at the end of pOutBuffer array. The byte order of UCS2 character(output param) + * is little endian. + * PARAMETERS + * pOutBuffer : [OUT] The output buffer. + * pInBuffer : [IN] The input buffer. + * RETURNS + * Return the bytes to convert. + *****************************************************************************/ +extern U16 mmi_asc_to_ucs2(CHAR *pOutBuffer, CHAR *pInBuffer); + +/***************************************************************************** + * FUNCTION + * mmi_asc_n_to_ucs2 + * DESCRIPTION + * The function is used for convert the characters of ANSII string to UCS2 + * string. The caller need to make sure the pOutBuffer size is greater than + * len and the function doesn't add the terminated character at the end of + * the pOutBuffer array. The byte order of UCS2 character(output param) is + * little endian. + * PARAMETERS + * pOutBuffer : [OUT] UCS2 destination string. + * pInBuffer : [IN] ANSII source string + * len : [IN] Length in bytes + * RETURNS + * Return the bytes to convert. + *****************************************************************************/ +extern U16 mmi_asc_n_to_ucs2(CHAR *pOutBuffer, CHAR *pInBuffer, U32 len); + +/***************************************************************************** + * FUNCTION + * mmi_asc_to_ucs2_ex + * DESCRIPTION + * The function is used for convert ANSII string to UCS2 string. The caller + * need to make sure the pOutBuffer size must have enough space or the function + * causes the memory corruption. The function will add the terminated character + * at the end of pOutBuffer array. The byte order of UCS2 character(output param) + * is little endian. + * Unlike mmi_asc_to_ucs2, it will ignore the controls in ANSII string. + * PARAMETERS + * pOutBuffer : [OUT] UCS2 destination string + * pInBuffer : [IN] ANSII source string + * RETURNS + * Return the bytes to convert. + *****************************************************************************/ +extern U16 mmi_asc_to_ucs2_ex(CHAR *pOutBuffer, CHAR *pInBuffer); + +/***************************************************************************** + * FUNCTION + * mmi_asc_n_to_ucs2_Ex + * DESCRIPTION + * The function is used for convert the characters of ANSII string to UCS2 + * string. The caller need to make sure the pOutBuffer size is greater than + * len and the function doesn't add the terminated character at the end of + * the pOutBuffer array. The byte order of UCS2 character(output param) is + * little endian. + * Unlike mmi_asc_n_to_ucs2, it will ignore the controls in ANSII string. + * PARAMETERS + * pOutBuffer : [OUT] UCS2 destination string. + * pInBuffer : [IN] ANSII source string + * len : [IN] size in bytes + * RETURNS + * Return the bytes to convert. + *****************************************************************************/ +extern U16 mmi_asc_n_to_ucs2_ex(CHAR *pOutBuffer, CHAR *pInBuffer, U32 len); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2_to_asc + * DESCRIPTION + * The function is used for convert UCS2 string to ANSII string. + * The caller need to make sure the pOutBuffer size must have enough space + * or the function causes the memory corruption. The function will add the + * terminated character at the end of pOutBuffer array. The byte order of + * UCS2 character(input param) is little endian. + * PARAMETERS + * pOutBuffer : [OUT] The output Buffer. + * pInBuffer : [IN] The input Buffer + * RETURNS + * U16 + *****************************************************************************/ +extern U16 mmi_ucs2_to_asc(CHAR *pOutBuffer, CHAR *pInBuffer); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2_n_to_asc + * DESCRIPTION + * The function is used for convert the characters of UCS2 string to ANSII + * string. The caller need to make sure the pOutBuffer size is greater than + * len and the function doesn't add the terminated character at the end of + * the pOutBuffer array. The byte order of UCS2 character(input param) is little endian. + * PARAMETERS + * pOutBuffer : [OUT] ANSII destination string. + * pInBuffer : [IN] UCS2 source string. + * len : [IN] Length in bytes. + * RETURNS + * U16 + *****************************************************************************/ +extern U16 mmi_ucs2_n_to_asc(CHAR *pOutBuffer, CHAR *pInBuffer, U32 len); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2str + * DESCRIPTION + * Finds the first occurrence of string2 in string1 + * PARAMETERS + * str1 : [IN] string to search in. + * str2 : [IN] string to search for. + * RETURNS + * returns a pointer to the first occurrence of string2 in + * string1, or NULL if string2 does not occur in string1 + *****************************************************************************/ +extern CHAR *mmi_ucs2str(const CHAR *str1, const CHAR *str2); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2chr + * DESCRIPTION + * Searches a UCS2 encoded string for a given wide-character, + * which may be the null character L'\0'. + * PARAMETERS + * strSrc : [IN] UCS2 encoded string to search in. + * c : [IN] UCS2 encoded wide-character to search for. + * RETURNS + * returns pointer to the first occurrence of ch in string + * returns NULL if ch does not occur in string + *****************************************************************************/ +extern CHAR *mmi_ucs2chr(const CHAR *string, WCHAR ch); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2rchr + * DESCRIPTION + * Scan a UCS2 encoded string for the last occurrence of a character. + * PARAMETERS + * string : [IN] UCS2 encoded string to search in. + * ch : [IN] UCS2 encoded wide-character to search for. + * RETURNS + * returns pointer to the last occurrence of ch in string + * returns NULL if ch does not occur in string + *****************************************************************************/ +extern CHAR *mmi_ucs2rchr(const CHAR * string, WCHAR ch); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2upr + * DESCRIPTION + * mmi_ucs2upr converts upper-case characters in a null-terminated + * UCS2 encoded string their upper-case equivalents. + * PARAMETERS + * string : [IN] UCS2 encoded string to change to upper case. + * RETURNS + * returns a pointer to the converted string. Because the modification is + * done in place, the pointer returned is the same as the pointer passed + * as the input argument. + *****************************************************************************/ +extern CHAR *mmi_ucs2upr(CHAR *string); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2lwr + * DESCRIPTION + * mmi_ucs2lwr converts lower-case characters in a null-terminated + * UCS2 encoded string their lower-case equivalents. + * PARAMETERS + * string : [IN] UCS2 encoded string to change to upper case. + * RETURNS + * returns a pointer to the converted string. Because the modification is + * done in place, the pointer returned is the same as the pointer passed + * as the input argument. + *****************************************************************************/ +extern CHAR *mmi_ucs2lwr(CHAR *string); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2icmp + * DESCRIPTION + * mmi_ucs2icmp perform a case-insensitive UCS2 encoded string + * (wide-character) comparison. + * PARAMETERS + * str_src : [IN] UCS2 encoded destination string for + * left-hand side of comparison. + * str_dst : [IN] UCS2 encoded source string for right-hand + * side of comparison. + * RETURNS + * returns -1 if str_src < str_dst + * returns 0 if str_src == str_dst + * returns +1 if str_src > str_dst + *****************************************************************************/ +extern S32 mmi_ucs2icmp(const CHAR *str_src, const CHAR *str_dst); + +/***************************************************************************** + * FUNCTION + * mmi_ucs2nicmp + * DESCRIPTION + * Compares two UCS2 encoded strings for lexical order without regard to case. + * The comparison stops after: + * (1) a difference between the strings is found; + * (2) the end of the strings is reached; + * (3) count characters have been compared. + * PARAMETERS + * str_src : [IN] UCS2 encoded destination string for + * left-hand side of comparison. + * str_dst : [IN] UCS2 encoded source string for right-hand + * side of comparison. + * count : [IN] Number of characters to compare. + * RETURNS + * returns -1 if str_src < str_dst + * returns 0 if str_src == str_dst + * returns +1 if str_src > str_dst + *****************************************************************************/ +extern S32 mmi_ucs2nicmp(const CHAR *str_src, const CHAR *str_dst, U32 count); + +/***************************************************************************** + * FUNCTION + * mmi_tolower + * DESCRIPTION + * Convert character to lowercase. + * PARAMETERS + * c : [IN] Character to convert. + * RETURNS + * return the point to the converted character. + *****************************************************************************/ +extern CHAR* mmi_tolower(CHAR *c); + +/***************************************************************************** + * FUNCTION + * mmi_toupper + * DESCRIPTION + * Convert character to uppercase. + * PARAMETERS + * c : [IN] Character to convert. + * RETURNS + * return the point to the converted character. + *****************************************************************************/ +extern CHAR* mmi_toupper(CHAR *c); +/* DOM-NOT_FOR_SDK-END */ + +/***************************************************************************** + * FUNCTION + * mmi_asc_to_wcs + * DESCRIPTION + * The function is used for convert ANSII string to UCS2 string. The caller + * need to make sure the pOutBuffer size must have enough space or the function + * causes the memory corruption. The function will add the terminated character + * at the end of pOutBuffer array. The byte order of UCS2 character(output param) + * is little endian. + * PARAMETERS + * pOutBuffer : [OUT] UCS2 destination string + * pInBuffer : [IN] ANSII source string + * RETURNS + * Return the bytes to convert. + *****************************************************************************/ +extern U16 mmi_asc_to_wcs(WCHAR *pOutBuffer, CHAR *pInBuffer); + +/***************************************************************************** + * FUNCTION + * mmi_asc_n_to_wcs + * DESCRIPTION + * The function is used for convert the characters of ANSII string to UCS2 + * string. The caller need to make sure the pOutBuffer size is greater than + * len and the function doesn't add the terminated character at the end of + * the pOutBuffer array. The byte order of UCS2 character(output param) is + * little endian. + * PARAMETERS + * pOutBuffer : [OUT] UCS2 destination string. + * pInBuffer : [IN] ANSII source string + * len : [IN] size in bytes + * RETURNS + * Return the bytes to convert. + *****************************************************************************/ +extern U16 mmi_asc_n_to_wcs(WCHAR *pOutBuffer, CHAR *pInBuffer, U32 len); + +/***************************************************************************** + * FUNCTION + * mmi_wcs_to_asc + * DESCRIPTION + * The function is used for convert UCS2 string to ANSII string. + * The caller need to make sure the pOutBuffer size must have enough space + * or the function causes the memory corruption. The function will add the + * terminated character at the end of pOutBuffer array. + * PARAMETERS + * pOutBuffer : [OUT] ANSII destination string + * pInBuffer : [IN] UCS2 source string + * RETURNS + * Return the bytes to convert. + *****************************************************************************/ +extern U16 mmi_wcs_to_asc(CHAR *pOutBuffer, WCHAR *pInBuffer); + +/***************************************************************************** + * FUNCTION + * mmi_wcs_n_to_asc + * DESCRIPTION + * The function is used for convert the characters of UCS2 string to ANSII + * string. The caller need to make sure the pOutBuffer size is greater than + * len and the function doesn't add the terminated character at the end of + * the pOutBuffer array. The byte order of UCS2 character(input param) is + * little endian. + * PARAMETERS + * pOutBuffer : [OUT] ANSII destination string. + * pInBuffer : [IN] UCS2 source string. + * len : [IN] Length in bytes. + * RETURNS + * Return the bytes to convert. + *****************************************************************************/ +extern U16 mmi_wcs_n_to_asc(CHAR *pOutBuffer, WCHAR *pInBuffer, U32 len); + +/* DOM-NOT_FOR_SDK-BEGIN */ +/***************************************************************************** + * FUNCTION + * mmi_asc_to_wcs_ex + * DESCRIPTION + * The function is used for convert ANSII string to UCS2 string. The caller + * need to make sure the dest size must have enough space or the function + * causes the memory corruption. The function will add the terminated character + * at the end of dest array. The byte order of UCS2 character(output param) + * is little endian. + * PARAMETERS + * dest : [OUT] UCS2 destination string. + * src : [IN] ANSII source string. + * src_end_pos : [OUT] The point to the end of converted sub-string at the input string. + * RETURNS + * Return the bytes to convert. + *****************************************************************************/ +extern U16 mmi_asc_to_wcs_ex(WCHAR *dest, CHAR *src, U32 *src_end_pos); + +/***************************************************************************** + * FUNCTION + * mmi_asc_n_to_wcs_ex + * DESCRIPTION + * The function is used for convert the characters of ANSII string to UCS2 + * string. The caller need to make sure the dest size must have enough space + * or the function causes the memory corruption. The function will add the + * terminated character at the end of dest array. The byte order of UCS2 + * character(output param) is little endian. + * PARAMETERS + * dest : [OUT] UCS2 destination string. + * src : [IN] ANSII source string. + * len : [IN] Size in bytes + * src_end_pos : [OUT] The point to the end of converted sub-string at the input string. + * RETURNS + * Return the bytes to convert. + *****************************************************************************/\ +extern U16 mmi_asc_n_to_wcs_ex(WCHAR *dest, CHAR *src, U32 len, U32 *src_end_pos); +/* DOM-NOT_FOR_SDK-END */ + +/***************************************************************************** + * FUNCTION + * mmi_wcslen + * DESCRIPTION + * Gets the number of characters of the given UCS2 encoded string(wide-character), + * not including the final null wide-characters. + * PARAMETERS + * string : [IN] UCS2 encoded string(wide-character) which length is to + * be computed. + * RETURNS + * The number of characters of a wide-character string. + *****************************************************************************/ +extern S32 mmi_wcslen(const WCHAR *string); + +/***************************************************************************** + * FUNCTION + * mmi_wcscmp + * DESCRIPTION + * Compares two UCS2 encoded strings(wide-character) and returns an integer to + * indicate whether the destination string is less than the source string, + * the two are equal, or whether the destination string is greater than the + * source string. + * PARAMETERS + * str_src : [IN] UCS2 encoded destination string(wide-character) for + * left-hand side of comparison. + * str_dst : [IN] UCS2 encoded source string(wide-character) for right-hand + * side of comparison. + * RETURNS + * returns <0 if str_src < str_dst + * returns 0 if str_src == str_dst + * returns >0 if str_src > str_dst + *****************************************************************************/ +extern S32 mmi_wcscmp(const WCHAR *str_src, const WCHAR *str_dst); + +/***************************************************************************** + * FUNCTION + * mmi_wcsncmp + * DESCRIPTION + * Compares two UCS2 encoded strings(wide-character) for lexical order. + * The comparison stops after: + * (1) a difference between the strings is found; + * (2) the end of the strings is reached; + * (3) count characters have been compared (wide-character strings). + * PARAMETERS + * str_src : [IN] UCS2 encoded destination string(wide-character) for + * left-hand side of comparison. + * str_dst : [IN] UCS2 encoded source string(wide-character) for right-hand + * side of comparison. + * count : [IN] Number of characters to compare. + * RETURNS + * returns -1 if str_src < str_dst + * returns 0 if str_src == str_dst + * returns +1 if str_src > str_dst + *****************************************************************************/ +extern S32 mmi_wcsncmp(const WCHAR *str_src, const WCHAR *str_dst, U32 count); + +/***************************************************************************** + * FUNCTION + * mmi_wcscpy + * DESCRIPTION + * Copies the UCS2 encoded source string(wide-character) into the destination + * string; Assumes enough space in the destination string. + * PARAMETERS + * str_dst : [OUT] UCS2 encoded destination string(wide-character) over which + * the source string is to be copied. + * str_src : [IN] UCS2 encoded source string(wide-character) to be copied + * over the destination string. + * RETURNS + * A pointer to the destination string. + *****************************************************************************/ +extern WCHAR *mmi_wcscpy(WCHAR *str_dst, const WCHAR *str_src); + +/***************************************************************************** + * FUNCTION + * mmi_wcsncpy + * DESCRIPTION + * Copies count characters from the source string to the destination string. + * Note: + * Unlike ANSI C standard library function wcsncpy. If count is less than the + * length of source, NULL wide-characters also is put onto the end of the + * copied string. But if count is greater than the length of sources, str_dst + * is not padded with null characters to length count (wide-characters). + * PARAMETERS + * str_dst : [OUT] UCS2 encoded destination string(wide-character) over which + * the source string is to be copied. + * str_src : [IN] UCS2 encoded source string(wide-character) to be copied + * over the destination string. + * count : [IN] max number of characters to copy. + * RETURNS + * A pointer to the destination string. + *****************************************************************************/ +extern WCHAR *mmi_wcsncpy(WCHAR *str_dst, const WCHAR *str_src, U32 count); + +/***************************************************************************** + * FUNCTION + * mmi_wcscat + * DESCRIPTION + * Concatenates the source string onto the end of the destination string. + * Assumes enough space in the destination string. + * PARAMETERS + * str_dst : [OUT] UCS2 encoded destination string(wide-character) over which + * "str_src" is to be copied. + * str_src : [IN] UCS2 encoded source string(wide-character) to be copied + * over "str_dst". + * RETURNS + * A pointer to the destination string. + *****************************************************************************/ +extern WCHAR *mmi_wcscat(WCHAR *str_dst, const WCHAR *str_src); + +/***************************************************************************** + * FUNCTION + * mmi_wcsncat + * DESCRIPTION + * Appends at most count characters of the source string onto the + * end of destination string, and ALWAYS terminates with a null character. + * If count is greater than the length of source string, the length of source + * string is used instead. (Like app_ucs2_wcsncpy, this routine does not pad out + * to count characters). + * PARAMETERS + * str_dst : [OUT] UCS2 encoded destination string(wide-character) to be appended. + * str_src : [IN] UCS2 encoded source string(wide-character) to be appended + * to the end of destination string. + * count : [IN] Number of characters to append. + * RETURNS + * A pointer to the destination string. + *****************************************************************************/ +extern WCHAR *mmi_wcsncat(WCHAR *str_dst, const WCHAR *str_src, U32 count); + +/***************************************************************************** + * FUNCTION + * mmi_wcsstr + * DESCRIPTION + * Find a substring. + * PARAMETERS + * string : [IN] UCS2 encoded string(wide-character) to search. + * str_char_set : [IN] UCS2 encoded string(wide-character) to search for. + * RETURNS + * Returns a pointer to the first occurrence of str_char_set in string, or + * NULL if str_char_set does not appear in string. If str_char_set points to + * a string of zero length, the function returns string. + *****************************************************************************/ +extern WCHAR *mmi_wcsstr(WCHAR *string, const WCHAR *str_char_set); + +/***************************************************************************** + * FUNCTION + * mmi_wcschr + * DESCRIPTION + * Searches a UCS2 encoded string(wide-character) for a given wide-character, + * which may be the null character L'\0'. + * PARAMETERS + * string : [IN] UCS2 encoded string(wide-character) to search in. + * ch : [IN] UCS2 encoded wide-character to search for. + * RETURNS + * returns pointer to the first occurrence of ch in string + * returns NULL if ch does not occur in string + *****************************************************************************/ +extern WCHAR *mmi_wcschr(const WCHAR *string, WCHAR ch); + +/***************************************************************************** + * FUNCTION + * mmi_wcsrchr + * DESCRIPTION + * Scan a UCS2 encoded string(wide-character) for the last occurrence of a + * character. + * PARAMETERS + * string : [IN] UCS2 encoded string(wide-character) to search in. + * ch : [IN] UCS2 encoded wide-character to search for. + * RETURNS + * returns pointer to the last occurrence of ch in string + * returns NULL if ch does not occur in string + *****************************************************************************/ +extern WCHAR *mmi_wcsrchr(const WCHAR * string, WCHAR ch); + +/***************************************************************************** + * FUNCTION + * mmi_wcslwr + * DESCRIPTION + * mmi_wcslwr converts upper-case characters in a null-terminated + * UCS2 encoded string(wide-character) to their lower-case equivalents. + * PARAMETERS + * string : [IN] UCS2 encoded string(wide-character) to change to lower + * case. + * RETURNS + * returns a pointer to the converted string. Because the modification is + * done in place, the pointer returned is the same as the pointer passed + * as the input argument. + *****************************************************************************/ +extern WCHAR *mmi_wcslwr(WCHAR *string); + +/***************************************************************************** + * FUNCTION + * mmi_wcslwr + * DESCRIPTION + * mmi_wcslwr converts upper-case characters in a null-terminated + * UCS2 encoded string(wide-character) to their lower-case equivalents. + * PARAMETERS + * string : [IN] UCS2 encoded string(wide-character) to change to lower + * case. + * RETURNS + * returns a pointer to the converted string. Because the modification is + * done in place, the pointer returned is the same as the pointer passed + * as the input argument. + *****************************************************************************/ +extern WCHAR *mmi_wcsupr(WCHAR *string); + +/***************************************************************************** + * FUNCTION + * mmi_wcsicmp + * DESCRIPTION + * mmi_wcsicmp perform a case-insensitive wchar_t UCS2 encoded + * string(wide-character) comparison. + * PARAMETERS + * str_src : [IN] UCS2 encoded destination string(wide-character) for + * left-hand side of comparison. + * str_dst : [IN] UCS2 encoded source string(wide-character) for right-hand + * side of comparison. + * RETURNS + * returns <0 if str_src < str_dst + * returns 0 if str_src == str_dst + * returns >0 if str_src > str_dst + *****************************************************************************/ +extern S32 mmi_wcsicmp(const WCHAR *str_src, const WCHAR *str_dst); + +/***************************************************************************** + * FUNCTION + * mmi_wcsnicmp + * DESCRIPTION + * Compares two UCS2 encoded strings(wide-character) for lexical order + * without regard to case. + * The comparison stops after: + * (1) a difference between the strings is found; + * (2) the end of the strings is reached; + * (3) count characters have been compared (wide-character strings). + * PARAMETERS + * str_src : [IN] UCS2 encoded destination string(wide-character) for + * left-hand side of comparison. + * str_dst : [IN] UCS2 encoded source string(wide-character) for right-hand + * side of comparison. + * count : [IN] Number of characters to compare. + * RETURNS + * returns -1 if str_src < str_dst + * returns 0 if str_src == str_dst + * returns +1 if str_src > str_dst + *****************************************************************************/ +extern S32 mmi_wcsnicmp(const WCHAR *str_src, const WCHAR *str_dst, U32 count); + +/***************************************************************************** + * FUNCTION + * mmi_towlower + * DESCRIPTION + * Convert character to lowercase. + * PARAMETERS + * wc : [IN] Character to convert. + * RETURNS + * Each of these routines converts a copy of wc, if possible, and returns the + * result. + ****************************************************************************/ +extern WCHAR mmi_towlower(WCHAR wc); + +/***************************************************************************** + * FUNCTION + * mmi_towupper + * DESCRIPTION + * Convert character to uppercase. + * PARAMETERS + * wc : [IN] Character to convert. + * RETURNS + * Each of these routines converts a copy of wc, if possible, and returns the + * result. + *****************************************************************************/ +extern WCHAR mmi_towupper(WCHAR wc); + +/***************************************************************************** + * FUNCTION + * mmi_wcs_wtoi + * DESCRIPTION + * Convert string to integer. + * PARAMETERS + * pInbuf : [IN] input string + * RETURNS + * returns a pointer to string. + *****************************************************************************/ +extern S32 mmi_wcs_wtoi(WCHAR *pInbuf); + +/***************************************************************************** + * FUNCTION + * mmi_wcs_itow + * DESCRIPTION + * Convert an integer to a string. + * PARAMETERS + * value : [IN] Number to be converted. + * pOutbuf : [OUT] String result. + * radix : [IN] Base of value; must be in the range 2 C 36. + * RETURNS + * returns a pointer to string. + *****************************************************************************/ +extern WCHAR *mmi_wcs_itow(S32 value, WCHAR *pOutbuf, U32 radix); + +#endif /* _UNICODEXDCL_H_ */ diff --git a/inc/C_H/alloca.h b/inc/C_H/alloca.h new file mode 100644 index 0000000..ca28b3d --- /dev/null +++ b/inc/C_H/alloca.h @@ -0,0 +1,74 @@ +/* alloca.h: Stack based allocation */ +/* Copyright 1999 ARM Limited. All rights reserved */ + +/* + * RCS $Revision: 1.5.2.2 $ + * Checkin $Date: 2001/05/23 21:56:07 $ + * Revising $Author: sdouglas $ + */ + +#ifndef __alloca_h +#define __alloca_h + + #ifndef __ALLOCA_DECLS + #define __ALLOCA_DECLS + + #undef __CLIBNS + + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) + /* unconditional in C++ and non-strict C for consistency of debug info */ + typedef unsigned int size_t; +#elif !defined(__size_t) + #define __size_t 1 + typedef unsigned int size_t; /* see */ +#endif + +#undef NULL +#define NULL 0 /* see */ + +typedef struct { + void *__chunk; + int __pos; +} __alloca_state; + +#define alloca(n) __CLIBNS __alloca(n) + +void *__alloca(size_t /* size */); + +/* Allocate a block of at least size bytes. Returns a pointer to the first + * word, or NULL if the allocation isn't successful. + * Deallocation of all blocks allocated in a function is done on return. + * Alloca can not be used as a function pointer. + */ + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __ALLOCA_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __ALLOCA_NO_EXPORTS + using std::__alloca_state; + using std::__alloca; + #endif + #endif +#endif + +/* end of alloca.h */ diff --git a/inc/C_H/armdsp.h b/inc/C_H/armdsp.h new file mode 100644 index 0000000..eb00729 --- /dev/null +++ b/inc/C_H/armdsp.h @@ -0,0 +1,286 @@ +/* armdsp.h + * + * Copyright 2001 ARM Limited. All rights reserved. + * + * RCS $Revision: 1.1.2.2 $ + * Checkin $Date: 2001/07/31 16:10:40 $ + * Revising $Author: statham $ + */ + +/* ---------------------------------------------------------------------- + * This header file provides a set of DSP-type primitive + * operations, such as saturating integer arithmetic and 16x16 bit + * multiplication. The operations it provides are exactly the same + * operations supported directly by the ARM9E. + * + * This header file is intended as an example implementation. It + * demonstrates how to use the inline assembly feature in the ARM + * compilers, to construct intrinsic functions that provide + * C-language access to the ARM9E's DSP capability. + */ + +#ifndef ARMDSP_ARMDSP_H +#define ARMDSP_ARMDSP_H + +#ifndef ARMDSP_WORD32_DEFINED +#define ARMDSP_WORD32_DEFINED +typedef signed int Word32; +typedef signed short Word16; +#define ARMDSP_WORD32_MAX ((Word32)0x7FFFFFFF) +#define ARMDSP_WORD32_MIN ((Word32)-0x80000000) +#define ARMDSP_WORD16_MAX ((Word16)0x7FFF) +#define ARMDSP_WORD16_MIN ((Word16)-0x8000) +#endif + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/* + * Saturating 32-bit integer addition. + */ +__inline Word32 qadd(Word32 x, Word32 y) +{ + Word32 ret; + __asm { + qadd ret, x, y; + } + return ret; +} + +/* + * Saturating 32-bit integer subtraction. + */ +__inline Word32 qsub(Word32 x, Word32 y) +{ + Word32 ret; + __asm { + qsub ret, x, y; + } + return ret; +} + +/* + * Saturating 32-bit integer addition, with the second operand + * multiplied by two. (i.e. return x + 2 * y) + */ +__inline Word32 qdadd(Word32 x, Word32 y) +{ + Word32 ret; + __asm { + qdadd ret, x, y; + } + return ret; +} + +/* + * Saturating 32-bit integer subtraction, with the second operand + * multiplied by two. (i.e. return x - 2 * y) + */ +__inline Word32 qdsub(Word32 x, Word32 y) +{ + Word32 ret; + __asm { + qdsub ret, x, y; + } + return ret; +} + +/* + * Multiply two signed 16-bit numbers, taken from the bottom or top + * halves of the input words. For example, smulbt(x,y) multiplies + * the bottom 16 bits of x with the top 16 bits of y. + */ + +/* smulbb - multiply bottom half of x and bottom half of y */ +__inline Word32 smulbb(Word32 x, Word32 y) +{ + Word32 ret; + __asm { + smulbb ret, x, y; + } + return ret; +} + +/* smulbt - multiply bottom half of x and top half of y */ +__inline Word32 smulbt(Word32 x, Word32 y) +{ + Word32 ret; + __asm { + smulbt ret, x, y; + } + return ret; +} + +/* smultb - multiply top half of x and bottom half of y */ +__inline Word32 smultb(Word32 x, Word32 y) +{ + Word32 ret; + __asm { + smultb ret, x, y; + } + return ret; +} + +/* smultt - multiply top half of x and top half of y */ +__inline Word32 smultt(Word32 x, Word32 y) +{ + Word32 ret; + __asm { + smultt ret, x, y; + } + return ret; +} + +/* + * Multiply two signed 16-bit numbers, taken from the bottom or top + * halves of the input words x and y, and add to the input word a. + * For example, smlabt(x,y,a) multiplies the bottom 16 bits of x with + * the top 16 bits of y, and then adds a. + */ + +/* smlabb - multiply bottom half of x and bottom half of y */ +__inline Word32 smlabb(Word32 x, Word32 y, Word32 a) +{ + Word32 ret; + __asm { + smlabb ret, x, y, a; + } + return ret; +} + +/* smlabt - multiply bottom half of x and top half of y */ +__inline Word32 smlabt(Word32 x, Word32 y, Word32 a) +{ + Word32 ret; + __asm { + smlabt ret, x, y, a; + } + return ret; +} + +/* smlatb - multiply top half of x and bottom half of y */ +__inline Word32 smlatb(Word32 x, Word32 y, Word32 a) +{ + Word32 ret; + __asm { + smlatb ret, x, y, a; + } + return ret; +} + +/* smlatt - multiply top half of x and top half of y */ +__inline Word32 smlatt(Word32 x, Word32 y, Word32 a) +{ + Word32 ret; + __asm { + smlatt ret, x, y, a; + } + return ret; +} + +/* + * Multiply two signed 16-bit numbers, taken from the bottom or top + * halves of the input words x and y, and add to the 64-bit integer + * stored in the input words lo and hi. For example, + * smlalbt(&lo,&hi,x,y) multiplies the bottom 16 bits of x with the + * top 16 bits of y, and then adds the result to (hi,lo). + * + * WARNING: if you use these primitives too often inside the same + * function, they may fail to be inlined. + */ + +/* smlalbb - multiply bottom half of x and bottom half of y */ +__inline void smlalbb(Word32 *lo, Word32 *hi, Word32 x, Word32 y) +{ + __asm { + smlalbb *lo, *hi, x, y; + } +} + +/* smlalbt - multiply bottom half of x and top half of y */ +__inline void smlalbt(Word32 *lo, Word32 *hi, Word32 x, Word32 y) +{ + __asm { + smlalbt *lo, *hi, x, y; + } +} + +/* smlaltb - multiply top half of x and bottom half of y */ +__inline void smlaltb(Word32 *lo, Word32 *hi, Word32 x, Word32 y) +{ + __asm { + smlaltb *lo, *hi, x, y; + } +} + +/* smlaltt - multiply top half of x and top half of y */ +__inline void smlaltt(Word32 *lo, Word32 *hi, Word32 x, Word32 y) +{ + __asm { + smlaltt *lo, *hi, x, y; + } +} + +/* + * Multiply a 32-bit signed integer (the input word x) with a + * 16-bit signed integer (taken from either the top or the bottom + * half of the input word y). Discard the bottom 16 bits of the + * 48-bit product. + */ + +/* smulwb - multiply x by the bottom half of y */ +__inline Word32 smulwb(Word32 x, Word32 y) +{ + Word32 ret; + __asm { + smulwb ret, x, y; + } + return ret; +} + +/* smulwt - multiply x by the top half of y */ +__inline Word32 smulwt(Word32 x, Word32 y) +{ + Word32 ret; + __asm { + smulwt ret, x, y; + } + return ret; +} + +/* + * Multiply a 32-bit signed integer (the input word x) with a + * 16-bit signed integer (taken from either the top or the bottom + * half of the input word y). Discard the bottom 16 bits of the + * 48-bit product, and add to the input word a. + */ + +/* smlawb - multiply x by the bottom half of y */ +__inline Word32 smlawb(Word32 x, Word32 y, Word32 a) +{ + Word32 ret; + __asm { + smlawb ret, x, y, a; + } + return ret; +} + +/* smlawt - multiply x by the top half of y */ +__inline Word32 smlawt(Word32 x, Word32 y, Word32 a) +{ + Word32 ret; + __asm { + smlawt ret, x, y, a; + } + return ret; +} + +#ifdef __cplusplus +} +#endif + +#endif /* ARMDSP_ARMDSP_H */ diff --git a/inc/C_H/assert.h b/inc/C_H/assert.h new file mode 100644 index 0000000..6ad0c3b --- /dev/null +++ b/inc/C_H/assert.h @@ -0,0 +1,49 @@ +/* assert.h: ANSI 'C' (X3J11 Oct 88) library header section 4.2 */ +/* Copyright (C) Codemist Ltd., 1988-1993 */ +/* Copyright 1991-1993 ARM Limited. All rights reserved. */ +/* version 0.04 */ + +/* + * RCS $Revision: 1.6 $ + * Checkin $Date: 2000/11/08 15:43:30 $ + * Revising $Author: statham $ + */ + +/* + * The assert macro puts diagnostics into programs. When it is executed, + * if its argument expression is false, it writes information about the + * call that failed (including the text of the argument, the name of the + * source file, and the source line number - the latter are respectively + * the values of the preprocessing macros __FILE__ and __LINE__) on the + * standard error stream. It then calls the abort function. + * If its argument expression is true, the assert macro returns no value. + */ + +/* + * Note that may be included more that once in a program with + * different setting of NDEBUG. Hence the slightly unusual first-time + * only flag. + */ + +#ifndef __assert_h +# define __assert_h +# ifdef __cplusplus + extern "C" void __assert(const char *, const char *, int); +# else + extern void __assert(const char *, const char *, int); +# endif +#else +# undef assert +#endif + +#ifdef NDEBUG +# define assert(ignore) ((void)0) +#else +# ifdef __STDC__ +# define assert(e) ((e) ? (void)0 : __assert(#e, __FILE__, __LINE__)) +# else +# define assert(e) ((e) ? (void)0 : __assert("e", __FILE__, __LINE__)) +# endif +#endif + +/* end of assert.h */ diff --git a/inc/C_H/compnent.h b/inc/C_H/compnent.h new file mode 100644 index 0000000..cc97878 --- /dev/null +++ b/inc/C_H/compnent.h @@ -0,0 +1,49 @@ +#ifndef __COMPNENT_H +#define __COMPNENT_H + +/*************************************************************************** + * + * compnent.h - #defines for all unfinished or broken components + * + * $Id: compnent.h,v 1.38 1996/08/28 01:28:29 smithey Exp $ + * + *************************************************************************** + * + * Copyright (c) 1994-1999 Rogue Wave Software, Inc. All Rights Reserved. + * + * This computer software is owned by Rogue Wave Software, Inc. and is + * protected by U.S. copyright laws and other laws and by international + * treaties. This computer software is furnished by Rogue Wave Software, + * Inc. pursuant to a written license agreement and may be used, copied, + * transmitted, and stored only in accordance with the terms of such + * license and with the inclusion of the above copyright notice. This + * computer software or any other copies thereof may not be provided or + * otherwise made available to any other person. + * + * U.S. Government Restricted Rights. This computer software is provided + * with Restricted Rights. Use, duplication, or disclosure by the + * Government is subject to restrictions as set forth in subparagraph (c) + * (1) (ii) of The Rights in Technical Data and Computer Software clause + * at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the + * Commercial Computer Software Restricted Rights at 48 CFR 52.227-19, + * as applicable. Manufacturer is Rogue Wave Software, Inc., 5500 + * Flatiron Parkway, Boulder, Colorado 80301 USA. + * + **************************************************************************/ + +#ifndef _RW_OLD_IOSTREAM +# define _RW_STD_LOCALE 1 +# define _RW_STD_IOSTREAM 1 +#endif +#define _RW_STD_STL 1 +#define _RW_STD_STRING 1 +#define _RW_STD_COMPLEX 1 +#define _RW_STD_BITSET 1 +#define _RW_STD_EXCEPT 1 +#define _RW_STD_VALARRAY 1 +#define _RW_STD_LIMITS 1 + +#define _RW_NO_SIGNED_OVERLOAD 1 + +#endif + diff --git a/inc/C_H/ctype.h b/inc/C_H/ctype.h new file mode 100644 index 0000000..4052259 --- /dev/null +++ b/inc/C_H/ctype.h @@ -0,0 +1,195 @@ +/* ctype.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.3 */ +/* Copyright (C) Codemist Ltd. 1988-1993. */ +/* Copyright 1991-1993 ARM Limited. All rights reserved. */ +/* version 0.03 */ + +/* + * RCS $Revision: 1.10.2.2 $ + * Checkin $Date: 2001/05/23 21:56:07 $ + * Revising $Author: sdouglas $ + */ + +/* + * ctype.h declares several functions useful for testing and mapping + * characters. In all cases the argument is an int, the value of which shall + * be representable as an unsigned char or shall equal the value of the + * macro EOF. If the argument has any other value, the behaviour is undefined. + */ + +#ifndef __ctype_h +#define __ctype_h + + #ifndef __CTYPE_DECLS + #define __CTYPE_DECLS + + #undef __CLIBNS + + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + +/* N.B. - keep in step with */ + +#define __S 1 /* whitespace */ +#define __P 2 /* punctuation */ +#define __B 4 /* blank */ +#define __L 8 /* lower case letter */ +#define __U 16 /* upper case letter */ +#define __N 32 /* (decimal) digit */ +#define __C 64 /* control chars */ +#define __X 128 /* A-F and a-f */ + +extern __pure unsigned char **__rt_ctype_table(void); + +#define __ctype (*__CLIBNS __rt_ctype_table()) + +#ifdef __cplusplus + inline int isalnum(int __c) { return (__ctype[__c] & (__U+__L+__N)); } +#else + #define isalnum(c) (__ctype[c] & (__U+__L+__N)) + extern int (isalnum)(int /*c*/); +#endif + /* non-0 iff c is alphabetic or numeric */ + +#ifdef __cplusplus + inline int isalpha(int __c) { return (__ctype[__c] & (__U+__L)); } +#else + #define isalpha(c) (__ctype[c] & (__U+__L)) + extern int (isalpha)(int /*c*/); +#endif + /* non-0 iff c is alphabetic */ + +#ifdef __cplusplus + inline int iscntrl(int __c) { return (__ctype[__c] & __C); } +#else + #define iscntrl(c) (__ctype[c] & __C) + extern int (iscntrl)(int /*c*/); +#endif + /* non-0 iff c is a control character - in the ASCII locale */ + /* this means (c < ' ') || (c > '~') */ + +#ifdef __cplusplus + inline int isdigit(int __c) { return (__ctype[__c] & __N); } +#else + #define isdigit(c) (__ctype[c] & __N) + extern int (isdigit)(int /*c*/); +#endif + /* non-0 iff c is a decimal digit */ + +#ifdef __cplusplus + inline int isgraph(int __c) { return (__ctype[__c] & (__L+__U+__N+__P)); } +#else + #define isgraph(c) (__ctype[c] & (__L+__U+__N+__P)) + extern int (isgraph)(int /*c*/); +#endif + /* non-0 iff c is any printing character other than ' ' */ + +#ifdef __cplusplus + inline int islower(int __c) { return (__ctype[__c] & __L); } +#else + #define islower(c) (__ctype[c] & __L) + extern int (islower)(int /*c*/); +#endif + /* non-0 iff c is a lower-case letter */ + +#ifdef __cplusplus + inline int isprint(int __c) { return (__ctype[__c] & (__L+__U+__N+__P+__B)); } +#else + #define isprint(c) (__ctype[c] & (__L+__U+__N+__P+__B)) + extern int (isprint)(int /*c*/); +#endif + /* non-0 iff c is a printing character - in the ASCII locale */ + /* this means 0x20 (space) -> 0x7E (tilde) */ + +#ifdef __cplusplus + inline int ispunct(int __c) { return (__ctype[__c] & __P); } +#else + #define ispunct(c) (__ctype[c] & __P) + extern int (ispunct)(int /*c*/); +#endif + /* non-0 iff c is a non-space, non-alpha-numeric, printing character */ + +#ifdef __cplusplus + inline int isspace(int __c) { return (__ctype[__c] & __S); } +#else + #define isspace(c) (__ctype[c] & __S) + extern int (isspace)(int /*c*/); +#endif + /* non-0 iff c is a white-space char: ' ', '\f', '\n', '\r', '\t', '\v'. */ + +#ifdef __cplusplus + inline int isupper(int __c) { return (__ctype[__c] & __U); } +#else + #define isupper(c) (__ctype[c] & __U) + extern int (isupper)(int /*c*/); +#endif + /* non-0 iff c is an upper-case letter */ + +#ifdef __cplusplus + inline int isxdigit(int __c) { return (__ctype[__c] & (__N+__X)); } +#else + #define isxdigit(c) (__ctype[c] & (__N+__X)) + extern int (isxdigit)(int /*c*/); +#endif + /* non-0 iff c is a digit, in 'a'..'f', or in 'A'..'F' */ + +extern int tolower(int /*c*/); + /* if c is an upper-case letter then return the corresponding */ + /* lower-case letter, otherwise return c. */ + +extern int toupper(int /*c*/); + /* if c is an lower-case letter then return the corresponding */ + /* upper-case letter, otherwise return c. */ + +extern void __use_iso8859_locale(void); +extern void __use_iso8859_ctype(void); +extern void __use_iso8859_collate(void); +extern void __use_iso8859_monetary(void); +extern void __use_iso8859_numeric(void); + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __CTYPE_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __CTYPE_NO_EXPORTS + using std::isalnum; + using std::isalpha; + using std::iscntrl; + using std::isdigit; + using std::isgraph; + using std::islower; + using std::isprint; + using std::ispunct; + using std::isspace; + using std::isupper; + using std::isxdigit; + using std::tolower; + using std::toupper; + using std::__use_iso8859_locale; + using std::__use_iso8859_ctype; + using std::__use_iso8859_collate; + using std::__use_iso8859_monetary; + using std::__use_iso8859_numeric; + #endif + #endif + +#endif + +/* end of ctype.h */ + + diff --git a/inc/C_H/dspfns.h b/inc/C_H/dspfns.h new file mode 100644 index 0000000..0536541 --- /dev/null +++ b/inc/C_H/dspfns.h @@ -0,0 +1,618 @@ +/* dspfns.h + * + * Copyright 2001 ARM Limited. All rights reserved. + * + * RCS $Revision: 1.1.2.2 $ + * Checkin $Date: 2001/07/31 16:10:40 $ + * Revising $Author: statham $ + */ + +/* ---------------------------------------------------------------------- + * This header file provides a set of DSP-type primitive + * operations, such as 16-bit and 32-bit saturating arithmetic. The + * operations it provides are similar to the ones used by the ITU + * for publishing specifications of DSP algorithms. + * + * This header file is intended as an example implementation. It + * demonstrates how to use the inline assembly feature in the ARM + * compilers, to construct intrinsic functions that provide + * C-language access to the ARM9E's DSP capability. + * + * This header file is NOT SUFFICIENT to be used alone - you need + * to include "dspfns.c" from the examples\dsp directory as well. + */ + +#ifndef ARMDSP_DSPFNS_H +#define ARMDSP_DSPFNS_H + +#include + +#ifndef ARMDSP_WORD32_DEFINED +#define ARMDSP_WORD32_DEFINED +typedef signed int Word32; +typedef signed short Word16; +#define ARMDSP_WORD32_MAX ((Word32)0x7FFFFFFF) +#define ARMDSP_WORD32_MIN ((Word32)-0x80000000) +#define ARMDSP_WORD16_MAX ((Word16)0x7FFF) +#define ARMDSP_WORD16_MIN ((Word16)-0x8000) +#endif + +typedef int Flag; + +/* + * This global variable needs to exist somewhere in the compiled + * program in order for the flag-using functions to work. You can + * either include the declaration + * + * armdsp_flagdata_union armdsp_flagdata; + * + * in at least one of your source files (that includes this + * header), or compile in "dspfns.c" from the examples\dsp + * directory. + */ +typedef union { + unsigned int armdsp_flags_word; + struct { +#ifdef __BIG_ENDIAN + Flag armdsp_n:1, armdsp_z:1, armdsp_c:1, armdsp_v:1, armdsp_q:1, armdsp_unused:27; +#else + Flag armdsp_unused:27, armdsp_q:1, armdsp_v:1, armdsp_c:1, armdsp_z:1, armdsp_n:1; +#endif + } armdsp_bitfields; +} armdsp_flagdata_union; +extern armdsp_flagdata_union armdsp_flagdata; + +#define Carry ( armdsp_flagdata.armdsp_bitfields.armdsp_c ) +#define Overflow ( armdsp_flagdata.armdsp_bitfields.armdsp_q ) + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +/* + * Convert a 32-bit signed integer into a 16-bit signed integer by + * saturation. + */ +__inline Word16 saturate(Word32 x) +{ + if (x > ARMDSP_WORD16_MAX) + Overflow = 1, x = ARMDSP_WORD16_MAX; + else if (x < ARMDSP_WORD16_MIN) + Overflow = 1, x = ARMDSP_WORD16_MIN; + return (Word16) x; +} + +/* + * Add two 16-bit signed integers with saturation. + */ +__inline Word16 add(Word16 x, Word16 y) +{ + Word32 xs, ys, rs; + __asm { + mov xs, x, lsl #16; + mov ys, y, lsl #16; + qadd rs, xs, ys; + } + return (Word16) (rs >> 16); +} + +/* + * Subtract one 16-bit signed integer from another with saturation. + */ +__inline Word16 sub(Word16 x, Word16 y) +{ + Word32 xs, ys, rs; + __asm { + mov xs, x, lsl #16; + mov ys, y, lsl #16; + qsub rs, xs, ys; + } + return (Word16) (rs >> 16); +} + +/* + * Absolute value of a 16-bit signed integer. Saturating, so + * abs(-0x8000) becomes +0x7FFF. + */ +__inline Word16 abs_s(Word16 x) +{ + if (x >= 0) + return x; + else if (x == ARMDSP_WORD16_MIN) + return ARMDSP_WORD16_MAX; + else + return (Word16) -x; +} + +/* + * Shift a 16-bit signed integer left (or right, if the shift count + * is negative). Saturate on overflow. + */ +__inline Word16 shl(Word16 x, Word16 shift) +{ + if (shift <= 0 || x == 0) + return (Word16) (x >> (-shift)); + if (shift > 15) + shift = 16; + return saturate(x << shift); +} + +/* + * Shift a 16-bit signed integer right (or left, if the shift count + * is negative). Saturate on overflow. + */ +__inline Word16 shr(Word16 x, Word16 shift) +{ + if (shift >= 0 || x == 0) + return (Word16) (x >> shift); + if (shift < -15) + shift = -16; + return saturate(x << (-shift)); +} + +/* + * Multiply two 16-bit signed integers, shift the result right by + * 15 and saturate it. (Saturation is only necessary if both inputs + * were -0x8000, in which case the result "should" be 0x8000 and is + * saturated to 0x7FFF.) + */ +__inline Word16 mult(Word16 x, Word16 y) +{ + Word32 product; + __asm { + smulbb product, x, y; + qadd product, product, product; + } + return (Word16) (product >> 16); /* the qadd added one to the 15 */ +} + +/* + * Multiply two 16-bit signed integers to give a 32-bit signed + * integer. Shift left by one, and saturate the result. (Saturation + * is only necessary if both inputs were -0x8000, in which case the + * result "should" be 0x40000000 << 1 = +0x80000000, and is + * saturated to +0x7FFFFFFF.) + */ +__inline Word32 L_mult(Word16 x, Word16 y) +{ + Word32 product; + __asm { + smulbb product, x, y; + qadd product, product, product; + } + return product; +} + +/* + * Negate a 16-bit signed integer, with saturation. (Saturation is + * only necessary when the input is -0x8000.) + */ +__inline Word16 negate(Word16 x) +{ + if (x == ARMDSP_WORD16_MIN) + return ARMDSP_WORD16_MAX; + return (Word16) -x; +} + +/* + * Return the top 16 bits of a 32-bit signed integer. + */ +__inline Word16 extract_h(Word32 x) +{ + return (Word16) (x >> 16); +} + +/* + * Return the bottom 16 bits of a 32-bit signed integer, with no + * saturation, just coerced into a two's complement 16 bit + * representation. + */ +__inline Word16 extract_l(Word32 x) +{ + return (Word16) x; +} + +/* + * Divide a 32-bit signed integer by 2^16, rounding to the nearest + * integer (round up on a tie). Equivalent to adding 0x8000 with + * saturation, then shifting right by 16. + */ +__inline Word16 round(Word32 x) +{ + __asm { + qadd x, x, 0x8000; + } + return extract_h(x); +} + +/* + * Multiply two 16-bit signed integers together to give a 32-bit + * signed integer, shift left by one with saturation, and add to + * another 32-bit integer with saturation. + * + * Note the intermediate saturation operation in the definition: + * + * L_mac(-1, -0x8000, -0x8000) + * + * will give 0x7FFFFFFE and not 0x7FFFFFFF: + * the unshifted product is: 0x40000000 + * shift left with saturation: 0x7FFFFFFF + * add to -1 with saturation: 0x7FFFFFFE + */ +__inline Word32 L_mac(Word32 accumulator, Word16 x, Word16 y) +{ + Word32 product; + __asm { + smulbb product, x, y; + qdadd accumulator, accumulator, product; + } + return accumulator; +} + +/* + * Multiply two 16-bit signed integers together to give a 32-bit + * signed integer, shift left by one with saturation, and subtract + * from another 32-bit integer with saturation. + * + * Note the intermediate saturation operation in the definition: + * + * L_msu(1, -0x8000, -0x8000) + * + * will give 0x80000002 and not 0x80000001: + * the unshifted product is: 0x40000000 + * shift left with saturation: 0x7FFFFFFF + * subtract from 1 with saturation: 0x80000002 + */ +__inline Word32 L_msu(Word32 accumulator, Word16 x, Word16 y) +{ + Word32 product; + __asm { + smulbb product, x, y; + qdsub accumulator, accumulator, product; + } + return accumulator; +} + +/* + * Add two 32-bit signed integers with saturation. + */ +__inline Word32 L_add(Word32 x, Word32 y) +{ + Word32 result; + __asm { + qadd result, x, y; + } + return result; +} + +/* + * Subtract one 32-bit signed integer from another with saturation. + */ +__inline Word32 L_sub(Word32 x, Word32 y) +{ + Word32 result; + __asm { + qsub result, x, y; + } + return result; +} + +/* + * Add together the Carry variable and two 32-bit signed integers, + * without saturation. + */ +__inline Word32 L_add_c(Word32 x, Word32 y) +{ + Word32 result, flags; + + __asm { + msr CPSR_f, armdsp_flagdata.armdsp_flags_word; + adcs result, x, y; + mrs flags, CPSR; + orrvs flags, flags, #0x08000000; // set Q if V is set + mov armdsp_flagdata.armdsp_flags_word, flags; + } + return result; +} + +/* + * Subtract one 32-bit signed integer, together with the Carry + * variable, from another 32-bit signed integer, without + * saturation. + */ +__inline Word32 L_sub_c(Word32 x, Word32 y) +{ + Word32 result, flags; + + __asm { + msr CPSR_f, armdsp_flagdata.armdsp_flags_word; + sbcs result, x, y; + mrs flags, CPSR; + orrvs flags, flags, #0x08000000; // set Q if V is set + mov armdsp_flagdata.armdsp_flags_word, flags; + } + return result; +} + +/* + * Multiply two 16-bit signed integers together to give a 32-bit + * signed integer, shift left by one _with_ saturation, and add + * with carry to another 32-bit integer _without_ saturation. + */ +__inline Word32 L_macNs(Word32 accumulator, Word16 x, Word16 y) +{ + return L_add_c(accumulator, L_mult(x, y)); +} + +/* + * Multiply two 16-bit signed integers together to give a 32-bit + * signed integer, shift left by one _with_ saturation, and + * subtract with carry from another 32-bit integer _without_ + * saturation. + */ +__inline Word32 L_msuNs(Word32 accumulator, Word16 x, Word16 y) +{ + return L_sub_c(accumulator, L_mult(x, y)); +} + +/* + * Negate a 32-bit signed integer, with saturation. (Saturation is + * only necessary when the input is -0x80000000.) + */ +__inline Word32 L_negate(Word32 x) +{ + if (x == ARMDSP_WORD32_MIN) + return ARMDSP_WORD32_MAX; + return -x; +} + +/* + * Multiply two 16-bit signed integers, shift the result right by + * 15 with rounding, and saturate it. (Saturation is only necessary + * if both inputs were -0x8000, in which case the result "should" + * be 0x8000 and is saturated to 0x7FFF.) + */ +__inline Word16 mult_r(Word16 x, Word16 y) +{ + Word32 product; + __asm { + smulbb product, x, y; + qdadd product, 0x8000, product; + } + return (Word16) (product >> 16); /* qdadd adds one to the 15 */ +} + +/* + * Shift a 32-bit signed integer left (or right, if the shift count + * is negative). Saturate on overflow. + */ +__inline Word32 L_shl(Word32 x, Word16 shift) +{ + int lz; + int absx; + if (shift <= 0) + return x >> (-shift); + absx = (x < 0 ? -x : x); + __asm { + clz lz, absx; + } + if (shift < lz || x == 0) + return x << shift; + if (x < 0) + return ARMDSP_WORD32_MIN; + else + return ARMDSP_WORD32_MAX; +} + +/* + * Shift a 32-bit signed integer right (or left, if the shift count + * is negative). Saturate on overflow. + */ +__inline Word32 L_shr(Word32 x, Word16 shift) +{ + int lz; + int absx; + if (shift >= 0) + return x >> shift; + absx = (x < 0 ? -x : x); + __asm { + clz lz, absx; + } + if (-shift < lz || x == 0) + return x << (-shift); + if (x < 0) + return ARMDSP_WORD32_MIN; + else + return ARMDSP_WORD32_MAX; +} + +/* + * Shift a 16-bit signed integer right, with rounding. Shift left + * with saturation if the shift count is negative. + */ +__inline Word16 shr_r(Word16 x, Word16 shift) +{ + if (shift == 0 || x == 0) + return (Word16) (x >> shift); + if (shift > 0) + return (Word16) (((x >> (shift-1)) + 1) >> 1); + if (shift < -15) + shift = -16; + return saturate(x << (-shift)); +} + +/* + * Multiply two 16-bit signed integers together to give a 32-bit + * signed integer, shift left by one with saturation, and add to + * another 32-bit integer with saturation (like L_mac). Then shift + * the result right by 15 bits with rounding (like round). + */ +__inline Word16 mac_r(Word32 accumulator, Word16 x, Word16 y) +{ + return round(L_mac(accumulator, x, y)); +} + +/* + * Multiply two 16-bit signed integers together to give a 32-bit + * signed integer, shift left by one with saturation, and subtract + * from another 32-bit integer with saturation (like L_msu). Then + * shift the result right by 15 bits with rounding (like round). + */ +__inline Word16 msu_r(Word32 accumulator, Word16 x, Word16 y) +{ + return round(L_msu(accumulator, x, y)); +} + +/* + * Shift a 16-bit signed integer left by 16 bits to generate a + * 32-bit signed integer. The bottom 16 bits are zeroed. + */ +__inline Word32 L_deposit_h(Word16 x) +{ + return ((Word32)x) << 16; +} + +/* + * Sign-extend a 16-bit signed integer by 16 bits to generate a + * 32-bit signed integer. + */ +__inline Word32 L_deposit_l(Word16 x) +{ + return (Word32)x; +} + +/* + * Shift a 32-bit signed integer right, with rounding. Shift left + * with saturation if the shift count is negative. + */ +__inline Word32 L_shr_r(Word32 x, Word16 shift) +{ + int lz; + int absx; + if (shift == 0 || x == 0) + return x >> shift; + if (shift > 0) { + Word32 x2 = x >> (shift-1); + return (x2 >> 1) + (x2 & 1); + } + absx = (x < 0 ? -x : x); + __asm { + clz lz, absx; + } + if (-shift < lz || x == 0) + return x << (-shift); + if (x < 0) + return ARMDSP_WORD32_MIN; + else + return ARMDSP_WORD32_MAX; +} + +/* + * Absolute value of a 32-bit signed integer. Saturating, so + * abs(-0x80000000) becomes +0x7FFFFFFF. + */ +__inline Word32 L_abs(Word32 x) +{ + if (x >= 0) + return x; + else if (x == ARMDSP_WORD32_MIN) + return ARMDSP_WORD32_MAX; + else + return -x; +} + +/* + * Return a saturated value appropriate to the most recent carry- + * affecting operation (L_add_c, L_macNs, L_sub_c, L_msuNs). + * + * In other words: return the argument if the Q flag is clear. + * Otherwise, return -0x80000000 or +0x7FFFFFFF depending on + * whether the Carry flag is set or clear (respectively). + */ +__inline Word32 L_sat(Word32 x) +{ + int qflag; + __asm { + mrs qflag, CPSR; + } + if (!(qflag & 0x08000000)) + return x; + if (Carry) + return ARMDSP_WORD32_MIN; + else + return ARMDSP_WORD32_MAX; +} + +/* + * Return the number of bits of left shift needed to arrange for a + * 16-bit signed integer to have value >= 0x4000 or <= -0x4001. + * + * Returns zero if x is zero. + */ +__inline Word16 norm_s(Word16 x) +{ + int lz; + if (x == 0) + return 0; /* 0 is a special case */ + x = (Word16) (x ^ (x >> 15)); /* invert x if it's negative */ + __asm { + clz lz, x; + } + return (Word16) (lz - 17); +} + +/* + * Divide one 16-bit signed integer by another, and produce a + * 15-bit fixed point fractional result (by multiplying the true + * mathematical result by 0x8000). The divisor (denominator) is + * assumed to be non-zero and also assumed to be greater or equal + * to the dividend (numerator). Hence the (unscaled) result is + * necessarily within the range [0,1]. + * + * Both operands are assumed to be positive. + * + * After division, the result is saturated to fit into a 16-bit + * signed integer. (The only way this can happen is if the operands + * are equal, so that the result would be 1, i.e. +0x8000 in 15-bit + * fixed point.) + */ +__inline Word16 div_s(Word16 x, Word16 y) +{ + Word32 quot; + assert(y > 0); + assert(x >= 0); + assert(x <= y); + quot = 0x8000 * x; + quot /= y; + if (quot > ARMDSP_WORD16_MAX) + return ARMDSP_WORD16_MAX; + else + return (Word16)quot; +} + +/* + * Return the number of bits of left shift needed to arrange for a + * 32-bit signed integer to have value >= 0x40000000 (if + * + * Returns zero if x is zero. + */ +__inline Word16 norm_l(Word32 x) +{ + int lz; + if (x == 0) + return 0; /* 0 is a special case */ + x ^= (x >> 31); /* invert x if it's negative */ + __asm { + clz lz, x; + } + return (Word16) (lz - 1); +} + +#ifdef __cplusplus +} +#endif + +#endif /* ARMDSP_DSPFNS_H */ diff --git a/inc/C_H/errno.h b/inc/C_H/errno.h new file mode 100644 index 0000000..db3a259 --- /dev/null +++ b/inc/C_H/errno.h @@ -0,0 +1,104 @@ +/* errno.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.1.3 */ +/* Copyright (C) Codemist Ltd., 1988 */ +/* Copyright 1991 ARM Limited. All rights reserved. */ +/* version 1 */ + +/* + * RCS $Revision: 1.11.2.1 $ + * Checkin $Date: 2001/02/22 16:23:35 $ + * Revising $Author: cadeniyi $ + */ + +#ifndef __errno_h +#define __errno_h + + #ifndef __ERRNO_DECLS + #define __ERRNO_DECLS + + #undef __CLIBNS + + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + + +extern __pure volatile int *__rt_errno_addr(void); + + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __ERRNO_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __ERRNO_NO_EXPORTS + using std::__rt_errno_addr; + #endif + #endif + +#define errno (*__CLIBNS __rt_errno_addr()) + +/* + * expands to a modifiable lvalue that has type volatile int, the value of + * which is set to a positive error code by several library functions. It is + * initialised to zero at program startup, but is never set to zero by any + * library function. The value of errno may be set to nonzero by a library + * function call whether or not there is an error, provided the use of errno + * is not documented in the description of the function in the Standard. + */ + +#define EDOM 1 +/* + * if a domain error occurs (an input argument is outside the + * domain over which the mathematical function is defined) the + * integer expression errno acquires the value of the macro EDOM + * and HUGE_VAL is returned. EDOM may be used by non-mathematical + * functions. + */ +#define ERANGE 2 +/* + * a range error occurs if the result of a function can not be + * represented as a double value. If the result overflows (the + * magnitude of the result is so large that it cannot be + * represented in an object of the specified type), the function + * returns the value of the macro HUGE_VAL, with the same sign as + * the correct value of the function; the integer expression errno + * acquires the value of the macro ERANGE. If the result underflows + * (the magnitude of the result is so small that it cannot be + * represented in an object of the specified type), the function + * returns zero; the integer expression errno acquires the value of + * the macro ERANGE. ERANGE may be used by non-mathematical + * functions. + */ +#define ESIGNUM 3 +/* + * ESIGNUM is generated by signal() if the user attempts to change + * the handling of a nonexistent signal. ESIGNUM is not part of the + * ANSI C standard. + */ +#define EILSEQ 4 +/* + * EILSEQ is notionally generated by multi-byte character + * processing routines (mbtowc et al), and must be defined for this + * reason. ARM's libraries do not generate it. + * + * EILSEQ is not mentioned in the ANSI C standard itself, but in + * Normative Addendum 1. + */ + +#endif + +/* end of errno.h */ diff --git a/inc/C_H/fenv.h b/inc/C_H/fenv.h new file mode 100644 index 0000000..5f4f97e --- /dev/null +++ b/inc/C_H/fenv.h @@ -0,0 +1,203 @@ +/* fenv.h + * + * Copyright 1998 ARM Limited. All rights reserved. + * + * RCS $Revision: 1.8 $ + * Checkin $Date: 2000/11/08 15:43:30 $ + * Revising $Author: statham $ + */ + +#ifndef __fenv_h +#define __fenv_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Types. + */ + +typedef unsigned int __ieee_edata_t; /* exception flags passed to traps */ + +typedef union { + float f; + float s; + double d; + int i; + unsigned int ui; + long long l; + unsigned long long ul; + struct { int word1, word2; } str; +} __ieee_value_t; /* in/out values passed to traps */ + +typedef __softfp __ieee_value_t (*__ieee_handler_t) (__ieee_value_t, __ieee_value_t, + __ieee_edata_t); + +typedef struct { + unsigned statusword; + __ieee_handler_t invalid_handler; + __ieee_handler_t divbyzero_handler; + __ieee_handler_t overflow_handler; + __ieee_handler_t underflow_handler; + __ieee_handler_t inexact_handler; +} fenv_t, fexcept_t; + +/* + * Exception flags. + */ + +#define FE_INVALID (0x01) +#define FE_DIVBYZERO (0x02) +#define FE_OVERFLOW (0x04) +#define FE_UNDERFLOW (0x08) +#define FE_INEXACT (0x10) +#define FE_ALL_EXCEPT (0x1F) + +/* + * Rounding modes. + */ + +#define FE_TONEAREST (0) +#define FE_UPWARD (1) +#define FE_DOWNWARD (2) +#define FE_TOWARDZERO (3) + +/* + * Default environment. + */ + +extern const fenv_t __fpl_default_env; +#define FE_DFL_ENV (&__fpl_default_env) + +/* + * Exception functions. + */ + +void fegetexceptflag(fexcept_t *, int); +void fesetexceptflag(const fexcept_t *, int); + +void feclearexcept(int); +void feraiseexcept(int); +int fetestexcept(int); + +/* + * Rounding functions. + */ + +int fegetround(void); +int fesetround(int); + +/* + * Full environment access. + */ + +void fegetenv(fenv_t *); +void fesetenv(const fenv_t *); + +int feholdexcept(fenv_t *); +void feupdateenv(const fenv_t *); + +/* + * Implementation-specific: ARM's own optimal status word access + * function, and the macros that go with it. + */ +extern unsigned __ieee_status(unsigned, unsigned); +#define FE_IEEE_FLUSHZERO (0x01000000) +#define FE_IEEE_ROUND_TONEAREST (0x00000000) +#define FE_IEEE_ROUND_UPWARD (0x00400000) +#define FE_IEEE_ROUND_DOWNWARD (0x00800000) +#define FE_IEEE_ROUND_TOWARDZERO (0x00C00000) +#define FE_IEEE_ROUND_MASK (0x00C00000) +#define FE_IEEE_MASK_INVALID (0x00000100) +#define FE_IEEE_MASK_DIVBYZERO (0x00000200) +#define FE_IEEE_MASK_OVERFLOW (0x00000400) +#define FE_IEEE_MASK_UNDERFLOW (0x00000800) +#define FE_IEEE_MASK_INEXACT (0x00001000) +#define FE_IEEE_MASK_ALL_EXCEPT (0x00001F00) +#define FE_IEEE_INVALID (0x00000001) +#define FE_IEEE_DIVBYZERO (0x00000002) +#define FE_IEEE_OVERFLOW (0x00000004) +#define FE_IEEE_UNDERFLOW (0x00000008) +#define FE_IEEE_INEXACT (0x00000010) +#define FE_IEEE_ALL_EXCEPT (0x0000001F) + +/* + * The constants that define the format of __ieee_edata_t. + */ + +#define FE_EX_RDIR (-1 << 31) +#define FE_EX_EXCEPT_SHIFT (26) +#define FE_EX_EXCEPT_MASK (0x1F << FE_EX_EXCEPT_SHIFT) +#define FE_EX_INEXACT (0x10 << FE_EX_EXCEPT_SHIFT) +#define FE_EX_UNDERFLOW (0x08 << FE_EX_EXCEPT_SHIFT) +#define FE_EX_OVERFLOW (0x04 << FE_EX_EXCEPT_SHIFT) +#define FE_EX_DIVBYZERO (0x02 << FE_EX_EXCEPT_SHIFT) +#define FE_EX_INVALID (0x01 << FE_EX_EXCEPT_SHIFT) +#define FE_EX_FLUSHZERO_SHIFT (24) +#define FE_EX_FLUSHZERO (1 << FE_EX_FLUSHZERO_SHIFT) +#define FE_EX_ROUND_SHIFT (22) +#define FE_EX_ROUND_MASK (3 << FE_EX_ROUND_SHIFT) +#define FE_EX_INTYPE_SHIFT (7) +#define FE_EX_INTYPE_MASK (7 << FE_EX_INTYPE_SHIFT) +#define FE_EX_OUTTYPE_SHIFT (4) +#define FE_EX_OUTTYPE_MASK (7 << FE_EX_OUTTYPE_SHIFT) +#define FE_EX_TYPE_SHIFT (4) +#define FE_EX_TYPE_MASK (7 << FE_EX_TYPE_SHIFT) +#define FE_EX_FN_SHIFT (0) +#define FE_EX_FN_MASK (15 << FE_EX_FN_SHIFT) + +#define FE_EX_ROUND_NEAREST (0 << FE_EX_ROUND_SHIFT) +#define FE_EX_ROUND_PLUSINF (1 << FE_EX_ROUND_SHIFT) +#define FE_EX_ROUND_MINUSINF (2 << FE_EX_ROUND_SHIFT) +#define FE_EX_ROUND_ZERO (3 << FE_EX_ROUND_SHIFT) + +#define FE_EX_BASETYPE_FLOAT (0) +#define FE_EX_BASETYPE_DOUBLE (1) +#define FE_EX_BASETYPE_INT (4) +#define FE_EX_BASETYPE_LONGLONG (5) +#define FE_EX_BASETYPE_UINT (6) +#define FE_EX_BASETYPE_ULONGLONG (7) + +#define FE_EX_TYPE_FLOAT (FE_EX_BASETYPE_FLOAT << FE_EX_TYPE_SHIFT) +#define FE_EX_TYPE_DOUBLE (FE_EX_BASETYPE_DOUBLE << FE_EX_TYPE_SHIFT) +#define FE_EX_TYPE_INT (FE_EX_BASETYPE_INT << FE_EX_TYPE_SHIFT) +#define FE_EX_TYPE_LONGLONG (FE_EX_BASETYPE_LONGLONG << FE_EX_TYPE_SHIFT) +#define FE_EX_TYPE_UINT (FE_EX_BASETYPE_UINT << FE_EX_TYPE_SHIFT) +#define FE_EX_TYPE_ULONGLONG (FE_EX_BASETYPE_ULONGLONG << FE_EX_TYPE_SHIFT) + +#define FE_EX_INTYPE_FLOAT (FE_EX_BASETYPE_FLOAT << FE_EX_INTYPE_SHIFT) +#define FE_EX_INTYPE_DOUBLE (FE_EX_BASETYPE_DOUBLE << FE_EX_INTYPE_SHIFT) +#define FE_EX_INTYPE_INT (FE_EX_BASETYPE_INT << FE_EX_INTYPE_SHIFT) +#define FE_EX_INTYPE_LONGLONG (FE_EX_BASETYPE_LONGLONG << FE_EX_INTYPE_SHIFT) +#define FE_EX_INTYPE_UINT (FE_EX_BASETYPE_UINT << FE_EX_INTYPE_SHIFT) +#define FE_EX_INTYPE_ULONGLONG (FE_EX_BASETYPE_ULONGLONG< extensions. + */ +#ifdef __cplusplus +extern "C" { +#endif +unsigned _controlfp(unsigned, unsigned); +unsigned _clearfp(void); +unsigned _statusfp(void); +#ifdef __cplusplus +} +#endif + + +/* + * Because the _EM_ constants are shared between _controlfp (masks) + * and _statusfp (sticky bits), we adopt the convention that + * _controlfp will shift its arguments left by 8 bits before using + * them. + */ + +#define _MCW_EM 0x001F +#define _EM_INVALID 0x0001 +#define _EM_ZERODIVIDE 0x0002 +#define _EM_OVERFLOW 0x0004 +#define _EM_UNDERFLOW 0x0008 +#define _EM_INEXACT 0x0010 + +#define _MCW_RC 0xC000 +#define _RC_CHOP 0xC000 +#define _RC_UP 0x4000 +#define _RC_DOWN 0x8000 +#define _RC_NEAR 0x0000 + +/* + * _FPE_ constants passed as the hidden second argument to SIGFPE + * handlers. + */ +#define _FPE_INVALID 0x04000000 +#define _FPE_ZERODIVIDE 0x08000000 +#define _FPE_OVERFLOW 0x10000000 +#define _FPE_UNDERFLOW 0x20000000 +#define _FPE_INEXACT 0x40000000 + + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __FLOAT_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __FLOAT_NO_EXPORTS + using std::_controlfp; + using std::_clearfp; + using std::_statusfp; + #endif + #endif + +/* end of float.h */ +#endif /* __float_h */ diff --git a/inc/C_H/inttypes.h b/inc/C_H/inttypes.h new file mode 100644 index 0000000..4a8b148 --- /dev/null +++ b/inc/C_H/inttypes.h @@ -0,0 +1,212 @@ +/* Copyright (C) ARM Ltd., 1999 */ +/* All rights reserved */ + +/* + * RCS $Revision: 1.5.2.2 $ + * Checkin $Date: 2001/05/24 07:32:01 $ + * Revising $Author: sdouglas $ + */ + +/* Based on WG14/N843 (C9X) Committee Draft August 3, 1998 */ + +#ifndef __inttypes_h +#define __inttypes_h + +#include + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) + + /* 7.8.1 */ + +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "d" +#define PRId64 "lld" +#define PRIdLEAST8 "d" +#define PRIdLEAST16 "d" +#define PRIdLEAST32 "d" +#define PRIdLEAST64 "lld" +#define PRIdFAST8 "d" +#define PRIdFAST16 "d" +#define PRIdFAST32 "d" +#define PRIdFAST64 "lld" +#define PRIdMAX "jd" +#define PRIdPTR "d" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 "lli" +#define PRIiLEAST8 "i" +#define PRIiLEAST16 "i" +#define PRIiLEAST32 "i" +#define PRIiLEAST64 "lli" +#define PRIiFAST8 "i" +#define PRIiFAST16 "i" +#define PRIiFAST32 "i" +#define PRIiFAST64 "lli" +#define PRIiMAX "ji" +#define PRIiPTR "i" + +#define PRIo8 "o" +#define PRIo16 "o" +#define PRIo32 "o" +#define PRIo64 "llo" +#define PRIoLEAST8 "o" +#define PRIoLEAST16 "o" +#define PRIoLEAST32 "o" +#define PRIoLEAST64 "llo" +#define PRIoFAST8 "o" +#define PRIoFAST16 "o" +#define PRIoFAST32 "o" +#define PRIoFAST64 "llo" +#define PRIoMAX "jo" +#define PRIoPTR "o" + +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 "llu" +#define PRIuLEAST8 "u" +#define PRIuLEAST16 "u" +#define PRIuLEAST32 "u" +#define PRIuLEAST64 "llu" +#define PRIuFAST8 "u" +#define PRIuFAST16 "u" +#define PRIuFAST32 "u" +#define PRIuFAST64 "llu" +#define PRIuMAX "ju" +#define PRIuPTR "u" + +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "x" +#define PRIx64 "llx" +#define PRIxLEAST8 "x" +#define PRIxLEAST16 "x" +#define PRIxLEAST32 "x" +#define PRIxLEAST64 "llx" +#define PRIxFAST8 "x" +#define PRIxFAST16 "x" +#define PRIxFAST32 "x" +#define PRIxFAST64 "llx" +#define PRIxMAX "jx" +#define PRIxPTR "x" + +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "X" +#define PRIX64 "llX" +#define PRIXLEAST8 "X" +#define PRIXLEAST16 "X" +#define PRIXLEAST32 "X" +#define PRIXLEAST64 "llX" +#define PRIXFAST8 "X" +#define PRIXFAST16 "X" +#define PRIXFAST32 "X" +#define PRIXFAST64 "llX" +#define PRIXMAX "jX" +#define PRIXPTR "X" + +#define SCNd16 "hd" +#define SCNd32 "d" +#define SCNd64 "lld" +#define SCNdLEAST16 "hd" +#define SCNdLEAST32 "d" +#define SCNdLEAST64 "lld" +#define SCNdFAST8 "d" +#define SCNdFAST16 "d" +#define SCNdFAST32 "d" +#define SCNdFAST64 "lld" +#define SCNdMAX "jd" +#define SCNdPTR "d" + +#define SCNi16 "hi" +#define SCNi32 "i" +#define SCNi64 "lli" +#define SCNiLEAST16 "hi" +#define SCNiLEAST32 "i" +#define SCNiLEAST64 "lli" +#define SCNiFAST8 "i" +#define SCNiFAST16 "i" +#define SCNiFAST32 "i" +#define SCNiFAST64 "lli" +#define SCNiMAX "ji" +#define SCNiPTR "i" + +#define SCNo16 "ho" +#define SCNo32 "o" +#define SCNo64 "llo" +#define SCNoLEAST16 "ho" +#define SCNoLEAST32 "o" +#define SCNoLEAST64 "llo" +#define SCNoFAST8 "o" +#define SCNoFAST16 "o" +#define SCNoFAST32 "o" +#define SCNoFAST64 "llo" +#define SCNoMAX "jo" +#define SCNoPTR "o" + +#define SCNu16 "hu" +#define SCNu32 "u" +#define SCNu64 "llu" +#define SCNuLEAST16 "hu" +#define SCNuLEAST32 "u" +#define SCNuLEAST64 "llu" +#define SCNuFAST8 "u" +#define SCNuFAST16 "u" +#define SCNuFAST32 "u" +#define SCNuFAST64 "llu" +#define SCNuMAX "ju" +#define SCNuPTR "u" + +#define SCNx16 "hx" +#define SCNx32 "x" +#define SCNx64 "llx" +#define SCNxLEAST16 "hx" +#define SCNxLEAST32 "x" +#define SCNxLEAST64 "llx" +#define SCNxFAST8 "x" +#define SCNxFAST16 "x" +#define SCNxFAST32 "x" +#define SCNxFAST64 "llx" +#define SCNxMAX "jx" +#define SCNxPTR "x" + +#endif /* __STDC_FORMAT_MACROS */ + +#ifndef __cplusplus /* wchar_t is a builtin type for C++ */ + #if !defined(__STRICT_ANSI__) + /* unconditional in non-strict C for consistency of debug info */ + typedef unsigned short wchar_t; /* see */ + #elif !defined(__wchar_t) + #define __wchar_t 1 + typedef unsigned short wchar_t; /* see */ + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +intmax_t strtoimax(const char * /*restrict*/ /*nptr*/, + char ** /*restrict*/ /*endptr*/, int /*base*/); + /* as for strtol */ +uintmax_t strtoumax(const char * /*restrict*/ /*nptr*/, + char ** /*restrict*/ /*endptr*/, int /*base*/); + /* as for strtoul */ + +#if 0 /* not yet implemented */ +intmax_t wcstoimax(const wchar_t * restrict /*nptr*/, + wchar_t ** restrict /*endptr*/, int /*base*/); +uintmax_t wcstoumax(const wchar_t * restrict /*nptr*/, + wchar_t ** restrict /*endptr*/, int /*base*/); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __inttypes_h */ + +/* end of inttypes.h */ diff --git a/inc/C_H/iso646.h b/inc/C_H/iso646.h new file mode 100644 index 0000000..1819a49 --- /dev/null +++ b/inc/C_H/iso646.h @@ -0,0 +1,29 @@ +/* iso646.h: ISO 'C' NA1 library header */ +/* Copyright 1996 ARM Limited. All rights reserved. */ + +/* + * Copyright ARM Ltd, 1999. All rights reserved. + * RCS $Revision: 1.4 $ + * Checkin $Date: 2000/11/08 15:43:30 $ + * Revising $Author: statham $ + */ + + +#ifndef __iso646_h +#define __iso646_h + +#define and && +#define and_eq &= +#define bitand & +#define bitor | +#define compl ~ +#define not ! +#define not_eq != +#define or || +#define or_eq |= +#define xor ^ +#define xor_eq ^= + +#endif + +/* end of iso646.h */ diff --git a/inc/C_H/limits.h b/inc/C_H/limits.h new file mode 100644 index 0000000..179737a --- /dev/null +++ b/inc/C_H/limits.h @@ -0,0 +1,66 @@ +/* limits.h: ANSI 'C' (X3J11 Oct 88) library header, section 2.2.4.2 */ +/* Copyright (C) Codemist Ltd., 1988 */ +/* Copyright 1991-1997 ARM Limited. All rights reserved */ + +/* + * RCS $Revision: 1.5 $ + * Checkin $Date: 1999/05/19 14:49:55 $ + * Revising $Author: wdijkstr $ + */ + +#ifndef __limits_h +#define __limits_h + +#define CHAR_BIT 8 + /* max number of bits for smallest object that is not a bit-field (byte) */ +#define SCHAR_MIN (-128) + /* mimimum value for an object of type signed char */ +#define SCHAR_MAX 127 + /* maximum value for an object of type signed char */ +#define UCHAR_MAX 255 + /* maximum value for an object of type unsigned char */ +#ifdef __FEATURE_SIGNED_CHAR + #define CHAR_MIN (-128) + /* minimum value for an object of type char */ + #define CHAR_MAX 127 + /* maximum value for an object of type char */ +#else + #define CHAR_MIN 0 + /* minimum value for an object of type char */ + #define CHAR_MAX 255 + /* maximum value for an object of type char */ +#endif +#define MB_LEN_MAX 1 + /* maximum number of bytes in a multibyte character, */ + /* for any supported locale */ + +#define SHRT_MIN (-0x8000) + /* minimum value for an object of type short int */ +#define SHRT_MAX 0x7fff + /* maximum value for an object of type short int */ +#define USHRT_MAX 65535 + /* maximum value for an object of type unsigned short int */ +#define INT_MIN (~0x7fffffff) /* -2147483648 and 0x80000000 are unsigned */ + /* minimum value for an object of type int */ +#define INT_MAX 0x7fffffff + /* maximum value for an object of type int */ +#define UINT_MAX 0xffffffffU + /* maximum value for an object of type unsigned int */ +#define LONG_MIN (~0x7fffffffL) + /* minimum value for an object of type long int */ +#define LONG_MAX 0x7fffffffL + /* maximum value for an object of type long int */ +#define ULONG_MAX 0xffffffffUL + /* maximum value for an object of type unsigned long int */ +#ifndef __STRICT_ANSI__ + #define LLONG_MIN (~0x7fffffffffffffffLL) + /* minimum value for an object of type long long int */ + #define LLONG_MAX 0x7fffffffffffffffLL + /* maximum value for an object of type long long int */ + #define ULLONG_MAX 0xffffffffffffffffULL + /* maximum value for an object of type unsigned long int */ +#endif + +#endif + +/* end of limits.h */ diff --git a/inc/C_H/locale.h b/inc/C_H/locale.h new file mode 100644 index 0000000..5c789f4 --- /dev/null +++ b/inc/C_H/locale.h @@ -0,0 +1,221 @@ +/* locale.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.3 */ +/* Copyright (C) Codemist Ltd., 1988 */ +/* Copyright 1991,1999 ARM Limited. All rights reserved. */ +/* version 0.03 */ + +/* + * RCS $Revision: 1.10.2.2 $ + * Checkin $Date: 2001/05/23 21:56:08 $ + * Revising $Author: sdouglas $ + */ + +#ifndef __locale_h +#define __locale_h + + #ifndef __LOCALE_DECLS + #define __LOCALE_DECLS + + #undef __CLIBNS + + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + +/* Handles national characteristics */ + +#define LC_COLLATE 1 + /* affects the behaviour of the strcoll function */ +#define LC_CTYPE 2 + /* affects the behaviour of the character handling functions */ + /* (isdigit, isspace and isxdigit are not affected) */ +#define LC_MONETARY 4 + /* affects the monetary formatting information returned by the */ + /* localeconv function. */ +#define LC_NUMERIC 8 + /* affects the decimal-point character for the formatted input/output */ + /* functions and the string conversion functions */ +#define LC_TIME 16 + /* could affect the behaviour of the strftime function but doesn't */ + /* for currently supported locales */ +#define LC_ALL (LC_TIME|LC_NUMERIC|LC_MONETARY|LC_CTYPE|LC_COLLATE) + /* program's entire locale */ + +extern char *setlocale(int /*category*/, const char * /*locale*/); + /* + * Selects the appropriate piece of the program's locale as specified by the + * category and locale arguments. The setlocale function may be used to + * change or query the program's entire current locale or portions thereof. + * The effect of the category argument for each value is described above. + * A value of "C" for locale specifies the minimal environment for C + * translation; a value of "" for locale specifies the implementation-defined + * native environment. At program startup the equivalent of + * setlocale(LC_ALL, "C") is executed. + * + * Return value: + * If a pointer to string is given for locale and the selection can be + * honoured, the string associated with the specified category for the new + * locale is returned. If the selction can not be honoured, a null pointer + * is returned and the program's locale is not changed. + * A null pointer for locale causes the string associated with the category + * for the program's current locale to be returned and the program's locale + * is not changed. If the category is LC_ALL and the most recent successful + * locale-setting call used a category other than LC_ALL a composite string + * may need to be returned. + * The string returned is such that a subsequent call with that string and + * its associated category will restore that part of the program's locale. + * The string returned shall not be modified by the program, but may be + * overwritten by a subsequent call to setlocale. + */ + +struct lconv { + char *decimal_point; + /* The decimal point character used to format non-monetary quantities */ + char *thousands_sep; + /* The character used to separate groups of digits to the left of the */ + /* decimal point character in formatted non-monetary quantities. */ + char *grouping; + /* A string whose elements indicate the size of each group of digits */ + /* in formatted non-monetary quantities. See below for more details. */ + char *int_curr_symbol; + /* The international currency symbol applicable to the current locale.*/ + /* The first three characters contain the alphabetic international */ + /* currency symbol in accordance with those specified in ISO 4217 */ + /* Codes for the representation of Currency and Funds. The fourth */ + /* character (immediately preceding the null character) is the */ + /* character used to separate the international currency symbol from */ + /* the monetary quantity. */ + char *currency_symbol; + /* The local currency symbol applicable to the current locale. */ + char *mon_decimal_point; + /* The decimal-point used to format monetary quantities. */ + char *mon_thousands_sep; + /* The separator for groups of digits to the left of the decimal-point*/ + /* in formatted monetary quantities. */ + char *mon_grouping; + /* A string whose elements indicate the size of each group of digits */ + /* in formatted monetary quantities. See below for more details. */ + char *positive_sign; + /* The string used to indicate a nonnegative-valued formatted */ + /* monetary quantity. */ + char *negative_sign; + /* The string used to indicate a negative-valued formatted monetary */ + /* quantity. */ + char int_frac_digits; + /* The number of fractional digits (those to the right of the */ + /* decimal-point) to be displayed in an internationally formatted */ + /* monetary quantities. */ + char frac_digits; + /* The number of fractional digits (those to the right of the */ + /* decimal-point) to be displayed in a formatted monetary quantity. */ + char p_cs_precedes; + /* Set to 1 or 0 if the currency_symbol respectively precedes or */ + /* succeeds the value for a nonnegative formatted monetary quantity. */ + char p_sep_by_space; + /* Set to 1 or 0 if the currency_symbol respectively is or is not */ + /* separated by a space from the value for a nonnegative formatted */ + /* monetary quantity. */ + char n_cs_precedes; + /* Set to 1 or 0 if the currency_symbol respectively precedes or */ + /* succeeds the value for a negative formatted monetary quantity. */ + char n_sep_by_space; + /* Set to 1 or 0 if the currency_symbol respectively is or is not */ + /* separated by a space from the value for a negative formatted */ + /* monetary quantity. */ + char p_sign_posn; + /* Set to a value indicating the position of the positive_sign for a */ + /* nonnegative formatted monetary quantity. See below for more details*/ + char n_sign_posn; + /* Set to a value indicating the position of the negative_sign for a */ + /* negative formatted monetary quantity. See below for more details. */ + + /* + * The elements of grouping amd mon_grouping are interpreted according to + * the following: + * CHAR_MAX No further grouping is to be performed. + * 0 The previous element is to be repeatedly used for the + * remainder of the digits. + * other The value is the number of digits that compromise the current + * group. The next element is examined to determine the size of + * the next group of digits to the left of the current group. + * + * The value of p_sign_posn and n_sign_posn is interpreted according to + * the following: + * 0 Parentheses surround the quantity and currency_symbol. + * 1 The sign string preceeds the quantity and currency_symbol. + * 2 The sign string succeeds the quantity and currency_symbol. + * 3 The sign string immediately preceeds the currency_symbol. + * 4 The sign string immediately succeeds the currency_symbol. + */ +}; + +extern struct lconv *localeconv(void); + /* + * Sets the components of an object with type struct lconv with values + * appropriate for the formatting of numeric quantities (monetary and + * otherwise) according to the rules of the current locale. + * The members of the structure with type char * are strings, any of which + * (except decimal_point) can point to "", to indicate that the value is not + * available in the current locale or is of zero length. The members with + * type char are nonnegative numbers, any of which can be CHAR_MAX to + * indicate that the value is not available in the current locale. + * The members included are described above. + * + * Return value: + * A pointer to the filled in object. The structure pointed to by the return + * value shall not be modified by the program, but may be overwritten by a + * subsequent call to the localeconv function. In addition, calls to the + * setlocale function with categories LC_ALL, LC_MONETARY, or LC_NUMERIC may + * overwrite the contents of the structure. + */ + +extern void _get_lconv(struct lconv * /*result*/); + /* + * Fills in the provided `lconv' structure exactly as + * localeconv does. This ANSI extension removes the need for + * static data within the library. + */ + +extern void __use_iso8859_locale(void); +extern void __use_iso8859_ctype(void); +extern void __use_iso8859_collate(void); +extern void __use_iso8859_monetary(void); +extern void __use_iso8859_numeric(void); + +#undef NULL +#define NULL 0 /* see */ + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __LOCALE_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __LOCALE_NO_EXPORTS + using std::setlocale; + using std::lconv; + using std::localeconv; + using std::_get_lconv; + using std::__use_iso8859_locale; + using std::__use_iso8859_ctype; + using std::__use_iso8859_collate; + using std::__use_iso8859_monetary; + using std::__use_iso8859_numeric; + #endif + #endif + +#endif + +/* end of locale.h */ diff --git a/inc/C_H/math.h b/inc/C_H/math.h new file mode 100644 index 0000000..68a6c7a --- /dev/null +++ b/inc/C_H/math.h @@ -0,0 +1,556 @@ +/* + * math.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.5 + * Copyright (C) Codemist Ltd., 1988 + * Copyright 1991-1998 ARM Limited. All rights reserved + */ + +/* + * RCS $Revision: 1.34.2.1 $ Codemist 0.03 + * Checkin $Date: 2001/02/22 16:23:35 $ + * Revising $Author: cadeniyi $ + */ + + +#ifndef __math_h +#define __math_h + + #ifndef __MATH_DECLS + #define __MATH_DECLS + + #undef __CLIBNS + + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + + +#ifndef HUGE_VAL +#ifndef __STRICT_ANSI__ +#define HUGE_VAL (0d_7FF0000000000000) +#else +extern const double __huge_val; +#define HUGE_VAL (__huge_val) +#endif +#endif + +#ifndef __STRICT_ANSI__ /* C99 extensions: */ +#define INFINITY (0f_7F800000) /* positive float infinity */ +#define NAN (0f_7FC00001) /* float quiet NaN */ +#endif + +extern double acos(double /*x*/); + /* computes the principal value of the arc cosine of x */ + /* a domain error occurs for arguments not in the range -1 to 1 */ + /* Returns: the arc cosine in the range 0 to Pi. */ +extern double asin(double /*x*/); + /* computes the principal value of the arc sine of x */ + /* a domain error occurs for arguments not in the range -1 to 1 */ + /* and -HUGE_VAL is returned. */ + /* Returns: the arc sine in the range -Pi/2 to Pi/2. */ + +extern __pure double atan(double /*x*/); + /* computes the principal value of the arc tangent of x */ + /* Returns: the arc tangent in the range -Pi/2 to Pi/2. */ + +extern double atan2(double /*y*/, double /*x*/); + /* computes the principal value of the arc tangent of y/x, using the */ + /* signs of both arguments to determine the quadrant of the return value */ + /* a domain error occurs if both args are zero, and -HUGE_VAL returned. */ + /* Returns: the arc tangent of y/x, in the range -Pi to Pi. */ + + +extern __pure double cos(double /*x*/); + /* computes the cosine of x (measured in radians). A large magnitude */ + /* argument may yield a result with little or no significance */ + /* Returns: the cosine value. */ +extern __pure double sin(double /*x*/); + /* computes the sine of x (measured in radians). A large magnitude */ + /* argument may yield a result with little or no significance */ + /* Returns: the sine value. */ + +extern void __use_accurate_range_reduction(void); + /* reference this to select the larger, slower, but more accurate */ + /* range reduction in sin, cos and tan */ + +extern double tan(double /*x*/); + /* computes the tangent of x (measured in radians). A large magnitude */ + /* argument may yield a result with little or no significance */ + /* Returns: the tangent value. */ + /* if range error; returns HUGE_VAL. */ + +extern double cosh(double /*x*/); + /* computes the hyperbolic cosine of x. A range error occurs if the */ + /* magnitude of x is too large. */ + /* Returns: the hyperbolic cosine value. */ + /* if range error; returns HUGE_VAL. */ +extern double sinh(double /*x*/); + /* computes the hyperbolic sine of x. A range error occurs if the */ + /* magnitude of x is too large. */ + /* Returns: the hyperbolic sine value. */ + /* if range error; returns -HUGE_VAL or HUGE_VAL depending */ + /* on the sign of the argument */ + +extern __pure double tanh(double /*x*/); + /* computes the hyperbolic tangent of x. */ + /* Returns: the hyperbolic tangent value. */ + +extern double exp(double /*x*/); + /* computes the exponential function of x. A range error occurs if the */ + /* magnitude of x is too large. */ + /* Returns: the exponential value. */ + /* if underflow range error; 0 is returned. */ + /* if overflow range error; HUGE_VAL is returned. */ + +extern double frexp(double /*value*/, int * /*exp*/); + /* breaks a floating-point number into a normalised fraction and an */ + /* integral power of 2. It stores the integer in the int object pointed */ + /* to by exp. */ + /* Returns: the value x, such that x is a double with magnitude in the */ + /* interval 0.5 to 1.0 or zero, and value equals x times 2 raised to the */ + /* power *exp. If value is zero, both parts of the result are zero. */ + +extern double ldexp(double /*x*/, int /*exp*/); + /* multiplies a floating-point number by an integral power of 2. */ + /* A range error may occur. */ + /* Returns: the value of x times 2 raised to the power of exp. */ + /* if range error; HUGE_VAL is returned. */ +extern double log(double /*x*/); + /* computes the natural logarithm of x. A domain error occurs if the */ + /* argument is negative, and -HUGE_VAL is returned. A range error occurs */ + /* if the argument is zero. */ + /* Returns: the natural logarithm. */ + /* if range error; -HUGE_VAL is returned. */ +extern double log10(double /*x*/); + /* computes the base-ten logarithm of x. A domain error occurs if the */ + /* argument is negative. A range error occurs if the argument is zero. */ + /* Returns: the base-ten logarithm. */ +extern double modf(double /*value*/, double * /*iptr*/); + /* breaks the argument value into integral and fraction parts, each of */ + /* which has the same sign as the argument. It stores the integral part */ + /* as a double in the object pointed to by iptr. */ + /* Returns: the signed fractional part of value. */ + +extern double pow(double /*x*/, double /*y*/); + /* computes x raised to the power of y. A domain error occurs if x is */ + /* zero and y is less than or equal to zero, or if x is negative and y */ + /* is not an integer, and -HUGE_VAL returned. A range error may occur. */ + /* Returns: the value of x raised to the power of y. */ + /* if underflow range error; 0 is returned. */ + /* if overflow range error; HUGE_VAL is returned. */ +extern double sqrt(double /*x*/); + /* computes the non-negative square root of x. A domain error occurs */ + /* if the argument is negative, and -HUGE_VAL returned. */ + /* Returns: the value of the square root. */ +#ifdef __TARGET_FPU_VFP + extern double _sqrt(double); /* native VFP double precision sqrt */ + extern float _sqrtf(float); /* native VFP single precision sqrt */ +#else + __inline double _sqrt(double __x) { return sqrt(__x); } + __inline float _sqrtf(float __x) { return (float)sqrt(__x); } +#endif + +extern __pure double ceil(double /*x*/); + /* computes the smallest integer not less than x. */ + /* Returns: the smallest integer not less than x, expressed as a double. */ +extern __pure double fabs(double /*x*/); + /* computes the absolute value of the floating-point number x. */ + /* Returns: the absolute value of x. */ + +extern float (_fabsf)(float); +#ifndef __STRICT_ANSI__ + #define fabsf (_fabsf) /* C99 */ +#endif + +extern __pure double floor(double /*d*/); + /* computes the largest integer not greater than x. */ + /* Returns: the largest integer not greater than x, expressed as a double */ + +extern double fmod(double /*x*/, double /*y*/); + /* computes the floating-point remainder of x/y. */ + /* Returns: the value x - i * y, for some integer i such that, if y is */ + /* nonzero, the result has the same sign as x and magnitude */ + /* less than the magnitude of y. If y is zero, a domain error */ + /* occurs and -HUGE_VAL is returned. */ + + /* Additional Mathlib functions not defined by the ANSI standard. + * Not guaranteed, and not necessarily very well tested. + * C99 requires the user to include to use these functions + * declaring them "by hand" is not sufficient + */ +#ifndef __STRICT_ANSI__ + +#if defined __thumb || defined __TARGET_FPU_SOFTVFP || defined __TARGET_FPU_SOFTVFP_VFP || \ + defined __TARGET_FPU_SOFTFPA || defined __TARGET_FPU_SOFTFPA_FPA +#define _FPMANGLE(name) __softfp_ ## name +#else +#define _FPMANGLE(name) __hardfp_ ## name +#endif + +extern double _FPMANGLE(acosh) (double /*x*/); +__inline double acosh(double __x) { return _FPMANGLE(acosh)(__x); } + /* + * Inverse cosh. EDOM if argument < 1.0 + */ +extern double _FPMANGLE(asinh) (double /*x*/); +__inline double asinh(double __x) { return _FPMANGLE(asinh)(__x); } + /* + * Inverse sinh. + */ +extern double _FPMANGLE(atanh) (double /*x*/); +__inline double atanh(double __x) { return _FPMANGLE(atanh)(__x); } + /* + * Inverse tanh. EDOM if |argument| > 1.0 + */ +extern double _FPMANGLE(cbrt) (double /*x*/); +__inline double cbrt(double __x) { return _FPMANGLE(cbrt)(__x); } + /* + * Cube root. + */ +extern double _FPMANGLE(copysign) (double /*x*/, double /*y*/); +__inline double copysign(double __x, double __y) { return _FPMANGLE(copysign)(__x,__y); } + /* + * Returns x with sign bit replaced by sign of y. + */ +extern double _FPMANGLE(erf) (double /*x*/); +__inline double erf(double __x) { return _FPMANGLE(erf)(__x); } + /* + * Error function. (2/sqrt(pi)) * integral from 0 to x of exp(-t*t) dt. + */ +extern double _FPMANGLE(erfc) (double /*x*/); +__inline double erfc(double __x) { return _FPMANGLE(erfc)(__x); } + /* + * 1-erf(x). (More accurate than just coding 1-erf(x), for large x.) + */ +extern double _FPMANGLE(expm1) (double /*x*/); +__inline double expm1(double __x) { return _FPMANGLE(expm1)(__x); } + /* + * exp(x)-1. (More accurate than just coding exp(x)-1, for small x.) + */ +extern int _FPMANGLE(finite) (double /*x*/); +__inline double finite(double __x) { return _FPMANGLE(finite)(__x); } + /* + * TRUE if argument is finite (ie not infinity or NaN). + */ +extern double _FPMANGLE(gamma) (double /*x*/); +__inline double gamma(double __x) { return _FPMANGLE(gamma)(__x); } + /* + * The log of the absolute value of the gamma function of x. The sign + * of the gamma function of x is returned in the global `signgam'. + */ +extern double _FPMANGLE(gamma_r) (double /*x*/, int * /*signgam*/); +__inline double gamma_r(double __x, int *__p) { return _FPMANGLE(gamma_r)(__x,__p); } + /* + * The log of the absolute value of the gamma function of x. The sign + * of the gamma function of x is returned in the second argument. + */ +extern double _FPMANGLE(hypot) (double /*x*/, double /*y*/); +__inline double hypot(double __x, double __y) { return _FPMANGLE(hypot)(__x,__y); } + /* + * sqrt(x*x+y*y), ie the length of the vector (x,y) or the + * hypotenuse of a right triangle whose other two sides are x + * and y. Won't overflow unless the _answer_ is too big, even + * if the intermediate x*x+y*y is too big. + */ +extern int _FPMANGLE(ilogb) (double /*x*/); +__inline int ilogb(double __x) { return _FPMANGLE(ilogb)(__x); } + /* + * Exponent of x (returns 0 for 1.0, 1 for 2.0, -1 for 0.5, etc.) + */ +extern int _FPMANGLE(isnan) (double /*x*/); +__inline double isnan(double __x) { return _FPMANGLE(isnan)(__x); } + /* + * Returns TRUE if x is a NaN. + */ +extern double _FPMANGLE(j0) (double /*x*/); +__inline double j0(double __x) { return _FPMANGLE(j0)(__x); } + /* + * Bessel function of the first kind, order 0. Returns ERANGE + * if |x| > 2^52 (total loss of significance). + */ +extern double _FPMANGLE(j1) (double /*x*/); +__inline double j1(double __x) { return _FPMANGLE(j1)(__x); } + /* + * Bessel function of the first kind, order 1. Returns ERANGE + * if |x| > 2^52 (total loss of significance). + */ +extern double _FPMANGLE(jn) (int /*n*/, double /*x*/); +__inline double jn(int __n, double __x) { return _FPMANGLE(jn)(__n, __x); } + /* + * Bessel function of the first kind, order n. Returns ERANGE + * if |x| > 2^52 (total loss of significance). + */ +extern double _FPMANGLE(lgamma) (double /*x*/); +__inline double lgamma(double __x) { return _FPMANGLE(lgamma)(__x); } + /* + * The log of the absolute value of the gamma function of x. The sign + * of the gamma function of x is returned in the global `signgam'. + */ +extern double _FPMANGLE(lgamma_r) (double /*x*/, int * /*signgam*/); +__inline double lgamma_r(double __x, int *__p) { return _FPMANGLE(lgamma_r)(__x,__p); } + /* + * The log of the absolute value of the gamma function of x. The sign + * of the gamma function of x is returned in the second argument. + */ +extern double _FPMANGLE(log1p) (double /*x*/); +__inline double log1p(double __x) { return _FPMANGLE(log1p)(__x); } + /* + * log(1+x). (More accurate than just coding log(1+x), for small x.) + */ +extern double _FPMANGLE(logb) (double /*x*/); +__inline double logb(double __x) { return _FPMANGLE(logb)(__x); } + /* + * Like ilogb but returns a double. + */ +extern double _FPMANGLE(nextafter) (double /*x*/, double /*y*/); +__inline double nextafter(double __x, double __y) { return _FPMANGLE(nextafter)(__x,__y); } + /* + * Returns the next representable number after x, in the + * direction toward y. + */ +extern double _FPMANGLE(remainder) (double /*x*/, double /*y*/); +__inline double remainder(double __x, double __y) { return _FPMANGLE(remainder)(__x,__y); } + /* + * Returns the remainder of x by y, in the IEEE 754 sense. + */ +extern double _FPMANGLE(rint) (double /*x*/); +__inline double rint(double __x) { return _FPMANGLE(rint)(__x); } + /* + * Rounds x to an integer, in the IEEE 754 sense. + */ +extern double _FPMANGLE(scalb) (double /*x*/, double /*n*/); +__inline double scalb(double __x, double __n) { return _FPMANGLE(scalb)(__x,__n); } + /* + * Compute x times 2^n quickly. Undefined if n is not an integer. + */ +extern double _FPMANGLE(scalbn) (double /*x*/, int /*n*/); +__inline double scalbn(double __x, int __n) { return _FPMANGLE(scalbn)(__x,__n); } + /* + * Compute x times 2^n quickly. + */ +extern double _FPMANGLE(significand) (double /*x*/); +__inline double significand(double __x) { return _FPMANGLE(significand)(__x); } + /* + * Return the fraction part of x, in the range 1.0 to 2.0 + * (including 1.0, excluding 2.0). + */ +extern double _FPMANGLE(y0) (double /*x*/); +__inline double y0(double __x) { return _FPMANGLE(y0)(__x); } + /* + * Bessel function of the second kind, order 0. Returns ERANGE + * if x > 2^52 (total loss of significance). + */ +extern double _FPMANGLE(y1) (double /*x*/); +__inline double y1(double __x) { return _FPMANGLE(y1)(__x); } + /* + * Bessel function of the second kind, order 1. Returns ERANGE + * if x > 2^52 (total loss of significance). + */ +extern double _FPMANGLE(yn) (int /*n*/, double /*x*/); +__inline double yn(int __n, double __x) { return _FPMANGLE(yn)(__n, __x); } + /* + * Bessel function of the second kind, order n. Returns ERANGE + * if x > 2^52 (total loss of significance). + */ +#endif + +#ifdef __cplusplus + extern float __mathlib_tofloat(double); /* internal; used below */ + extern "C++" { + inline double abs(double __x) + { return fabs(__x); } + inline float abs(float __x) + { return (_fabsf)(__x); } + inline float acos(float __x) // acosf + { return (float)(acos((double) __x)); } + inline float asin(float __x) // asinf + { return (float)(asin((double) __x)); } + inline float atan(float __x) // atanf + { return (float)(atan((double) __x)); } + inline float atan2(float __y, float __x) // atan2f + { return (float)(atan2((double) __y, (double) __x)); } + inline float ceil(float __x) // ceilf + { return (float)(ceil((double) __x)); } + inline float cos(float __x) // cosf + { return (float)(cos((double) __x)); } + inline float cosh(float __x) // coshf + { return __mathlib_tofloat(cosh((double) __x)); } + inline float exp(float __x) // expf + { return __mathlib_tofloat(exp((double) __x)); } + inline float (fabs)(float __x) // fabsf + { return (float)(fabs((double) __x)); } + inline float floor(float __x) // floorf + { return (float)(floor((double) __x)); } + inline float fmod(float __x, float __y) //fmodf + { return (float)(fmod((double) __x, (double) __y)); } + inline float frexp(float __x, int* __exp) // frexpf + { return (float)(frexp((double) __x, __exp)); } + inline float ldexp(float __x, int __exp) // ldexpf + { return __mathlib_tofloat(ldexp((double) __x, __exp));} + inline float log(float __x) // logf + { return (float)(log((double) __x)); } + inline float log10(float __x) // log10f + { return (float)(log10((double) __x)); } + inline float modf(float __x, float* __iptr) // modff + { double __d; float __ret; + __ret = (float)(modf((double) __x, &__d)); + *__iptr = (float)(__d); return __ret; } + inline float pow(float __x, float __y) // powf + { return __mathlib_tofloat(pow((double) __x, (double) __y)); } + inline float pow (float __x, int __y) + { return __mathlib_tofloat(pow((double) __x, (double) __y)); } + inline float sin(float __x) //sinf + { return (float)(sin((double) __x)); } + inline float sinh(float __x) //sinhf + { return __mathlib_tofloat(sinh((double) __x)); } + inline float sqrt(float __x) // sqrtf + { return (float)(sqrt((double) __x)); } + inline float _sqrt(float __x) // _sqrtf + { return _sqrtf(__x); } + inline float tan(float __x) // tanf + { return __mathlib_tofloat(tan((double) __x)); } + inline float tanh(float __x) // tanhf + { return (float)(tanh((double) __x)); } + + inline double pow(double __x, int __y) + { return pow(__x, (double) __y); } + + inline long double abs(long double __x) // fabsl + { return (long double)abs((double) __x); } + inline long double acos(long double __x) // acosl + { return (long double)acos((double) __x); } + inline long double asin(long double __x) // asinl + { return (long double)asin((double) __x); } + inline long double atan(long double __x) // atanl + { return (long double)atan((double) __x); } + inline long double atan2(long double __y, long double __x) //atan2l + { return (long double)atan2((double) __y, (double) __x); } + inline long double ceil(long double __x) // ceill + { return (long double)ceil((double) __x); } + inline long double cos(long double __x) // cosl + { return (long double)cos((double) __x); } + inline long double cosh(long double __x) // coshl + { return (long double)cosh((double) __x); } + inline long double exp(long double __x) // expl + { return (long double)exp((double) __x); } + inline long double (fabs)(long double __x) // fabsl + { return (long double)fabs((double) __x); } + inline long double floor(long double __x) // floorl + { return (long double)floor((double) __x); } + inline long double fmod(long double __x, long double __y) // fmodl + { return (long double)fmod((double) __x, (double) __y); } + inline long double frexp(long double __x, int* __p) // frexpl + { return (long double)frexp((double) __x, __p); } + inline long double ldexp(long double __x, int __exp) // ldexpl + { return (long double)ldexp((double) __x, __exp); } + inline long double log(long double __x) // logl + { return (long double)log((double) __x); } + inline long double log10(long double __x) // log10l + { return (long double)log10((double) __x); } + inline long double modf(long double __x, long double* __p) //modfl + { return (long double)modf((double) __x, (double *) __p); } + inline long double pow(long double __x, long double __y) // powl + { return (long double)pow((double) __x, (double) __y); } + inline long double pow (long double __x, int __y) + { return (long double)pow((double) __x, __y); } + inline long double sin(long double __x) //sinl + { return (long double)sin((double) __x); } + inline long double sinh(long double __x) // sinhl + { return (long double)sinh((double) __x); } + inline long double sqrt(long double __x) // sqrtl + { return (long double)sqrt((double) __x); } + inline long double _sqrt(long double __x) // _sqrtl + { return (long double)_sqrt((double) __x); } + inline long double tan(long double __x) // tanl + { return (long double)tan((double) __x); } + inline long double tanh(long double __x) // tanhl + { return (long double)tanh((double) __x); } + } +#endif + + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __MATH_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __MATH_NO_EXPORTS + using std::__mathlib_tofloat; + using std::__use_accurate_range_reduction; + using std::abs; + using std::acos; + using std::asin; + using std::atan2; + using std::atan; + using std::ceil; + using std::cos; + using std::cosh; + using std::exp; + using std::fabs; + using std::floor; + using std::fmod; + using std::frexp; + using std::ldexp; + using std::log10; + using std::log; + using std::modf; + using std::pow ; + using std::pow; + using std::sin; + using std::sinh; + using std::sqrt; + using std::tan; + using std::tanh; + using std::_fabsf; + #ifndef __STRICT_ANSI__ + using std::acosh; + using std::asinh; + using std::atanh; + using std::cbrt; + using std::copysign; + using std::erf; + using std::erfc; + using std::expm1; + using std::finite; + using std::gamma; + using std::gamma_r; + using std::hypot; + using std::ilogb; + using std::isnan; + using std::j0; + using std::j1; + using std::jn; + using std::lgamma; + using std::lgamma_r; + using std::log1p; + using std::logb; + using std::nextafter; + using std::remainder; + using std::rint; + using std::scalb; + using std::scalbn; + using std::significand; + using std::y0; + using std::y1; + using std::yn; + #endif + + #endif + #endif + +#endif + +/* end of math.h */ diff --git a/inc/C_H/new.h b/inc/C_H/new.h new file mode 100644 index 0000000..106441f --- /dev/null +++ b/inc/C_H/new.h @@ -0,0 +1,19 @@ +/* + * C++ Library file new.h + * (After Stroustrup, "The C++ Programming Language", section 3.2.6) + * Copyright 1993 ARM Limited. All rights reserved. + * Copyright (C) Codemist Limited, 1994. + */ + +/* + * RCS $Revision: 1.14 $ + * Checkin $Date: 2001/01/05 14:52:12 $ + * Revising $Author: vkorstan $ + */ + +#ifndef __NEW_H +#define __NEW_H +#include +#endif + +/* End of new.h */ diff --git a/inc/C_H/rt_fp.h b/inc/C_H/rt_fp.h new file mode 100644 index 0000000..ac5e3a0 --- /dev/null +++ b/inc/C_H/rt_fp.h @@ -0,0 +1,129 @@ +/* rt_fp.h: prototypes for the fplib basic-arithmetic functions + * + * Copyright 1999 ARM Limited. All rights reserved. + * + * RCS $Revision: 1.4 $ + * Checkin $Date: 2000/11/08 15:43:29 $ + * Revising $Author: statham $ + */ + +#ifndef __RT_FP_H +#define __RT_FP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Trivial routines. + */ +extern __softfp float _fneg(float); +extern __softfp float _fabs(float); +extern __softfp double _dneg(double); +extern __softfp double _dabs(double); + +/* + * Single-precision arithmetic routines. + */ +extern __softfp float _fadd(float, float); +extern __softfp float _fsub(float, float); +extern __softfp float _frsb(float, float); +extern __softfp float _fmul(float, float); +extern __softfp float _fdiv(float, float); +extern __softfp float _frdiv(float, float); +extern __softfp float _frem(float, float); +extern __softfp float _frnd(float); +extern __softfp float _fsqrt(float); + +/* + * Double-precision arithmetic routines. + */ +extern __softfp double _dadd(double, double); +extern __softfp double _dsub(double, double); +extern __softfp double _drsb(double, double); +extern __softfp double _dmul(double, double); +extern __softfp double _ddiv(double, double); +extern __softfp double _drdiv(double, double); +extern __softfp double _drem(double, double); +extern __softfp double _drnd(double); +extern __softfp double _dsqrt(double); + +/* + * Boolean-return compares ({f,d}cmp{eq,ge,le} are not listed + * because they return results in the flags and so cannot be + * described by C prototypes). + */ +extern __softfp int _feq(float, float); +extern __softfp int _fneq(float, float); +extern __softfp int _fgeq(float, float); +extern __softfp int _fgr(float, float); +extern __softfp int _fleq(float, float); +extern __softfp int _fls(float, float); +extern __softfp int _deq(double, double); +extern __softfp int _dneq(double, double); +extern __softfp int _dgeq(double, double); +extern __softfp int _dgr(double, double); +extern __softfp int _dleq(double, double); +extern __softfp int _dls(double, double); + +/* + * Floating-to-floating format conversions. + */ +extern __softfp double _f2d(float); +extern __softfp float _d2f(double); + +/* + * Integer-to-floating format conversions. + */ +extern __softfp float _fflt(int); +extern __softfp float _ffltu(unsigned int); +extern __softfp double _dflt(int); +extern __softfp double _dfltu(unsigned int); +extern __softfp float _ll_sto_f(long long); +extern __softfp float _ll_uto_f(unsigned long long); +extern __softfp double _ll_sto_d(long long); +extern __softfp double _ll_uto_d(unsigned long long); + +/* + * Floating-to-integer format conversions, rounding toward zero + * always. + */ +extern __softfp int _ffix(float); +extern __softfp unsigned int _ffixu(float); +extern __softfp int _dfix(double); +extern __softfp unsigned int _dfixu(double); +extern __softfp long long _ll_sfrom_f(float); +extern __softfp unsigned long long _ll_ufrom_f(float); +extern __softfp long long _ll_sfrom_d(double); +extern __softfp unsigned long long _ll_ufrom_d(double); + +/* + * Floating-to-integer format conversions, rounding to nearest or + * configurably. + */ +extern __softfp int _ffix_r(float); +extern __softfp unsigned int _ffixu_r(float); +extern __softfp int _dfix_r(double); +extern __softfp unsigned int _dfixu_r(double); +extern __softfp long long _ll_sfrom_f_r(float); +extern __softfp unsigned long long _ll_ufrom_f_r(float); +extern __softfp long long _ll_sfrom_d_r(double); +extern __softfp unsigned long long _ll_ufrom_d_r(double); + +/* + * Call this before using any fplib routines, if you're trying to + * use fplib on the bare metal. + */ +extern void _fp_init(void); + +/* + * This returns a pointer to the FP status word, when it's stored + * in memory. + */ +extern unsigned *__rt_fp_status_addr(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/C_H/rt_heap.h b/inc/C_H/rt_heap.h new file mode 100644 index 0000000..2c3858b --- /dev/null +++ b/inc/C_H/rt_heap.h @@ -0,0 +1,62 @@ +/* rt_heap.h: definitions to enable retargetting of heap implementation + * + * Copyright 1999 ARM Limited. All rights reserved. + * + * RCS $Revision: 1.8 $ + * Checkin $Date: 2000/11/08 15:43:29 $ + * Revising $Author: statham $ + */ + +#ifndef __RT_HEAP_H +#define __RT_HEAP_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This is the structure that defines the heap descriptor. The + * first section of it is used by the C library and so the format + * is fixed. Space after that can be used as the user wishes. + */ +struct __Heap_Descriptor; + +/* + * Define all these functions to override the heap. __Heap_DescSize + * must return the size of the __Heap_Descriptor structure. + */ +extern int __Heap_DescSize(int zero); +extern void __Heap_Initialize(struct __Heap_Descriptor *h); +extern void __Heap_ProvideMemory(struct __Heap_Descriptor *, void *, size_t); +extern void *__Heap_Alloc(struct __Heap_Descriptor *, size_t); +extern void __Heap_Free(struct __Heap_Descriptor *, void *); +extern void *__Heap_Realloc(struct __Heap_Descriptor *, void *, size_t); +extern void *__Heap_Stats(struct __Heap_Descriptor *, + int (* /*print*/)(void *, char const *format, ...), + void * /*printparam*/); +extern int __Heap_Valid(struct __Heap_Descriptor *, + int (* /*print*/)(void *, char const *format, ...), + void * /*printparam*/, int /*verbose*/); + +/* + * The heap can call these functions when it is full or + * inconsistent. __Heap_Full is passed the extra size that the heap + * needs, and will call back to __Heap_ProvideMemory if it can find + * some more storage. These are not functions you should override. + */ + +extern int __Heap_Full(struct __Heap_Descriptor *, size_t); +extern void __Heap_Broken(struct __Heap_Descriptor *); + +/* + * Call _init_alloc, and define __rt_heap_extend, if you are trying + * to run a heap on the bare metal. + */ +extern void _init_alloc(unsigned /*base*/, unsigned /*top*/); +extern unsigned __rt_heap_extend(unsigned /*size*/, void ** /*block*/); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/C_H/rt_locale.h b/inc/C_H/rt_locale.h new file mode 100644 index 0000000..2368c46 --- /dev/null +++ b/inc/C_H/rt_locale.h @@ -0,0 +1,269 @@ +/* rt_locale.h: definitions to enable retargetting of locale mechanism + * + * Copyright 1999 ARM Limited. All rights reserved. + * + * RCS $Revision: 1.7.2.2 $ + * Checkin $Date: 2001/09/25 15:20:37 $ + * Revising $Author: statham $ + */ + +#ifndef __RT_LOCALE_H +#define __RT_LOCALE_H + +#define __lblk_start _Pragma("push_once Ono_remove_unused_constdata Ono_data_reorder") +#define __lblk_end _Pragma("pop") + +/* + * Macros to define locale blocks. + * + * All the macros' first two arguments are a symbol prefix and a + * locale name. The resulting locale block will be addressed by the + * expression `&symprefix_start', and the index entry by the + * expression `&symprefix_index'. + */ + +/* + * usage: __LC_CTYPE_DEF(symprefix, localename) + * {table[0],table[1],...,table[255]}; + */ + +#define __LC_CTYPE_INTERNAL_DEF(sym,ln,tableclass,tablename) \ +__lblk_start \ +static const int sym##_index[] = {~3 & (3 + (268+(~3 & (3 + sizeof(ln)))))}; \ +static const char sym##_lname[~3 & (3 + sizeof(ln))] = ln; \ +static const int sym##_pname[] = {-4-(~3 & (3 + sizeof(ln)))}; \ +static const char sym##_start[] = {0}; \ +tableclass const char tablename[256] = + +#define __LC_CTYPE_DEF(sym,ln) \ + __LC_CTYPE_INTERNAL_DEF(sym,ln,static,sym##_table) + +/* + * usage: __LC_COLLATE_DEF(symprefix, localename) + * {table[0],table[1],...,table[255]}; + * + * Also: __LC_COLLATE_TRIVIAL_DEF(symprefix,localename) + * + * which will define a LC_COLLATE block in which + * offset_collate_table is zero, signifying the absence of a table. + */ + +#define __LC_COLLATE_DEF(sym,ln) \ +__lblk_start \ +static const int sym##_index[] = {~3&(3+(268+(~3&(3+sizeof(ln)))))}; \ +static const char sym##_lname[~3 & (3 + sizeof(ln))] = ln; \ +static const int sym##_pname[] = {-4-(~3 & (3 + sizeof(ln)))}; \ +static const int sym##_start[] = {4}; \ +static const char sym##_table[] = + +#define __LC_COLLATE_TRIVIAL_DEF(sym,ln) \ +__lblk_start \ +static const int sym##_index[] = {~3&(3+(12+(~3&(3+sizeof(ln)))))}; \ +static const char sym##_lname[~3 & (3 + sizeof(ln))] = ln; \ +static const int sym##_pname[] = {-4-(~3 & (3 + sizeof(ln)))}; \ +static const int sym##_start[] = {0}; + +/* + * usage: __LC_TIME_DEF(symprefix, localename, + * week_abbrevs, + * week_fullnames, + * month_abbrevs, + * month_fullnames, + * am, pm, + * datetime_fmt, + * date_fmt, + * time_fmt) + */ + +#define __LC_TIME_DEF(sym,ln,wa,wf,ma,mf,am,pm,dt,df,tf) \ +__lblk_start \ +static const int sym##_index[] = {~3 & (3 + (sizeof(wa)+sizeof(wf)+sizeof(ma)+ \ + sizeof(mf)+sizeof(am)+sizeof(pm)+ \ + sizeof(dt)+sizeof(df)+sizeof(tf)+ \ + 60+(~3 & (3 + sizeof(ln)))))}; \ +static const char sym##_lname[~3 & (3 + sizeof(ln))] = ln; \ +static const int sym##_pname[] = {-4-(~3 & (3 + sizeof(ln)))}; \ +static const int sym##_start[] = {52}; \ +static const int sym##_wfoff[] = {(sizeof(wa)+52)}; \ +static const int sym##_maoff[] = {(sizeof(wa)+sizeof(wf)+52)}; \ +static const int sym##_mfoff[] = {(sizeof(wa)+sizeof(wf)+sizeof(ma)+52)}; \ +static const int sym##_amoff[] = {(sizeof(wa)+sizeof(wf)+sizeof(ma)+ \ + sizeof(mf)+52)}; \ +static const int sym##_pmoff[] = {(sizeof(wa)+sizeof(wf)+sizeof(ma)+ \ + sizeof(mf)+sizeof(am)+52)}; \ +static const int sym##_dtoff[] = {(sizeof(wa)+sizeof(wf)+sizeof(ma)+ \ + sizeof(mf)+sizeof(am)+sizeof(pm)+52)}; \ +static const int sym##_dfoff[] = {(sizeof(wa)+sizeof(wf)+sizeof(ma)+ \ + sizeof(mf)+sizeof(am)+sizeof(pm)+ \ + sizeof(dt)+52)}; \ +static const int sym##_tfoff[] = {(sizeof(wa)+sizeof(wf)+sizeof(ma)+ \ + sizeof(mf)+sizeof(am)+sizeof(pm)+ \ + sizeof(dt)+sizeof(df)+52)}; \ +static const int sym##_wasiz[] = {(sizeof(wa)/7)}; \ +static const int sym##_wfsiz[] = {(sizeof(wf)/7)}; \ +static const int sym##_masiz[] = {(sizeof(ma)/12)}; \ +static const int sym##_mfsiz[] = {(sizeof(mf)/12)}; \ +static const char sym##_watxt[] = wa; \ +static const char sym##_wftxt[] = wf; \ +static const char sym##_matxt[] = ma; \ +static const char sym##_mftxt[] = mf; \ +static const char sym##_amtxt[] = am; \ +static const char sym##_pmtxt[] = pm; \ +static const char sym##_dttxt[] = dt; \ +static const char sym##_dftxt[] = df; \ +static const char sym##_tftxt[] = tf; + +/* + * usage: __LC_NUMERIC_DEF(symprefix, localename, + * decimal_point, + * thousands_sep, + * grouping) + */ + +#define __LC_NUMERIC_DEF(sym,ln,dp,ts,gr) \ +__lblk_start \ +static const int sym##_index[] = {~3 & (3 + (sizeof(dp)+sizeof(ts)+sizeof(gr)+ \ + 20) + (~3 & (3 + sizeof(ln))))}; \ +static const char sym##_lname[~3 & (3 + sizeof(ln))] = ln; \ +static const int sym##_pname[] = {-4-(~3 & (3 + sizeof(ln)))}; \ +static const int sym##_start[] = {12}; \ +static const int sym##_tsoff[] = {(sizeof(dp)+12)}; \ +static const int sym##_groff[] = {(sizeof(dp)+sizeof(ts)+12)}; \ +static const char sym##_dptxt[] = dp; \ +static const char sym##_tstxt[] = ts; \ +static const char sym##_grtxt[] = gr; + +/* + * usage: __LC_MONETARY_DEF(symprefix, localename, + * int_curr_symbol, + * currency_symbol, + * mon_decimal_point, + * mon_thousands_sep, + * mon_grouping, + * positive_sign, + * negative_sign, + * int_frac_digits, + * frac_digits, + * p_cs_precedes, + * p_sep_by_space, + * n_cs_precedes, + * n_sep_by_space, + * p_sign_posn, + * n_sign_posn) + */ + +#define __LC_MONETARY_DEF(sym,ln,ic,cs,md,mt,mg,ps,ns, \ + id,fd,pc,pS,nc,nS,pp,np) \ +__lblk_start \ +static const int sym##_index[] = {~3 & (3 + (sizeof(ic)+sizeof(cs)+sizeof(md)+ \ + sizeof(mt)+sizeof(mg)+sizeof(ps)+ \ + sizeof(ns)+44) \ ++ (~3 & (3 + sizeof(ln))))}; \ +static const char sym##_lname[~3 & (3 + sizeof(ln))] = ln; \ +static const int sym##_pname[] = {-4-(~3 & (3 + sizeof(ln)))}; \ +static const char sym##_start[] = {id}; \ +static const char sym##_fdchr[] = {fd}; \ +static const char sym##_pcchr[] = {pc}; \ +static const char sym##_pSchr[] = {pS}; \ +static const char sym##_ncchr[] = {nc}; \ +static const char sym##_nSchr[] = {nS}; \ +static const char sym##_ppchr[] = {pp}; \ +static const char sym##_npchr[] = {np}; \ +static const int sym##_icoff[] = {36}; \ +static const int sym##_csoff[] = {(sizeof(ic)+36)}; \ +static const int sym##_mdoff[] = {(sizeof(ic)+sizeof(cs)+36)}; \ +static const int sym##_mtoff[] = {(sizeof(ic)+sizeof(cs)+sizeof(md)+36)}; \ +static const int sym##_mgoff[] = {(sizeof(ic)+sizeof(cs)+sizeof(md)+ \ + sizeof(mt)+36)}; \ +static const int sym##_psoff[] = {(sizeof(ic)+sizeof(cs)+sizeof(md)+ \ + sizeof(mt)+sizeof(mg)+36)}; \ +static const int sym##_nsoff[] = {(sizeof(ic)+sizeof(cs)+sizeof(md)+ \ + sizeof(mt)+sizeof(mg)+sizeof(ps)+36)}; \ +static const char sym##_ictxt[] = ic; \ +static const char sym##_cstxt[] = cs; \ +static const char sym##_mdtxt[] = md; \ +static const char sym##_mttxt[] = mt; \ +static const char sym##_mgtxt[] = mg; \ +static const char sym##_pstxt[] = ps; \ +static const char sym##_nstxt[] = ns; + +/* + * Use this macro to declare the end of an index. `symprefix' is + * provided to ensure a unique name. + */ +#define __LC_INDEX_END(symprefix) \ +__lblk_start \ +static const int symprefix##_index[] = {0}; \ +__lblk_end + +/* + * The `struct' forms of the blocks defined above. + */ +struct __lc_ctype_blk { + char ctype_table[257]; /* char ctype_table[-1..255] */ +}; +struct __lc_collate_blk { + unsigned offset_collate_table; /* char collate_table[256], or 0 */ +}; +struct __lc_time_blk { + unsigned offset_week_abbrs; /* char week_abbrs[] */ + unsigned offset_week_full; /* char week_full[] */ + unsigned offset_month_abbrs; /* char month_abbrs[] */ + unsigned offset_month_full; /* char month_full[] */ + unsigned offset_am; /* char am[] */ + unsigned offset_pm; /* char pm[] */ + unsigned offset_datetime_fmt; /* char datetime_fmt[] */ + unsigned offset_date_fmt; /* char date_fmt[] */ + unsigned offset_time_fmt; /* char time_fmt[] */ + unsigned size_week_abbrs; /* size of one entry */ + unsigned size_week_full; /* size of one entry */ + unsigned size_month_abbrs; /* size of one entry */ + unsigned size_month_full; /* size of one entry */ +}; +struct __lc_numeric_blk { + unsigned offset_decimal_point; /* char decimal_point[] */ + unsigned offset_thousands_sep; /* char thousands_sep[] */ + unsigned offset_grouping; /* char grouping[] */ +}; +struct __lc_monetary_blk { + char int_frac_digits; + char frac_digits; + char p_cs_precedes; + char p_sep_by_space; + char n_cs_precedes; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; + unsigned offset_int_curr_symbol; /* char int_curr_symbol[] */ + unsigned offset_currency_symbol; /* char currency_symbol[] */ + unsigned offset_mon_decimal_point; /* char mon_decimal_point[] */ + unsigned offset_mon_thousands_sep; /* char mon_thousands_sep[] */ + unsigned offset_mon_grouping; /* char mon_grouping[] */ + unsigned offset_positive_sign; /* char positive_sign[] */ + unsigned offset_negative_sign; /* char negative_sign[] */ +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The _findlocale function for performing index searches. + */ +extern void const *_findlocale(void const * /*index*/, char const * /*name*/); + +/* + * The _get_lc_CATEGORY functions. Override these to retarget + * locales. + */ +void const *_get_lc_collate(void const * /*null*/, char const * /*name*/); +void const *_get_lc_ctype(void const * /*null*/, char const * /*name*/); +void const *_get_lc_monetary(void const * /*null*/, char const * /*name*/); +void const *_get_lc_numeric(void const * /*null*/, char const * /*name*/); +void const *_get_lc_time(void const * /*null*/, char const * /*name*/); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/C_H/rt_misc.h b/inc/C_H/rt_misc.h new file mode 100644 index 0000000..1b978ed --- /dev/null +++ b/inc/C_H/rt_misc.h @@ -0,0 +1,153 @@ +/* rt_misc.h: definitions for miscellaneous retargetable functions + * + * Copyright 1999 ARM Limited. All rights reserved. + * + * RCS $Revision: 1.5.2.2 $ + * Checkin $Date: 2001/04/23 11:51:33 $ + * Revising $Author: statham $ + */ + +#ifndef __RT_MISC_H +#define __RT_MISC_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This will be called during startup if it's defined, in order to + * allow a user reimplementation of getenv() to initialise itself. + */ +extern void _getenv_init(void); + +/* + * This will be called during startup if it's defined, in order to + * allow a user reimplementation of clock() to initialise itself. + */ +extern void _clock_init(void); + +/* + * This must return a pointer to __USER_LIBSPACE_SIZE bytes of + * zero-initialised space, used to store vital static data such as + * errno, the heap state, and the FP status word. + */ +#define __USER_LIBSPACE_SIZE 96 +extern void *__user_libspace(void); + +/* + * This is the library init function itself, provided just in case + * a user needs to call it directly. It is called just after + * __rt_stackheap_init(), and passed an initial chunk of memory to + * use as a heap. It returns argc and argv ready to be passed to + * main(). + */ +struct __argc_argv { + int argc; + char **argv; +}; +extern __value_in_regs struct __argc_argv +__rt_lib_init(unsigned /*heapbase*/, unsigned /*heaptop*/); + +/* + * This is the library shutdown function, analogous to + * __rt_lib_init(). + */ +extern void __rt_lib_shutdown(void); + +/* + * The medium-level exit function. exit() calls atexit()-registered + * functions and shuts down the library; _sys_exit() does neither + * of those things; __rt_exit() shuts down the library but doesn't + * call atexit() functions. + */ +extern void __rt_exit(int /*returncode*/); /* never returns */ + +/* + * This can be defined to override the standard memory models' way + * of determining where to put the initial stack and heap. + * + * The input parameters R0 and R2 contain nothing useful. The input + * parameters SP and SL are the values that were in SP and SL when + * the program began execution (so you can return them if you want + * to keep that stack). + * + * The two `limit' fields in the return structure are ignored if + * you are using the one-region memory model: the memory region is + * taken to be all the space between heap_base and stack_base. + */ +struct __initial_stackheap { + unsigned heap_base; /* low-address end of initial heap */ + unsigned stack_base; /* high-address end of initial stack */ + unsigned heap_limit; /* high-address end of initial heap */ + unsigned stack_limit; /* low-address end of initial stack */ +}; +extern __value_in_regs struct __initial_stackheap +__user_initial_stackheap(unsigned /*R0*/, unsigned /*SP*/, + unsigned /*R2*/, unsigned /*SL*/); + +/* + * This can be defined to give bounds on the address space the heap + * will ever use. + */ +struct __heap_extent { + unsigned base, range; +}; +extern __value_in_regs struct __heap_extent +__user_heap_extent(unsigned /*ignore*/, unsigned /*ignore*/); + +/* + * This can be defined to specify how much spare stack is needed + * below SL in addition to the 256 bytes required by ATPCS: + * `always' gives the number of bytes of extra stack required at + * all instants (so that an interrupt handler has space to run in, + * for example), while `cleanup' gives the number of bytes of extra + * stack required to be available after a stack overflow has + * occurred, so that the stack overflow routine (e.g. SIGSTAK + * handler) has room to tidy up. + */ +struct __stack_slop { + unsigned always, cleanup; +}; +extern __value_in_regs struct __stack_slop +__user_stack_slop(unsigned /*ignore*/, unsigned /*ignore*/); + +/* + * This can be defined to return extra blocks of memory, separate + * from the initial one, to be used by the heap. It should place a + * pointer to a block of at least the requested size in `*base', + * and return the size of the block. It should return 0 if no such + * block can be returned, in which case the value stored at `*base' + * is never used. + */ +extern unsigned __user_heap_extend(int /*ignore*/, + unsigned /*requestedsize*/, + void ** /*base*/); + +/* + * Redefine this to completely override the C handling of signals + * (bypassing the signal() mechanism). Return values are 0 to + * continue execution, or a non-zero value to cause an exit with + * that return code. + */ +int __raise(int /*sig*/, int /*type*/); + +/* + * Redefine this to change the default handling of signals. The + * interface is the same as __raise(), but this function will only + * get called after the C signal handling mechanism has declined to + * process the signal. + */ +int __default_signal_handler(int /*sig*/, int /*type*/); + +/* + * Redefine this to replace the library's entire signal handling + * mechanism in the most efficient possible way. The default + * implementation of this is what calls __raise (above). + */ +void __rt_raise(int /*sig*/, int /*type*/); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/C_H/rt_sys.h b/inc/C_H/rt_sys.h new file mode 100644 index 0000000..0e7595a --- /dev/null +++ b/inc/C_H/rt_sys.h @@ -0,0 +1,146 @@ +/* rt_sys.h: prototypes for _sys_* functions and types + * + * Copyright 1999 ARM Limited. All rights reserved. + * + * RCS $Revision: 1.6 $ + * Checkin $Date: 2000/11/08 15:43:29 $ + * Revising $Author: statham $ + */ + +#ifndef __RT_SYS_H +#define __RT_SYS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This type is used by the _sys_ I/O functions to denote an open + * file. + */ +typedef int FILEHANDLE; + +/* + * Open a file. May return -1 if the file failed to open. + */ +extern FILEHANDLE _sys_open(const char * /*name*/, int /*openmode*/); +/* + * openmode is a bitmap, whose bits are given below. They + * correspond directly to the ANSI mode specification. + */ +#define OPEN_R 0 +#define OPEN_W 4 +#define OPEN_A 8 +#define OPEN_B 1 +#define OPEN_PLUS 2 + +/* + * These names should be special strings which will be recognised + * by _sys_open and will cause it to return the standard I/O + * handles, instead of opening a real file. + */ +extern const char __stdin_name[]; +extern const char __stdout_name[]; +extern const char __stderr_name[]; + +/* + * Close a file. Should return 0 on success or a negative value on error. + */ +extern int _sys_close(FILEHANDLE /*fh*/); + +/* + * Write to a file. Returns 0 on success, negative on error, and + * the number of characters _not_ written on partial success. + * `mode' is either 0 or OPEN_B, consistent with the mode in which + * the file was opened. + */ +extern int _sys_write(FILEHANDLE /*fh*/, const unsigned char * /*buf*/, + unsigned /*len*/, int /*mode*/); + +/* + * Read from a file. Can return: + * - zero if the read was completely successful + * - the number of bytes _not_ read, if the read was partially successful + * - the number of bytes not read, plus the top bit set (0x80000000), if + * the read was partially successful due to end of file + * - -1 if some error other than EOF occurred + * + * It is also legal to signal EOF by returning no data but + * signalling no error (i.e. the top-bit-set mechanism need never + * be used). + * + * So if (for example) the user is trying to read 8 bytes at a time + * from a file in which only 5 remain, this routine can do three + * equally valid things: + * + * - it can return 0x80000003 (3 bytes not read due to EOF) + * - OR it can return 3 (3 bytes not read), and then return + * 0x80000008 (8 bytes not read due to EOF) on the next attempt + * - OR it can return 3 (3 bytes not read), and then return + * 8 (8 bytes not read, meaning 0 read, meaning EOF) on the next + * attempt + * + * `mode' is either 0 or OPEN_B, consistent with the mode in which + * the file was opened. + */ +extern int _sys_read(FILEHANDLE /*fh*/, unsigned char * /*buf*/, + unsigned /*len*/, int /*mode*/); + +/* + * Write a character to the output channel. This function is used + * for last-resort error message output. + */ +extern void _ttywrch(int /*ch*/); + +/* + * Return non-zero if the argument file is connected to a terminal. + */ +extern int _sys_istty(FILEHANDLE /*fh*/); + +/* + * Move the file position to a given offset from the file start. + * Returns >=0 on success, <0 on failure. + */ +extern int _sys_seek(FILEHANDLE /*fh*/, long /*pos*/); + +/* + * Flush any OS buffers associated with fh, ensuring that the file + * is up to date on disk. Result is >=0 if OK, negative for an + * error. + */ +extern int _sys_ensure(FILEHANDLE /*fh*/); + +/* + * Return the current length of a file, or <0 if an error occurred. + * _sys_flen is allowed to reposition the file pointer (so Unix can + * implement it with a single lseek, for example), since it is only + * called when processing SEEK_END relative fseeks, and therefore a + * call to _sys_flen is always followed by a call to _sys_seek. + */ +extern long _sys_flen(FILEHANDLE /*fh*/); + +/* + * Return the name for temporary file number sig in the buffer + * name. Returns 0 on failure. maxlen is the maximum name length + * allowed. + */ +extern int _sys_tmpnam(char * /*name*/, int /*sig*/, unsigned /*maxlen*/); + +/* + * Terminate the program, passing a return code back to the user. + * This function may not return. + */ +extern void _sys_exit(int /*returncode*/); /* never returns */ + +/* + * Return a pointer to the command line used to invoke the program. + * The supplied buffer may be used to store the string, but need + * not be. + */ +extern char *_sys_command_string(char * /*cmd*/, int /*len*/); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/C_H/setjmp.h b/inc/C_H/setjmp.h new file mode 100644 index 0000000..22b22ed --- /dev/null +++ b/inc/C_H/setjmp.h @@ -0,0 +1,100 @@ +/* setjmp.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.6 */ + +/* Copyright (C) ARM Ltd., 1999 + * All rights reserved + * RCS $Revision: 1.9.2.1 $ + * Checkin $Date: 2001/02/22 16:23:35 $ + * Revising $Author: cadeniyi $ + */ + +/* Copyright (C) Codemist Ltd., 1988 */ +/* Copyright 1991 ARM Limited. All rights reserved. */ + + +/* + * setjmp.h declares two functions and one type, for bypassing the normal + * function call and return discipline (useful for dealing with unusual + * conditions encountered in a low-level function of a program). + */ + +#ifndef __setjmp_h +#define __setjmp_h + + #ifndef __SETJMP_DECLS + #define __SETJMP_DECLS + + #undef __CLIBNS + + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + +typedef int jmp_buf[32]; /* size suitable for the ARM */ + /* an array type suitable for holding the data */ + /* needed to restore a calling environment. */ + +/* setjmp is a macro so that it cannot be used other than directly called. */ +/* NB that ANSI declare that anyone who undefines the setjmp macro or uses */ +/* (or defines) the name setjmp without including this header will get */ +/* what they deserve. In addition, C++ requires setjmp to be a macro. */ + +extern int setjmp(jmp_buf /*env*/); + /* Saves its calling environment in its jmp_buf argument, for later use + * by the longjmp function. + * Returns: If the return is from a direct invocation, the setjmp function + * returns the value zero. If the return from a call to the longjmp + * function, the setjmp function returns a non zero value. + */ +#define setjmp(jmp_buf) (__CLIBNS setjmp(jmp_buf)) + +extern void longjmp(jmp_buf /*env*/, int /*val*/); + /* Restores the environment saved by the most recent call to setjmp in the + * same invocation of the program, with the corresponding jmp_buf argument. + * If there has been no such call, or if the function containing the call + * to setjmp has terminated execution (eg. with a return statement) in the + * interim, the behaviour is undefined. + * All accessible objects have values as of the time longjmp was called, + * except that the values of objects of automatic storage duration that do + * not have volatile type and have been changed between the setjmp and + * longjmp calls are indeterminate. + * As it bypasses the usual function call and return mechanism, the longjmp + * function shall execute correctly in contexts of interrupts, signals and + * any of their associated functions. However, if the longjmp function is + * invoked from a nested signal handler (that is, from a function invoked as + * a result of a signal raised during the handling of another signal), the + * behaviour is undefined. + * Returns: After longjmp is completed, program execution continues as if + * the corresponding call to setjmp had just returned the value + * specified by val. The longjmp function cannot cause setjmp to + * return the value 0; if val is 0, setjmp returns the value 1. + */ + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __SETJMP_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __SETJMP_NO_EXPORTS + using std::jmp_buf; + using std::setjmp; + using std::longjmp; + #endif + #endif + +#endif + +/* end of setjmp.h */ diff --git a/inc/C_H/signal.h b/inc/C_H/signal.h new file mode 100644 index 0000000..1eae54d --- /dev/null +++ b/inc/C_H/signal.h @@ -0,0 +1,142 @@ +/* signal.h + * + * Copyright (C) Codemist Ltd., 1988-1993. + * Copyright 1991-1999 ARM Limited. All rights reserved. + * + * RCS $Revision: 1.9.2.1 $ + * Checkin $Date: 2001/02/22 16:23:35 $ + * Revising $Author: cadeniyi $ + */ + +/* + * signal.h declares a type and two functions and defines several macros, for + * handling various signals (conditions that may be reported during program + * execution). + */ + +#ifndef __signal_h +#define __signal_h + + #ifndef __SIGNAL_DECLS + #define __SIGNAL_DECLS + + #undef __CLIBNS + + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + + +typedef int sig_atomic_t; + /* type which is the integral type of an object that can be modified as */ + /* an atomic entity, even in the presence of asynchronous interrupts. */ + +extern void __SIG_DFL(int); +extern void __SIG_ERR(int); +extern void __SIG_IGN(int); + /* + * Each of the following macros expand to a constant expression with a + * distinct value and has the same type as the second argument to, and the + * return value of the signal function, and whose value compares unequal to + * the address of any declarable function. + */ +#define SIG_DFL &__CLIBNS __SIG_DFL +#define SIG_ERR &__CLIBNS __SIG_ERR +#define SIG_IGN &__CLIBNS __SIG_IGN + + /* + * Each of the following macros expand to a positive integral constant + * expression that is the signal number corresponding the the specified + * condition. + */ +#define SIGABRT 1 /* abort */ +#define SIGFPE 2 /* arithmetic exception */ +#define SIGILL 3 /* illegal instruction */ +#define SIGINT 4 /* attention request from user */ +#define SIGSEGV 5 /* bad memory access */ +#define SIGTERM 6 /* termination request */ + /* (these following macros are not part of the ANSI standard, + * but private to this implementation) + */ +#define SIGSTAK 7 /* stack overflow */ +#define SIGRTRED 8 /* run-time redirection error */ +#define SIGRTMEM 9 /* run-time memory error */ +/* Signal numbers 10 and 11 are available for the user */ +#define SIGUSR1 10 +#define SIGUSR2 11 +#define SIGPVFN 12 /* pure virtual function called */ +#define SIGCPPL 13 /* exception from C++ library */ +/* Signal numbers 14-31 are reserved to the implementation */ +/* Signal numbers 32 and larger are for more user signals */ + +extern void (*signal (int /*sig*/, void (* /*func*/ )(int)))(int); + /* + * Chooses one of three ways in which receipt of the signal number sig is to + * be subsequently handled. If the value of func is SIG_DFL, default + * handling for that signal will occur. If the value of func is SIG_IGN, the + * signal will be ignored. Otherwise func shall point to a function to be + * called when that signal occurs. + * When a signal occurs, if func points to a function, first the + * equivalent of signal(sig, SIG_DFL); is executed. (If the value of sig + * is SIGILL, whether the reset to SIG_DFL occurs is implementation- + * defined). Next the equivalent of (*func)(sig); is executed. The + * function may terminate by calling the abort, exit or longjmp function. + * If func executes a return statement and the value of sig was SIGFPE or + * any other implementation-defined value corresponding to a computational + * exception, the behaviour is undefined. Otherwise, the program will + * resume execution at the point it was interrupted. + * If the signal occurs other than as a result of calling the abort or raise + * function, the behaviour is undefined if the signal handler calls any + * function in the standard library other than the signal function itself + * or refers to any object with static storage duration other than by + * assigning a value to a volatile static variable of type sig_atomic_t. + * At program startup, the equivalent of signal(sig, SIG_IGN); may be + * executed for some signals selected in an implementation-defined manner; + * the equivalent of signal(sig, SIG_DFL); is executed for all other + * signals defined by the implementation. + * Returns: If the request can be honoured, the signal function returns the + * value of func for most recent call to signal for the specified + * signal sig. Otherwise, a value of SIG_ERR is returned and the + * integer expression errno is set to indicate the error. + */ + +extern int raise(int /*sig*/); + /* sends the signal sig to the executing program. */ + /* Returns: zero if successful, non-zero if unsuccessful. */ + +#ifndef __STRICT_ANSI__ +#define DIVBYZERO 2 /* SIGFPE param for integer div-by-0 */ +#endif + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __SIGNAL_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __SIGNAL_NO_EXPORTS + using std::sig_atomic_t; + using std::__SIG_DFL; + using std::__SIG_ERR; + using std::__SIG_IGN; + using std::raise; + using std::signal; + #endif + #endif + +#endif + +/* end of signal.h */ diff --git a/inc/C_H/stdarg.h b/inc/C_H/stdarg.h new file mode 100644 index 0000000..8f3147f --- /dev/null +++ b/inc/C_H/stdarg.h @@ -0,0 +1,123 @@ +/* stdarg.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.8 */ +/* Copyright (C) Codemist Ltd., 1988 */ +/* Copyright (C) ARM Ltd., 1991-1999. All rights reserved */ + +/* + * RCS $Revision: 1.9.2.1 $ + * Checkin $Date: 2001/02/22 16:23:35 $ + * Revising $Author: cadeniyi $ + */ + +#ifndef __stdarg_h +#define __stdarg_h + + #ifndef __STDARG_DECLS + #define __STDARG_DECLS + + #undef __CLIBNS + + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + +/* + * stdarg.h declares a type and defines macros for advancing through a + * list of arguments whose number and types are not known to the called + * function when it is translated. A function may be called with a variable + * number of arguments of differing types. Its parameter list contains one or + * more parameters. The rightmost parameter plays a special role in the access + * mechanism, and will be called parmN in this description. + */ + +/* N.B. is required to declare vfprintf() without defining */ +/* va_list. Clearly the type __va_list there must keep in step. */ +typedef int *va_list[1]; + /* + * an array type suitable for holding information needed by the macro va_arg + * and the function va_end. The called function shall declare a variable + * (referred to as ap) having type va_list. The variable ap may be passed as + * an argument to another function. + * Note: va_list is an array type so that when an object of that type + * is passed as an argument it gets passed by reference. + */ + +#define va_start(ap, parmN) (void)(*(ap) = __va_start(parmN)) + /* + * The va_start macro shall be executed before any access to the unnamed + * arguments. The parameter ap points to an object that has type va_list. + * The va_start macro initialises ap for subsequent use by va_arg and + * va_end. The parameter parmN is the identifier of the rightmost parameter + * in the variable parameter list in the function definition (the one just + * before the '...'). If the parameter parmN is declared with the register + * storage class an error is given. + * If parmN is a narrow type (char, short, float) an error is given in + * strict ANSI mode, or a warning otherwise. + * Returns: no value. + */ + +#define va_arg(ap, type) __va_arg(*(ap), type) + /* + * The va_arg macro expands to an expression that has the type and value of + * the next argument in the call. The parameter ap shall be the same as the + * va_list ap initialised by va_start. Each invocation of va_arg modifies + * ap so that successive arguments are returned in turn. The parameter + * 'type' is a type name such that the type of a pointer to an object that + * has the specified type can be obtained simply by postfixing a * to + * 'type'. If type is a narrow type, an error is given in strict ANSI + * mode, or a warning otherwise. If the type is an array or function type, + * an error is given. + * In non-strict ANSI mode, 'type' is allowed to be any expression. + * Returns: The first invocation of the va_arg macro after that of the + * va_start macro returns the value of the argument after that + * specified by parmN. Successive invocations return the values of + * the remaining arguments in succession. + * The result is cast to 'type', even if 'type' is narrow. + */ + +#ifndef __STRICT_ANSI__ +#define va_copy(dest, src) ((void)(*(dest) = *(src))) + /* The va_copy macro makes the va_list dest be a copy of + * the va_list src, as if the va_start macro had been applied + * to it followed by the same sequence of uses of the va_arg + * macro as had previously been used to reach the present state + * of src. + */ +#endif + + +#define va_end(ap) ((void)(*(ap) = 0)) + /* + * The va_end macro facilitates a normal return from the function whose + * variable argument list was referenced by the expansion of va_start that + * initialised the va_list ap. If the va_end macro is not invoked before + * the return, the behaviour is undefined. + * Returns: no value. + */ + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __STDARG_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __STDARG_NO_EXPORTS + using std::va_list; + #endif + #endif + +#endif + +/* end of stdarg.h */ diff --git a/inc/C_H/stdcomp.h b/inc/C_H/stdcomp.h new file mode 100644 index 0000000..2f699fa --- /dev/null +++ b/inc/C_H/stdcomp.h @@ -0,0 +1,1566 @@ +#ifndef __STD_RWCOMPILER_H__ +#define __STD_RWCOMPILER_H__ 1 + +/*************************************************************************** + * + * Compiler and system related foibles and directives + * + *************************************************************************** + * + * Copyright (c) 1994-1999 Rogue Wave Software, Inc. All Rights Reserved. + * + * This computer software is owned by Rogue Wave Software, Inc. and is + * protected by U.S. copyright laws and other laws and by international + * treaties. This computer software is furnished by Rogue Wave Software, + * Inc. pursuant to a written license agreement and may be used, copied, + * transmitted, and stored only in accordance with the terms of such + * license and with the inclusion of the above copyright notice. This + * computer software or any other copies thereof may not be provided or + * otherwise made available to any other person. + * + * U.S. Government Restricted Rights. This computer software is provided + * with Restricted Rights. Use, duplication, or disclosure by the + * Government is subject to restrictions as set forth in subparagraph (c) + * (1) (ii) of The Rights in Technical Data and Computer Software clause + * at DFARS 252.227-7013 or subparagraphs (c) (1) and (2) of the + * Commercial Computer Software Restricted Rights at 48 CFR 52.227-19, + * as applicable. Manufacturer is Rogue Wave Software, Inc., 5500 + * Flatiron Parkway, Boulder, Colorado 80301 USA. + * + **************************************************************************/ + +/**************************************************************** + **************************************************************** + * * + * U S E R T U N A B L E S E C T I O N * + * * + **************************************************************** + ****************************************************************/ + + +// Library version number +// +#define _RWSTD_VER 0x020101 +// AABBCC +// | | | +// | | +-- CC = Maintenance number +// | +---- BB = Minor Release number +// +------ AA = Major Release number +// +// Note that former version numbers were of the form: 0xAABC +// i.e., they showed only one digit each for Minor and Maintenance. +// e.g. "0x0203" would be "0x020003" in the new, extended scheme. + +/* + * This section has various preprocessor constants that can + * be set to reflect the properties of your compiler. For most + * compilers (particularly, MS-DOS compilers) there is no need + * to do anything --- most settings can be autodetected. + * + * For many Unix compilers you may have to tune the settings below. + * This is most easily done by running the "config" shell script + * which will try various test programs to discover the properties + * of your compiler. + * + * THIS IS FAR EASIER THAN SETTING THESE BY HAND! + */ + +/* + * AT&T "CFRONT" USERS + */ + + +/* + * Most compilers have a built in "manifest constant". + * For the following compilers you must supply one by uncommenting + * an appropriate line: + * + * AT&T cfront V2.X: __ATT2__ + * AT&T cfront V3.0: __ATT3__ + */ + +/* #define __ATT2__ 1 */ +/* #define __ATT3__ 1 */ + +/** + ** *** ALL USERS *** + **/ + + +#define _RWSTD_NOMSG 0x00 +#define _RWSTD_CATGETS 0x01 +#define _RWSTD_GETTEXT 0x02 +#define _RWSTD_DGETTEXT 0x03 + +/* + * Set _RWSTD_MESSAGE to the type of messaging facility you want: + * _RWSTD_NOMSG No messaging facility + * _RWSTD_CATGETS Use catgets() + * _RWSTD_GETTEXT Use gettext() + * _RWSTD_DGETTEXT Use dgettext() + */ + +#define _RWSTD_MESSAGE _RWSTD_NOMSG + + +#if !defined( __TURBOC__) && !defined(_MSC_VER) && !defined(_OS2) + +/******************** OPTIONAL LIBRARY FEATURES********************/ +/* turned off by default */ + +/* Uncomment the following if you wish for bounds checking to be + * performed for operator[] for deque and vector + */ + +/* #define _RWSTD_BOUNDS_CHECKING 1 */ + +/* Uncomment the following if you wish to use localized error messages + */ + +/* #define _RWSTD_LOCALIZED_ERRORS 1 */ + + +/******************** COMPILER WORD SIZES, ETC ********************/ + +/* + * Uncomment the following and set to the number of decimal digits + * of precision for type double. + * If you do nothing, the default will be 16. + */ + +/* #define _RWSTD_DEFAULT_PRECISION 16 */ + + +/*************** COMPILER QUIRKS AND LIMITATIONS ******************/ + +/* + * Uncomment the following if your compiler does not support + * exceptions. + */ + +/* #define _RWSTD_NO_EXCEPTIONS 1 */ + +/* + * Uncomment the following if your compiler does not support + * exceptions specifications. + */ + +/* #define _RWSTD_NO_EX_SPEC 1 */ + + +/* + * Uncomment the following if your compiler does not support + * throwing of exceptions from a shared library. + */ + +/* #define _RWSTD_NO_THROW_WITH_SHARED 1 */ + +/*************************** TEMPLATES **********************************/ + +/* + * Uncomment the following if your compiler does not instantiates only those + * functions, member functions, classes or member classes that are + * required; i.e. your compiler instantiates things that your program + * doesn't actually use. + */ + +/* #define _RWSTD_NO_STRICT_TEMPLATE_INSTANTIATE 1 */ + +/* + * Uncomment the following if your compiler does not allow an unused + * T *operator-> in a template when T is of non-class type. + */ + +/* #define _RWSTD_NO_NONCLASS_ARROW_RETURN 1 */ + +/* + * Uncomment the following if your compiler does not support the new syntax + * for functions that are templatized only on the return type, e.g. + * template T func (void); // Declare the function template + * int my_int = func(); // Call the function + */ + +/* #define _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE 1 */ + +/* + * Uncomment the following if your compiler does template + * instantiation at compile time. + */ + +/* #define _RWSTD_COMPILE_INSTANTIATE 1 */ + + +/*************************** STRINGS ****************************/ + +/* + * Uncomment the following if your sprintf() does not + * return the size of the buffer as an int, as ANSI C requires. + */ + +/* #define _RWSTD_NO_ANSI_SPRINTF 1 */ + + +/* + * Uncomment the following if your compiler does not have the + * ANSI C function memmove(). + */ + +/* #define _RWSTD_NO_MEMMOVE 1 */ + +/* + * Uncomment the following if your compiler's stdio.h does not define + * an fpos_t type. + */ + +/* #define _RWSTD_NO_FPOS_T 1 */ + +/* + * Uncomment the following if your compiler's stdlib.h does not provide + * an ldiv function. + */ + +/* #define _RWSTD_NO_LDIV 1 */ + +/* + * Uncomment the following if your compiler's header does not + * define a bad_cast exception type. + */ + +/* #define _RWSTD_NO_BAD_CAST 1 */ + +/****************** INTERNATIONALIZATION ************************/ + +/* + * Uncomment the following if your compiler does not support + * wide characters strings (e.g., functions wslen(), etc.). + */ + +/* #define _RWSTD_NO_WSTR 1 */ + +/* + * Uncomment the following if your compiler's support for + * wide character strings does not include support for any + * of the following: wctomb(), mbtowc(), iswspace(), wmemset(), + * wmemchr() and wcsstr(). + */ + +/* #define _RWSTD_NOT_ALL_WSTR_CFUNCTIONS 1 */ + +/* + * Uncomment the following your compiler does not define type wint_t + * in either wchar.h or wctype.h. + */ + +/* #define _RWSTD_NO_WINT_TYPE 1 */ + +/* + * Uncomment the following if your compiler does not provide wide + * character functions swscanf and swprintf. + */ + +/* #define _RWSTD_NO_SWPRINTF 1 */ + +/* + * Uncomment the following if your compiler cannot distinguish wchar_t from + * other integer types in template argument lists. + */ + +/* #define _RWSTD_NO_OVERLOAD_WCHAR 1 */ + + +/* + * Uncomment the following if your compiler does not support + * the ANSI C locale facility fully, or if it does not support + * it at all (in particular, uncomment if setlocale(), strxform(), + * or strcoll() are not present or don't work). + */ + +/* #define _RWSTD_NO_LOCALE 1 */ + + +/* + * Uncomment the following if your compiler does not have + * the %C directive to strftime(). + */ + +/* #define _RWSTD_NO_STRFTIME_CAPC 1 */ + + +/************************** TIME ********************************/ + +/* + * Uncomment the following if your compiler does not have global + * variables "_daylight", "_timezone", and "_tzname", or corresponding + * variables without a leading underscore (generally + * this is true only for pure Berkeley systems). + */ + +/* #define _RWSTD_NO_GLOBAL_TZ 1 */ + + +/* + * Uncomment the following if your system supplies a global variable + * named "daylight" instead of the nominally more correct "_daylight". + */ + +/* #define _RWSTD_NO_LEADING_UNDERSCORE 1 */ + + +/* + * If your system does not have global variables "daylight" and + * "timezone" (see directive immediately above) and does not have + * the Berkeley function gettimeofday() either, then uncomment + * the following: + */ + +/* #define _RWSTD_NO_GETTIMEOFDAY 1 */ + + +/* + * If the struct tm defined in your has extra member data + * "tm_zone" and "tm_gmtoff" (this is true for SunOs 4.X), then you + * should uncomment the following: + */ + +/* #define _RWSTD_STRUCT_TM_TZ 1 */ + + +/* Uncomment the following if you have a Solaris platform that + * supports threads. (We choose this if you have it, in + * preference to other thread packages. You may prefer a + * different package.) + */ + +/* #define _RWSTD_SOLARIS_THREADS 1 */ + +/* Uncomment the following if you have a threads package which + * meets an early Posix draft, and you don't have Solaris threads. + */ + +/* #define _RWSTD_POSIX_THREADS 1 */ + +/* As above, if you have threads which meet + * the Posix Draft 10 threads description. If you define this, + * then you must also define RW_POSIX_THREADS + */ + +/* #define _RWSTD_POSIX_D10_THREADS 1 */ + +/* Uncomment the following if pthread_mutexattr_default is + * provided by your threads package. The posix standard (draft 10) + * does not require a pthreads package to provide this value. + */ + +/* #define _RWSTD_MUTEXATTR_DEFAULT 1 */ + +/* Uncomment the following if you have no threads, or your package doesn't + * meet our expectations for header and function names. + */ + +/* #define _RWSTD_NO_THREADS 1 */ + + +/************************** STANDARD LIBRARY ****************************/ + +/* + * Uncomment the following if your compiler does not support the bool type. + * This means that bool is not a unique type. + */ + +/* #define _RWSTD_NO_BOOL 1 */ + +/* + * Uncomment the following if your compiler does not support simple + * default templates. e.g: + * template ... + */ + +/* #define _RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES 1 */ + +/* + * Uncomment the following if your compiler does not support complex + * default templates. e.g: + * template > ... + */ + +/* #define _RWSTD_NO_COMPLEX_DEFAULT_TEMPLATES 1 */ + +/* + * Uncomment the following if your compiler doesn't support ~T() + * where T is a builtin. + */ + +/* #define _RWSTD_NO_DESTROY_BUILTIN 1 */ + +/* + * Uncomment the following if your compiler doesn't support ~T() + * where T is a non-builtin. + */ + +/* #define _RWSTD_NO_DESTROY_NONBUILTIN 1 */ + +/* + * If your compiler does not support complicated exceptions, such as + * throwing a domain_error exception, then uncomment the following: + */ + +/* #define _RWSTD_NO_COMPLICATED_EXCEPTIONS 1 */ + +/* + * Uncomment the following if your compiler cannot handle nested + * templates, or if you have to define the body of a class within + * the template (mostly sun compilers!) + */ + +/* #define _RWSTD_NO_NESTING_TEMPLATES 1 */ + +/* + * If your compiler does not support long double operators in iostreams, then + * uncomment the following: + */ + +/* #define _RWSTD_NO_STREAM_LONG_DOUBLE 1 */ + +/* + * Uncomment the following if your compiler does not support the + * _MUTABLE keyword + */ + +/* #define _RWSTD_NO_MUTABLE 1 */ + +/* + * If your compiler does not support namespaces, uncomment the following + */ + +/* #define _RWSTD_NO_NAMESPACE 1 */ + +/* + * Uncomment the following if your compiler does not support + * member template functions: + * template class C { + * template void foo(); + * }; + */ + +/* #define _RWSTD_NO_MEMBER_TEMPLATES 1 */ + + +/* + * Uncomment the following if your compiler does not support + * member template classes: + * class C { + * template class N {}; + * }; + */ + +/* #define _RWSTD_NO_MEM_CLASS_TEMPLATES 1 */ + +/* + * Uncomment the following if your compiler does not support declaring a + * template function to be a friend: + * class C { + * template friend void foo (T); + * }; + */ + +/* #define _RWSTD_NO_FRIEND_TEMPLATES 1 */ + +/* + * If nontype-args are not allowed in function declarations, then uncomment + * the following. template void foo(char f[10][i]) + */ + +/* #define _RWSTD_NO_NONTYPE_ARGS 1 */ + +/* + * If simple static initialization of const member variables is not allowed, + * uncomment the following + */ + +/* #define _RWSTD_NO_STI_SIMPLE 1 */ + +/* + * If simple static initialization of const member variables in a + * template is not allowed, then uncomment the following + */ + +/* #define _RWSTD_NO_STI_TEMPLATE 1 */ + +/* + * If FLT_ROUNDS is a constant and not a variable, + * uncomment the following + */ + +/* #define _RWSTD_FLT_ROUNDS_IS_CONSTANT 1 */ + +/* + * If nested static template variables cannot be defined outside the + * class, uncomment this. +*/ + +/* #define _RWSTD_NO_STATIC_DEF 1 */ + +/* + * If static template variable definitions do not require initializers, + * uncomment this. + */ + +/* #define _RWSTD_NO_STATIC_DEF2 1 */ + + +/* + * If templatized static data members do not work correctly, uncomment this. + */ + +/* #define _RWSTD_NO_STATIC_DEF3 1 */ + + +/* + * Are long mangled names handled correctly by your compiler/linker? + * If not, uncomment the following + */ + +/* #define _RWSTD_NO_LONG_NAME 1 */ + +/* + * Are complicated typedefs handled by your compiler? + * If not, uncomment the following + */ + +/* #define _RWSTD_NO_COMPLICATED_TYPEDEF 1 */ + +/* + * Are embedded typedefs supported? + * If not, uncomment the following +*/ + +/* #define _RWSTD_NO_EMBEDDED_TYPEDEF 1 */ + +/* + * If your compiler does not support template template classes, then + * uncomment the following: + * template allocator> + */ + +/* #define _RWSTD_NO_TEMPLATE_TEMPLATE 1 */ + +/* + * If your compiler does not have a wchar_t type, uncomment + * the following + */ + +/* #define _RWSTD_NO_WIDE_CHAR 1 */ + +/* + * If your compiler does not have a wchar.h header file, uncomment + * the following + */ + +/* #define _RWSTD_NO_WCHAR_H 1 */ + +/* + * If your compiler does not handle typedef scoping correctly, + * then uncomment the following. + */ + +/* #define _RWSTD_NO_TYPEDEF_OVERLOAD 1 */ + +/* + * If your compiler does not function match on template base classes + * correctly, then uncomment the following. + */ + +/* #define _RWSTD_NO_BASE_CLASS_MATCH 1 */ + +/* + * If your compiler does not handle forward specializations + * correctly, then uncomment the following. + */ + +/* #define _RWSTD_NO_FORWARD_SPECIALIZATIONS 1 */ + +/* + * If your compiler does not handle template types as return types + * uncomment the following. + */ + +/* #define _RWSTD_NO_RET_TEMPLATE 1 */ + +/* + * If your compiler does not understand explicit constructors, uncomment + * the following. + */ + +/* #define _RWSTD_NO_EXPLICIT 1 */ + +/* + * If your compiler does not understand explicit argument qualification, + * uncomment the following. + */ + +/* #define _RWSTD_NO_EXPLICIT_ARG 1 */ + + +/* + * If your compiler does not understand the typename keyword, uncomment + * the following. + */ + +/* #define _RWSTD_NO_TYPENAME 1 */ + +/* + * Does your compiler instantiate typedefs of itself correctly? + * If not, uncomment the following + */ + +/* #define _RWSTD_NO_TYPEDEF_INST 1 */ + +/* + * Does your compiler instantiate templates with const types correctly? + * If not, uncomment the following + */ + +/* #define _RWSTD_NO_CONST_INST 1 */ + +/* + * Does your compiler assume trait typedefs are int? If not, uncomment + * the following + */ + +/* #define _RWSTD_NO_INT_TYPEDEF 1 */ + +/* + * Does your compiler give an ambiguity error on allocate()? If so, uncomment + * the following + */ + +/* #define _RWSTD_NO_ARG_MATCH 1 */ + +/* + * Does your compiler supply the new C++-style C headers? If not, + * uncomment the following + */ + +/* #define _RWSTD_NO_NEW_HEADER 1 */ + + +/* + * does your compiler provide a placement new definition? If no, + * uncomment the following + */ + +/* #define _RWSTD_NO_NEW_DECL 1 */ + +/* + * does your compiler inherit typedefs in templates correctly? If no, + * uncomment the following + */ + +/* #define _RWSTD_NO_INHERITED_TYPEDEFS 1 */ + +/* + * Does your compiler have difficulty with constructors in a return + * statement? If so then uncomment the following. + */ + +/* #define _RWSTD_NO_CTOR_RETURN 1 */ + +/* + * Does your compiler have difficulty with unDEFINED friends? If so + * then uncomment the following. + */ + +/* #define _RWSTD_NO_UNDEFINED_FRIEND 1 */ + +/* + * Does your compiler have trouble with structures that lack a default + * constructor even when their instantiation is indirect? If so + * then uncomment the following. + */ + +/* #define _RWSTD_NO_MEMBER_WO_DEF_CTOR 1 */ + +/* + * Does your compiler allow un-initialized static members? If not + * then uncomment the following. + */ + +/* #define _RWSTD_NO_UNINITIALIZED_STATIC_DEF 1 */ + +/* + * Does your compiler allow member types as template parameters? If not + * then uncomment the following. + */ + +/* #define _RWSTD_NO_MEMBER_TYPE_TPARAM 1 */ + +/* + * Does your compiler dis-allow the use of 'static' in the out of line + * initialization of a static const member? If so then uncomment the + * following. + */ + +/* #define _RWSTD_NO_STATIC_MEM_DEF 1 */ + +/* + * Does your compiler not allow default constructor syntax on built in + * types. (e.g. int i = int();). If so then uncomment the following. + */ + +/* #define _RWSTD_NO_BUILTIN_CTOR 1 */ + +/* Does your compiler not allow defaults for parameters in function + * templates when the function parameter is a template parameter type. + * If so then uncomment the following. + */ + +/* #define _RWSTD_NO_DEFAULT_FOR_TPARAM 1 */ + +/* Does your compiler not allow name injection. For instance, does it + * allow member function specializations to be declared but not defined, + * so that the template versions of these functions will be used. + * If not, then uncomment the following. + */ + +/* #define _RWSTD_NO_NAME_INJECTION 1 */ + +/* Does your compiler have problems overloading on function template + * arguments that are partial specializations? + * If so, then uncomment the following. + */ + +/* #define _RWSTD_NO_PART_SPEC_OVERLOAD 1 */ + +/* Does your compiler vendor supply wctype.h? + * If not, then uncomment the following. + */ + +/* #define _RWSTD_NO_WCTYPE_H 1 */ + +/* Can your compiler handle explicit instantiations? + * If not, then uncomment the following. + */ + +/* #define _RWSTD_NO_EXPLICIT_INSTANTIATION 1 */ + +/* Can your compiler handle explicit instantiations of + * function templates? + * If not, then uncomment the following. + */ + +/* #define _RWSTD_NO_EXPLICIT_FUNC_INSTANTIATION 1 */ + +/* If your compiler requires the non-standard + * include file , then uncomment the + * following. + */ + +/* #define _RWSTD_REQUIRES_IEEEFP 1 */ + +/* If your compiler typedefs long double to + * double, then uncomment the following. + */ + +/* #define _RWSTD_NO_LONGDOUBLE 1 */ + +/* If your compiler does not support static_cast<>, + then uncomment the following. +*/ + +/* #define _RWSTD_NO_STATIC_CAST 1 */ + +/* If your compiler doesn't support default values for const template + * reference arguements, then uncomment the following. + */ + +/* #define _RWSTD_NO_INIT_CONST_TEMPLATE_REF_ARG 1 */ + +/* If your compiler does not support using a template argument as a + * default parameter, then uncomment the following. + */ + +/* #define _RWSTD_NO_DEFAULT_TEMPLATE_ARGS 1 */ + +/* If your compiler does not support wide string null being + * defined as L"" but will work correctly when defined as L"\0", + * then uncomment the following. + */ +/* #define _RWSTD_WIDE_STRING_NULL_PROBLEM 1 */ + +/* If your compiler does not support partial specialisation + * of template function, then uncomment the following. + */ + +/* #define _RWSTD_NO_FUNC_PARTIAL_SPEC 1 */ + + +/* If your compiler does not support partial specialisation + * of template classes with default parameters, then uncomment + * the following. + */ + +/* #define _RWSTD_NO_CLASS_PARTIAL_SPEC 1 */ + +/* If your compiler does not support overload of template function, + * then uncomment the following. + */ + +/* #define _RWSTD_NO_OVERLOAD_OF_TEMPLATE_FUNCTION 1 */ + +/* If your compiler has difficulties with multi dimensional arrays of + * container classes, then uncomment the following. + */ + +/* #define _RWSTD_NO_MULTI_DIM_ARRAY 1 */ + +/* If your compiler does not provide a catopen/catgets style message + * catalog defined in header , then uncomment the following. + */ + +/* #define _RWSTD_NO_CATOPEN_CATGETS 1 */ + + +/* If the exception handler functions are located in namespace std, + * then uncomment the following. + */ + +/* #define _RWSTD_EXCEPTION_HANDLER_IN_STD 1 */ + +/* If your compiler has the class bad_alloc defined in new.h then + * uncomment the following. + */ + +/* #define _RWSTD_BAD_ALLOC_DEFINED 1 */ + +/* If your compiler has the exception classes already defined + * then uncomment the following. + */ + +/* #define _RWSTD_EXCEPTION_PREDEFINED 1 */ + +/* If your compiler has the class exception in its own exception + * file then uncomment the following. + */ + +/* #define _RWSTD_EXCEPTION_DEFINED 1 */ + +/* If your compiler has the class bad_exception in its own exception + * file then uncomment the following. + */ + +/* #define _RWSTD_BAD_EXCEPTION_DEFINED 1 */ + +/* If your compiler will not accept opterator::new[] + * then uncomment the following. + */ + +/* #define _RWSTD_NO_NEW_BRACKETS 1 */ + +/* If your compiler try to instantiate member function when + * creating variable of a class. + */ + +/* #define _RWSTD_NO_ONLY_NEEDED_INSTANTIATION 1 */ + +/* If your 'C' library does not provide overloads for the pow function + * (i.e. pow(float,float), and pow(long double, long double) if appropriate), + * then uncommment the following. + */ + +/* #define _RWSTD_NO_OVERLOAD_C_POW 1 */ + +/* If your compiler does not have an mbstate_t type then uncomment + * the following. + */ + +/* #define _RWSTD_NO_MBSTATE_T 1 */ + +/* If your compiler does not support the new template specialization + * syntax then umcomment the following + */ + +/* #define _RWSTD_NO_NEW_TEMPLATE_SYNTAX 1 */ + +/* If your compiler does not a have a throw specification on operator new + * then uncomment the following. + */ + +/* #define _RWSTD_NO_THROW_SPEC_ON_NEW 1 */ + +/* + * Uncomment this for EDG 2.36 + */ + +/* #define __NO_EDG_EXCEPTION_CLASSES=1 */ + +/* + * If you don't want to use RW extensions (to file streams) please + * uncomment this. See documentation for a detailed description about + * the class wise extensions added to the library. + */ + +/* #define _RWSTD_NO_EXTENSION 1 */ + +#ifdef __ARMCC_VERSION + /* library is compiled /ropi or /ropi/rwpi which does not allow + * initializing data with pointers to data + */ + #define ARM_NO_DATA_PTR_INIT 1 + // Enable iostream support for extra-long integer type. + #define _RWSTD_LONG_LONG __int64 + #define _RWSTD_LONG_LONG_PRINTF_PREFIX "ll" +#endif + + +/************************************************************************* +************************************************************************** +** ** +** From here on, it's pretty much boilerplate ** +** and rarely requires any tuning. ** +** ** +************************************************************************** +**************************************************************************/ + +/************************ Cfront derivatives ******************************/ + +/* Any of these defines a cfront style compiler: */ +#if defined(__ATT1__) || defined(__ATT2__) || defined(__ATT3__) +# define __ATT__ 1 +#endif + +#endif // !(__TURBOC__) && !(_MSC_VER) &&!(__OS2__) + +#define STARTWRAP +#define ENDWRAP + +#ifndef RW_NEVER_ENTER_DEFAULT_HEADER_BLOCK +#define RW_MESSAGE_SET_NUMBER 1 + +/* #define RW_INLINE86_ASSEMBLY 1 */ +/* #define RW_KR_ONLY 1 */ +/* #define RW_MESSAGE 1 */ +/* #define RW_NOT_POSIX_FSTAT 1 */ +/* #define RW_NO_OSTR_REF_CAST 1 */ + +#define RW_NO_POSIX_RE 1 + +/* #define RW_NO_SCHAR 1 */ +/* #define RW_NO_STRFTIME_CAPC 1 */ + +#define RW_NO_XMSG 1 + +/* #define __ATT2__ 1 */ +/* #define __ATT3__ 1 */ +/* #define __GLOCK__ 1 */ +/* #define RWOSVERSION 1 */ + +#define RWCOMPVERSION 120805 +#define RW_BYTES_PER_PTR 4 +#define RW_BYTES_PER_WORD 4 +#define RW_BYTES_PER_LONG 4 +#define RW_DEFAULT_PRECISION 16 + +/* #define RW_POSIX_D10_THREADS 1 */ +/* #define RW_DCE_THREADS 1 */ +/* #define RW_SOLARIS_THREADS 1 */ + +#define RW_NO_THREADS 1 + +/* #define RW_NO_DCE_PTHREAD_H 1 */ +/* #define RW_CMA_WRAPPERS 1 */ +/* #define RWSTD_WRAP_C 1 */ +/* #define _RWSTD_WRAP_C 1 */ +/* #define RWSTD_GLOBAL_ENUMS 1 */ +/* #define _RWSTD_NO_BOOL 1 */ +/* #define RWSTD_NO_BOOL 1 */ +/* #define RWSTD_NO_ACCESS_ADJUSTMENT 1 */ +/* #define RWSTD_BROKEN_ACCESS_ADJUST 1 */ +/* #define _RWSTD_BROKEN_ACCESS_ADJUST 1 */ +/* #define RWSTD_NO_CONST_OVERLOAD 1 */ + +#define _RWSTD_NO_EXCEPTIONS 1 +#define RWSTD_NO_EXCEPTIONS 1 + +/* #define RWSTD_NO_THROW_WITH_SHARED 1 */ +/* #define RWSTD_NO_OVERLOAD_UCHAR 1 */ +/* #define RWSTD_NO_OVERLOAD_SCHAR 1 */ +/* #define RWSTD_POSIX_D10_THREADS 1 */ +/* #define _RWSTD_POSIX_D10_THREADS 1 */ +/* #define RWSTD_DCE_THREADS 1 */ +/* #define _RWSTD_DCE_THREADS 1 */ +/* #define RWSTD_SOLARIS_THREADS 1 */ +/* #define _RWSTD_SOLARIS_THREADS 1 */ + +#define RWSTD_NO_THREADS 1 +#define _RWSTD_NO_THREADS 1 + +/* #define RWSTD_NO_DCE_PTHREAD_H 1 */ +/* #define _RWSTD_NO_DCE_PTHREAD_H 1 */ +/* #define RWSTD_NO_TYPENAME 1 */ +/* #define _RWSTD_NO_TYPENAME 1 */ + +#define RWSTD_COMPILE_INSTANTIATE 1 +#define _RWSTD_COMPILE_INSTANTIATE 1 + +/* #define RWSTD_HEADER_REQUIRES_HPP 1 */ +/* #define RWSTD_NO_ANSI_SPRINTF 1 */ + +#define RWSTD_NO_STRICMP 1 +#define RWSTD_NO_STRNICMP 1 +#define _RWSTD_NO_WCHAR_H 1 +#define RWSTD_NO_WCHAR_H 1 +#define RWSTD_NO_OVERLOAD_WCHAR 1 +#define _RWSTD_NO_OVERLOAD_WCHAR 1 +#define _RWSTD_NO_GLOBAL_TZ 1 + +/* #define _RWSTD_NO_LEADING_UNDERSCORE 1 */ +/* #define RWSTD_STRUCT_TM_TZ 1 */ +/* #define _RWSTD_STRUCT_TM_TZ 1 */ + +#define RWSTD_NO_WSTR 1 +#define _RWSTD_NO_WSTR 1 +#define RWSTD_NOT_ALL_WSTR_CFUNCTIONS 1 +#define _RWSTD_NOT_ALL_WSTR_CFUNCTIONS 1 + +/* #define RWSTD_SUPPLY_WSTR 1 */ +/* #define _RWSTD_SUPPLY_WSTR 1 */ +/* #define RWSTD_WSTR_C_HEADERS 1 */ +/* #define _RWSTD_WSTR_C_HEADERS 1 */ +/* #define RWSTD_USE_WCHEADERS 1 */ +/* #define _RWSTD_USE_WCHEADERS 1 */ + +#define RWSTD_NO_WCSXFRM 1 +#define _RWSTD_NO_WCSXFRM 1 + +/* #define RWSTD_NO_NEW_HEADER 1 */ +/* #define _RWSTD_NO_NEW_HEADER 1 */ +/* #define _RWSTD_NO_NEW_TEMPLATE_SYNTAX 1 */ +/* #define RWSTD_NO_NEW_TEMPLATE_SYNTAX 1 */ +/* #define _RWSTD_STRICT_ANSI 1 */ +/* #define RWSTD_STRICT_ANSI 1 */ +/* #define _RWSTD_BOUNDS_CHECKING 1 */ +/* #define RWSTD_BOUNDS_CHECKING 1 */ +/* #define _RWSTD_FAST_TEMP_BUF 1 */ +/* #define RWSTD_FAST_TEMP_BUF 1 */ +/* #define _RWSTD_ONE_STRING_MUTEX 1 */ +/* #define RWSTD_ONE_STRING_MUTEX 1 */ +/* #define _RWSTD_NO_FPOS_T 1 */ +/* #define RWSTD_NO_FPOS_T 1 */ +/* #define _RWSTD_NO_LDIV 1 */ +/* #define RWSTD_NO_LDIV 1 */ + +#define _RWSTD_NO_NAMESPACE 1 +#define RWSTD_NO_NAMESPACE 1 +#define _RWSTD_NO_WCTYPE_H 1 +#define RWSTD_NO_WCTYPE_H 1 +#define _RWSTD_NO_SWPRINTF 1 +#define RWSTD_NO_SWPRINTF 1 +#define _RWSTD_NO_WINT_TYPE 1 +#define RWSTD_NO_WINT_TYPE 1 + +/* #define _RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES 1 */ +/* #define RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES 1 */ + +#define _RWSTD_NO_COMPLEX_DEFAULT_TEMPLATES 1 +#define RWSTD_NO_COMPLEX_DEFAULT_TEMPLATES 1 + +/* #define _RWSTD_NO_DESTROY_BUILTIN 1 */ +/* #define RWSTD_NO_DESTROY_BUILTIN 1 */ +/* #define _RWSTD_EXPLICIT_SCOPE_DESTROY 1 */ +/* #define RWSTD_EXPLICIT_SCOPE_DESTROY 1 */ +/* #define _RWSTD_NO_DESTROY_NONBUILTIN 1 */ +/* #define RWSTD_NO_DESTROY_NONBUILTIN 1 */ +/* #define _RWSTD_NO_NESTING_TEMPLATES 1 */ +/* #define RWSTD_NO_NESTING_TEMPLATES 1 */ +/* #define _RWSTD_NO_NONTYPE_ARGS 1 */ +/* #define RWSTD_NO_NONTYPE_ARGS 1 */ +/* #define _RWSTD_NO_MUTABLE 1 */ +/* #define RWSTD_NO_MUTABLE 1 */ + +#define _RWSTD_NO_STREAM_LONG_DOUBLE 1 +#define RWSTD_NO_STREAM_LONG_DOUBLE 1 +#define _RWSTD_NO_BAD_CAST 1 +#define RWSTD_NO_BAD_CAST 1 + +/* #define _RWSTD_NO_MEMBER_TEMPLATES 1 */ +/* #define RWSTD_NO_MEMBER_TEMPLATES 1 */ +/* #define _RWSTD_NO_FRIEND_TEMPLATES 1 */ +/* #define RWSTD_NO_FRIEND_TEMPLATES 1 */ +/* #define _RWSTD_NO_TYPENAME 1 */ +/* #define RWSTD_NO_TYPENAME 1 */ +/* #define _RWSTD_NO_MEM_CLASS_TEMPLATES 1 */ +/* #define RWSTD_NO_MEM_CLASS_TEMPLATES 1 */ +/* #define _RWSTD_NO_STI_SIMPLE 1 */ +/* #define RWSTD_NO_STI_SIMPLE 1 */ +/* #define _RWSTD_NO_STI_TEMPLATE 1 */ +/* #define RWSTD_NO_STI_TEMPLATE 1 */ +/* #define _RWSTD_REQUIRES_IEEEFP 1 */ +/* #define RWSTD_REQUIRES_IEEEFP 1 */ + +#define _RWSTD_FLT_ROUNDS_IS_CONSTANT 1 +#define RWSTD_FLT_ROUNDS_IS_CONSTANT 1 + +/* #define _RWSTD_NO_STATIC_DEF 1 */ +/* #define RWSTD_NO_STATIC_DEF 1 */ +/* #define _RWSTD_NO_STATIC_DEF2 1 */ +/* #define RWSTD_NO_STATIC_DEF2 1 */ +/* #define _RWSTD_NO_STATIC_DEF3 1 */ +/* #define RWSTD_NO_STATIC_DEF3 1 */ +/* #define _RWSTD_NO_LONG_NAME 1 */ +/* #define RWSTD_NO_LONG_NAME 1 */ +/* #define _RWSTD_NO_COMPLICATED_TYPEDEF 1 */ +/* #define RWSTD_NO_COMPLICATED_TYPEDEF 1 */ +/* #define _RWSTD_NO_EMBEDDED_TYPEDEF 1 */ +/* #define RWSTD_NO_EMBEDDED_TYPEDEF 1 */ + +#define _RWSTD_NO_TEMPLATE_TEMPLATE 1 +#define RWSTD_NO_TEMPLATE_TEMPLATE 1 +#define _RWSTD_NO_WIDE_CHAR 1 +#define RWSTD_NO_WIDE_CHAR 1 + +/* #define _RWSTD_NO_LONGDOUBLE 1 */ +/* #define RWSTD_NO_LONGDOUBLE 1 */ + +#define _RWSTD_NO_STATIC_CAST 1 +#define RWSTD_NO_STATIC_CAST 1 + +/* #define _RWSTD_NO_CONST_CAST 1 */ +/* #define RWSTD_NO_CONST_CAST 1 */ +/* #define _RWSTD_NO_REINTERPRET_CAST 1 */ +/* #define RWSTD_NO_REINTERPRET_CAST 1 */ +/* #define _RWSTD_NO_EXPLICIT_ARG 1 */ +/* #define RWSTD_NO_EXPLICIT_ARG 1 */ +/* #define _RWSTD_NO_TYPEDEF_OVERLOAD 1 */ +/* #define RWSTD_NO_TYPEDEF_OVERLOAD 1 */ +/* #define _RWSTD_NO_BASE_CLASS_MATCH 1 */ +/* #define RWSTD_NO_BASE_CLASS_MATCH 1 */ +/* #define _RWSTD_NO_FO_RWARD_SPECIALIZATIONS 1 */ +/* #define RWSTD_NO_FO_RWARD_SPECIALIZATIONS 1 */ +/* #define _RWSTD_NO_RET_TEMPLATE 1 */ +/* #define RWSTD_NO_RET_TEMPLATE 1 */ +/* #define _RWSTD_NO_EXPLICIT 1 */ +/* #define RWSTD_NO_EXPLICIT 1 */ +/* #define _RWSTD_NO_TYPEDEF_INST 1 */ +/* #define RWSTD_NO_TYPEDEF_INST 1 */ +/* #define _RWSTD_NO_CONST_INST 1 */ +/* #define RWSTD_NO_CONST_INST 1 */ +/* #define _RWSTD_NO_INT_TYPEDEF 1 */ +/* #define RWSTD_NO_INT_TYPEDEF 1 */ +/* #define _RWSTD_NO_ARG_MATCH 1 */ +/* #define RWSTD_NO_ARG_MATCH 1 */ +/* #define _RWSTD_NO_NEW_DECL 1 */ +/* #define RWSTD_NO_NEW_DECL 1 */ +/* #define _RWSTD_NO_INHERITED_TYPEDEFS 1 */ +/* #define RWSTD_NO_INHERITED_TYPEDEFS 1 */ +/* #define _RWSTD_NO_CTOR_RETURN 1 */ +/* #define RWSTD_NO_CTOR_RETURN 1 */ +/* #define _RWSTD_NO_UNDEFINED_FRIEND 1 */ +/* #define RWSTD_NO_UNDEFINED_FRIEND 1 */ +/* #define _RWSTD_NO_MEMBER_WO_DEF_CTOR 1 */ +/* #define RWSTD_NO_MEMBER_WO_DEF_CTOR 1 */ +/* #define _RWSTD_NO_UNINITIALIZED_STATIC_DEF 1 */ +/* #define RWSTD_NO_UNINITIALIZED_STATIC_DEF 1 */ +/* #define _RWSTD_NO_MEMBER_TYPE_TPARAM 1 */ +/* #define RWSTD_NO_MEMBER_TYPE_TPARAM 1 */ + +#define _RWSTD_NO_STATIC_MEM_DEF 1 +#define RWSTD_NO_STATIC_MEM_DEF 1 + +/* #define _RWSTD_NO_DEFAULT_FOR_TPARAM 1 */ +/* #define RWSTD_NO_DEFAULT_FOR_TPARAM 1 */ +/* #define _RWSTD_NO_PART_SPEC_OVERLOAD 1 */ +/* #define RWSTD_NO_PART_SPEC_OVERLOAD 1 */ +/* #define _RWSTD_NO_EXPLICIT_INSTANTIATION 1 */ +/* #define RWSTD_NO_EXPLICIT_INSTANTIATION 1 */ +/* #define _RWSTD_NO_INIT_CONST_TEMPLATE_REF_ARG 1 */ +/* #define RWSTD_NO_INIT_CONST_TEMPLATE_REF_ARG 1 */ +/* #define _RWSTD_NO_CLASS_PARTIAL_SPEC 1 */ +/* #define RWSTD_NO_CLASS_PARTIAL_SPEC 1 */ +/* #define _RWSTD_NO_FUNC_PARTIAL_SPEC 1 */ +/* #define RWSTD_NO_FUNC_PARTIAL_SPEC 1 */ +/* #define _RWSTD_NO_OVERLOAD_OF_TEMPLATE_FUNCTION 1 */ +/* #define RWSTD_NO_OVERLOAD_OF_TEMPLATE_FUNCTION 1 */ +/* #define _RWSTD_NO_MULTI_DIM_ARRAY 1 */ +/* #define RWSTD_NO_MULTI_DIM_ARRAY 1 */ + +#define _RWSTD_NO_CATOPEN_CATGETS 1 +#define RWSTD_NO_CATOPEN_CATGETS 1 + +/* #define _RWSTD_EXCEPTION_HANDLER_IN_STD 1 */ +/* #define RWSTD_EXCEPTION_HANDLER_IN_STD 1 */ +/* #define _RWSTD_BAD_ALLOC_DEFINED 1 */ +/* #define RWSTD_BAD_ALLOC_DEFINED 1 */ +/* #define RWSTD_EXCEPTION_PREDEFINED 1 */ +/* #define _RWSTD_EXCEPTION_PREDEFINED 1 */ +/* #define _RWSTD_EXCEPTION_DEFINED 1 */ +/* #define _RWSTD_LOGIC_ERROR_PREDEFINED 1 */ +/* #define RWSTD_LOGIC_ERROR_PREDEFINED 1 */ +/* #define _RWSTD_BAD_EXCEPTION_DEFINED 1 */ +/* #define RWSTD_BAD_EXCEPTION_DEFINED 1 */ +/* #define _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE 1 */ +/* #define RWSTD_NO_TEMPLATE_ON_RETURN_TYPE 1 */ +/* #define _RWSTD_NO_NEW_BRACKETS 1 */ +/* #define RWSTD_NO_NEW_BRACKETS 1 */ +/* #define _RWSTD_NO_ONLY_NEEDED_INSTANTIATION 1 */ +/* #define RWSTD_NO_ONLY_NEEDED_INSTANTIATION 1 */ +/* #define _RWSTD_NO_EX_SPEC 1 */ +/* #define RWSTD_NO_EX_SPEC 1 */ +/* #define _RWSTD_NO_STRICT_TEMPLATE_INSTANTIATE 1 */ +/* #define RWSTD_NO_STRICT_TEMPLATE_INSTANTIATE 1 */ +/* #define _RWSTD_NO_NONCLASS_ARROW_RETURN 1 */ +/* #define RWSTD_NO_NONCLASS_ARROW_RETURN 1 */ +/* #define _RWSTD_NO_OVERLOAD_C_POW 1 */ +/* #define RWSTD_NO_OVERLOAD_C_POW 1 */ + +#define _RWSTD_NO_MBSTATE_T 1 +#define RWSTD_NO_MBSTATE_T 1 + +/* #define _RWSTD_NO_THROW_SPEC_ON_NEW 1 */ +/* #define RWSTD_NO_THROW_SPEC_ON_NEW 1 */ +/* #define _RWSTD_NOTHROW_IN_STD 1 */ +/* #define _RWSTD_NO_BUILTIN_CTOR 1 */ +/* #define RWSTD_NO_BUILTIN_CTOR 1 */ + +#define _RWSTD_ANSI_FILEIO 1 +#endif /* RW_NEVER_ENTER_DEFAULT_HEADER_BLOCK */ +// [Removed settings for various non-ARM compilers] + +/********************** Miscellaneous *********************************/ + +/* No Pi for these compilers: */ +#if defined(_RWSTD_MSC_BACKEND) || defined(__OREGON__) || defined(__HIGHC__) || defined(applec) || defined(CII) || defined(__WATCOMC__) +# ifndef M_PI +# define M_PI 3.14159265358979323846 +# endif +#endif + +/* + * Only Sun defines strftime("%C", ...) + */ +#if !defined(_RWSTD_NO_STRFTIME_CAPC) && !defined(sun) +#define _RWSTD_NO_STRFTIME_CAPC 1 +#endif + +#if defined(__SUNPRO_CC)&&(__SUNPRO_CC>=0x420) +#define _RWSTD_NO_TEMPLATE_STATIC_ID 1 +#define _RWSTD_NO_MBSTATE_COMPARE +#define _RWSTD_EXCEPTION_DEFINED +#endif + +/********************** Environment *********************************/ +/* + * This is the section for setting things which depend on the properties + * of the operating systems rather than specific compilers. It follows + * the compiler section so we have the chance to rationalize the different + * preprocessor constants (e.g. _MSDOS vs. __MSDOS__, _M_I86LM vs. __LARGE__) + */ + +#ifndef _RWSTD_DEFAULT_PRECISION +# define _RWSTD_DEFAULT_PRECISION 16 /* Assume standard IEEE format */ +#endif + +#if defined(__cplusplus)&&(__cplusplus >= 199707L) && defined(__STDCPP__) && (__STDCPP__ == 1) +#define _HPACC_ 1 +#undef _RWSTD_NO_NEW_HEADER +#if defined(__cplusplus)&&(__cplusplus >= 199711L) +#ifndef _RWSTD_BAD_ALLOC_DEFINED +#define _RWSTD_BAD_ALLOC_DEFINED +#endif +#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC +#define _RWSTD_NO_CLASS_PARTIAL_SPEC +#endif +#ifndef _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE +#define _RWSTD_NO_TEMPLATE_ON_RETURN_TYPE +#endif +#ifndef _RWSTD_NO_MEMBER_TEMPLATES +#define _RWSTD_NO_MEMBER_TEMPLATES +#endif +#endif +#endif + +/* + * Most (but not all) non-unix systems convert new line to carriage + * return / line feed on output: + */ +#if defined(__MSDOS__) || defined(__OS2__) || defined(__WIN32__) || defined(__NT__) || defined(__WINDOWS__) +# define _RWSTD_CRLF_CONVENTION 1 +#endif + +/* +** Miscellaneous workarounds. +*/ + +#ifdef _RWSTD_NO_BOOL +# ifdef _RWSTD_MSVC_BOOL_WARNING +# pragma warning ( disable : 4237 ) +# endif +typedef int bool; +# ifndef true +# define true 1 +# endif +# ifndef false +# define false 0 +# endif +#endif // _RWSTD_NO_BOOL + +#ifndef _RWSTD_NO_TYPENAME +#define _TYPENAME typename +#else +#define _TYPENAME +#endif + +#ifndef _RWSTD_NO_EXPLICIT +#define _EXPLICIT explicit +#else +#define _EXPLICIT +#endif + +#ifndef _RWSTD_NO_MUTABLE +#define _MUTABLE mutable +#else +#define _MUTABLE +#endif + +#ifndef _RWSTD_NO_TRICKY_INLINES +#define _RWSTD_TRICKY_INLINE inline +#else +#define _RWSTD_TRICKY_INLINE +#endif + +#ifdef _RWSTD_NO_MEMBER_WO_DEF_CTOR +#define _RWSTD_NO_CONST_INST 1 +#endif + +#if defined(_RWSTD_NO_STI_SIMPLE) && !defined(_RWSTD_NO_STI_TEMPLATE) +#define _RWSTD_NO_STI_TEMPLATE +#endif + +#ifdef _RWSTD_COMPILE_INSTANTIATE +/* explicit instantiation doesn't help if _RWSTD_COMPILE_INSTANTIATE */ +# define _RWSTD_NO_EXPLICIT_INSTANTIATION 1 +# define _RWSTD_NO_INSTANTIATE 1 +#endif + +#ifdef _RWSTD_NO_EXPLICIT_INSTANTIATION +# define _RWSTD_NO_EXPLICIT_FUNC_INSTANTIATION 1 +#endif + +#ifdef _RWSTD_NO_WIDE_CHAR +# ifndef _RWSTD_NO_OVERLOAD_WCHAR /* ARM: avoid redefinition warning */ +# define _RWSTD_NO_OVERLOAD_WCHAR 1 +# endif +# ifndef _RWSTD_NO_WSTR /* ARM: avoid redefinition warning */ +# define _RWSTD_NO_WSTR 1 +# endif +#endif + + +// +// Macro for forming or omitting default template arguments in constructors +// + +#ifndef _RWSTD_NO_DEFAULT_TEMPLATE_ARGS +# define _RWSTD_DEFAULT_ARG(n) = n +#else +# define _RWSTD_DEFAULT_ARG(n) +#endif + +// +// Macro for forming or ommitting default template parameters. +// +#ifndef _RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES +# define _RWSTD_SIMPLE_DEFAULT(a) = a +# ifndef _RWSTD_NO_COMPLEX_DEFAULT_TEMPLATES +# define _RWSTD_COMPLEX_DEFAULT(a) = a +# else +# define _RWSTD_COMPLEX_DEFAULT(a) +# endif +#else +# ifndef _RWSTD_NO_COMPLEX_DEFAULT_TEMPLATES +# define _RWSTD_NO_COMPLEX_DEFAULT_TEMPLATES +# endif +# define _RWSTD_SIMPLE_DEFAULT(a) +# define _RWSTD_COMPLEX_DEFAULT(a) +# ifndef _RWSTD_NO_DEFAULT_TEMPLATES +# define _RWSTD_NO_DEFAULT_TEMPLATES +# endif +#endif + +// +// Macros for adding 'std' or '__rwstd' to names +// +#ifndef _RWSTD_NO_NAMESPACE +# ifdef _MSC_VER +# define _RW_STD ::std +# define __RWSTD ::__rwstd +# else +# define _RW_STD std +# define __RWSTD __rwstd +# endif +#else +# define _RW_STD +# define __RWSTD +# endif + +// +// Macro for casting, using either the "old" method +// or the new C++ cast system +// + +#ifdef _RWSTD_NO_STATIC_CAST +# define _RWSTD_STATIC_CAST(x,y) ((x)(y)) +# define _RWSTD_REINTERPRET_CAST(x,y) ((x)(y)) +# define _RWSTD_CONST_CAST(x,y) ((x)(y)) +# define _RWSTD_REINTERPRET_CONST_CAST(x,y,z) ((x)(z)) +#else +# define _RWSTD_STATIC_CAST(x,y) static_cast< x >(y) +# define _RWSTD_REINTERPRET_CAST(x,y) reinterpret_cast< x >(y) +# define _RWSTD_CONST_CAST(x,y) const_cast< x >(y) +# define _RWSTD_REINTERPRET_CONST_CAST(x,y,z) reinterpret_cast< x >(const_cast< y >(z)) +#endif + +// +// Macro for the new template specialization syntax +// +#ifdef _RWSTD_NO_NEW_TEMPLATE_SYNTAX +# define _RWSTD_TEMPLATE +#else +# define _RWSTD_TEMPLATE template<> +#endif + +// +// If compiler supports member and default templates then it support +// the _RWSTD_ALLLOCATOR +// +#if !defined(_RWSTD_NO_MEMBER_TEMPLATES) && !defined(_RWSTD_NO_SIMPLE_DEFAULT_TEMPLATES) && !defined(_RWSTD_NO_MEM_CLASS_TEMPLATES) +#define _RWSTD_ALLOCATOR +#endif + +#ifdef _HPACC_ +#ifdef _RWSTD_ALLOCATOR +#undef _RWSTD_ALLOCATOR +#endif +#endif + +// +// Define typedef macro +// +#ifdef _RWSTD_NO_EMBEDDED_TYPEDEF +# define _RWSTD_ALLOC_SIZE_TYPE Allocator::size_type +# define _RWSTD_ALLOC_DIFF_TYPE Allocator::difference_type +#else +# define _RWSTD_ALLOC_SIZE_TYPE allocator_type::size_type +# define _RWSTD_ALLOC_DIFF_TYPE allocator_type::difference_type +#endif + +#define _RWSTD_MB_CUR_MAX 16 //??? Need to find absolute maximum for this + +#include + +// +// Define a generic macro for throw. To be used as in the following: +// +// _RWSTD_THROW(i < j && j < k, out_of_range, "j is out of range!"); +// +// ^ predicate ^ exception ^ message +// +// literally, if (predicate) throw exception(message) +// +#ifdef _RWSTD_NO_EXCEPTIONS +// +// If we don't have exceptions, then we'll use assert. +// We don't allow them to turn off the assert() in which such +// a thrown exception would result. +// + +#ifdef NDEBUG +#define __RW_NDEBUG +#undef NDEBUG +#endif +#ifdef NOT_FOR_ARM +#ifndef _RWSTD_NO_NEW_HEADER +#include +#else +#include +#endif +#define _RWSTD_THROW_NO_MSG(PRED,EXC) assert(!(PRED)) +#define _RWSTD_THROW(PRED,EXC,MESG) assert(!(PRED)) +#else +#define _RWSTD_NO_EX_MSGS 1 +extern "C" void __assert(const char *, const char *, int); +#define __cheap_assert(e) ((e) ? (void)0 : __assert(#e, __MODULE__, 0)) +#define _RWSTD_THROW_NO_MSG(PRED,EXC) __cheap_assert(!(PRED)) +#define _RWSTD_THROW(PRED,EXC,MESG) __cheap_assert(!(PRED)) +#endif +// +// We must also turn off expansion of assert() if that's what the user expects. +// +#ifdef __RW_NDEBUG +#define NDEBUG +#undef __RW_NDEBUG +#endif +#else /*!_RWSTD_NO_EXCEPTIONS*/ +// +// We must check to see if we can use or just a string. +// +#ifdef _RW_STD_EXCEPT +#define _RWSTD_THROW_NO_MSG(PRED,EXC) if (PRED) throw EXC() +#define _RWSTD_THROW(PRED,EXC,MESG) if (PRED) throw EXC(MESG) +#else +#define _RWSTD_THROW(PRED,EXC,MESG) if (PRED) throw (MESG) +#endif +#endif /*_RWSTD_NO_EXCEPTIONS*/ + +// +// Define two generic throw specification macros. One to illustrate +// the exceptions that a function can throw and the other to indicate +// that a function doesn't throw any exceptions. +// +// _RWSTD_THROW_SPEC(ExceptionList) +// +// _RWSTD_THROW_SPEC_NULL +// +// Owing to the face that the first macro must be able to take a +// variable number of arguments, we must simulate this by always +// passing the exceptions in parentheses; i.e. +// +// void f () _RWSTD_THROW_SPEC((out_of_range)); +// void g () _RWSTD_THROW_SPEC((domain_error, invalid_argument)); +// void h () _RWSTD_THROW_SPEC((out_of_range, invalid_argument, length_error)); +// + +#if defined(_RWSTD_NO_EXCEPTIONS) || defined(_RWSTD_NO_EX_SPEC) +#define _RWSTD_THROW_SPEC(EXCEPTIONS) /**/ +#define _RWSTD_THROW_SPEC_NULL /**/ +#else +#ifdef _RW_STD_EXCEPT +// +// _RWSTD_THROW will use the exceptions in +// +#define _RWSTD_THROW_SPEC(ExceptionList) throw ExceptionList +#define _RWSTD_THROW_SPEC_NULL throw() +#else +// +// _RWSTD_THROW will only throw const char * +// +#define _RWSTD_THROW_SPEC(ExceptionList) throw(const char *) +#define _RWSTD_THROW_SPEC_NULL throw() +#endif +#endif /*_RWSTD_NO_EXCEPTIONS||_RWSTD_NO_EX_SPEC*/ + +#ifndef _RWSTD_NO_TRICKY_INLINES +#define _RWSTD_INLINE_NO_THROW _RWSTD_THROW_SPEC_NULL +#else +#define _RWSTD_INLINE_NO_THROW +#endif + +// +// Macro for path to the ANSI 'C' headers +// Must be set specifically for each platform when the +// C++ wrappers for 'C' headers are used. +// +#define _RWSTD_ANSIC(x) + +#define _RWSTD_UNUNSED(x) ((void)(x)) + +#endif /*__RWSTDCOMPILER_H__*/ diff --git a/inc/C_H/stddef.h b/inc/C_H/stddef.h new file mode 100644 index 0000000..2163afc --- /dev/null +++ b/inc/C_H/stddef.h @@ -0,0 +1,100 @@ +/* stddef.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.1.4 */ + +/* Copyright (C) ARM Ltd., 1999 + * All rights reserved + * RCS $Revision: 1.8.2.4 $ + * Checkin $Date: 2001/07/13 15:08:14 $ + * Revising $Author: cadeniyi $ + */ + +/* Copyright (C) Codemist Ltd., 1988 */ +/* Copyright 1991 ARM Limited. All rights reserved. */ +/* version 0.05 */ + +/* + * The following types and macros are defined in several headers referred to in + * the descriptions of the functions declared in that header. They are also + * defined in this header file. + */ + +#ifndef __stddef_h +#define __stddef_h + + #ifndef __STDDEF_DECLS + #define __STDDEF_DECLS + #undef __CLIBNS + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + +typedef int ptrdiff_t; + +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) + /* unconditional in C++ and non-strict C for consistency of debug info */ + typedef unsigned int size_t; +#elif !defined(__size_t) + #define __size_t 1 + typedef unsigned int size_t; /* others (e.g. ) also define */ + /* the unsigned integral type of the result of the sizeof operator. */ +#endif + +#ifndef __cplusplus /* wchar_t is a builtin type for C++ */ + #if !defined(__STRICT_ANSI__) + /* unconditional in non-strict C for consistency of debug info */ + typedef unsigned short wchar_t; /* also in and */ + #elif !defined(__wchar_t) + #define __wchar_t 1 + typedef unsigned short wchar_t; /* also in and */ + /* + * An integral type whose range of values can represent distinct codes for + * all members of the largest extended character set specified among the + * supported locales; the null character shall have the code value zero and + * each member of the basic character set shall have a code value when used + * as the lone character in an integer character constant. + */ + #endif +#endif + +#undef NULL /* others (e.g. ) also define */ +#define NULL 0 + /* null pointer constant. */ + +#define offsetof(type, member) \ + ((__CLIBNS size_t)((char *)&(((type *)0)->member) - (char *)0)) + /* + * expands to an integral constant expression that has type size_t, the + * value of which is the offset in bytes, from the beginning of a structure + * designated by type, of the member designated by the identifier (if the + * specified member is a bit-field, the behaviour is undefined). + */ + + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __STDDEF_DECLS */ + + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __STDDEF_NO_EXPORTS + using std::size_t; + using std::ptrdiff_t; + #endif + #endif + +#endif + +/* end of stddef.h */ diff --git a/inc/C_H/stdint.h b/inc/C_H/stdint.h new file mode 100644 index 0000000..80d8e5a --- /dev/null +++ b/inc/C_H/stdint.h @@ -0,0 +1,267 @@ +/* Copyright (C) ARM Ltd., 1999 */ +/* All rights reserved */ + +/* + * RCS $Revision: 1.4.2.1 $ + * Checkin $Date: 2001/02/22 16:23:36 $ + * Revising $Author: cadeniyi $ + */ + +/* Based on WG14/N843 (C9X) Committee Draft August 3, 1998 */ + +#ifndef __stdint_h +#define __stdint_h + + #ifndef __STDINT_DECLS + #define __STDINT_DECLS + + #undef __CLIBNS + + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + + +/* + * 'signed' is redundant below, except for 'signed char' and if + * the typedef is used to declare a bitfield. + * '__int64' is used instead of 'long long' so that this header + * can be used in -strict mode. + */ + + /* 7.18.1.1 */ + + /* exact-width signed integer types */ +typedef signed char int8_t; +typedef signed short int int16_t; +typedef signed int int32_t; +typedef signed __int64 int64_t; + + /* exact-width unsigned integer types */ +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned __int64 uint64_t; + + /* 7.18.1.2 */ + + /* smallest type of at least n bits */ + /* minimum-width signed integer types */ +typedef signed char int_least8_t; +typedef signed short int int_least16_t; +typedef signed int int_least32_t; +typedef signed __int64 int_least64_t; + + /* minimum-width unsigned integer types */ +typedef unsigned char uint_least8_t; +typedef unsigned short int uint_least16_t; +typedef unsigned int uint_least32_t; +typedef unsigned __int64 uint_least64_t; + + /* 7.18.1.3 */ + + /* fastest minimum-width signed integer types */ +typedef signed int int_fast8_t; +typedef signed int int_fast16_t; +typedef signed int int_fast32_t; +typedef signed __int64 int_fast64_t; + + /* fastest minimum-width unsigned integer types */ +typedef unsigned int uint_fast8_t; +typedef unsigned int uint_fast16_t; +typedef unsigned int uint_fast32_t; +typedef unsigned __int64 uint_fast64_t; + + /* 7.18.1.4 integer types capable of holding object pointers */ +typedef signed int intptr_t; +typedef unsigned int uintptr_t; + + /* 7.18.1.5 greatest-width integer types */ +typedef signed __int64 intmax_t; +typedef unsigned __int64 uintmax_t; + + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) + + /* 7.18.2.1 */ + + /* minimum values of exact-width signed integer types */ +#define INT8_MIN -128 +#define INT16_MIN -32768 +#define INT32_MIN (~0x7fffffff) /* -2147483648 is unsigned */ +#define INT64_MIN (~0x7fffffffffffffffll) /* -9223372036854775808 is unsigned */ + + /* maximum values of exact-width signed integer types */ +#define INT8_MAX 127 +#define INT16_MAX 32767 +#define INT32_MAX 2147483647 +#define INT64_MAX 9223372036854775807ll + + /* maximum values of exact-width unsigned integer types */ +#define UINT8_MAX 255 +#define UINT16_MAX 65535 +#define UINT32_MAX 4294967295u +#define UINT64_MAX 18446744073709551615ull + + /* 7.18.2.2 */ + + /* minimum values of minimum-width signed integer types */ +#define INT_LEAST8_MIN -128 +#define INT_LEAST16_MIN -32768 +#define INT_LEAST32_MIN (~0x7fffffff) +#define INT_LEAST64_MIN (~0x7fffffffffffffffll) + + /* maximum values of minimum-width signed integer types */ +#define INT_LEAST8_MAX 127 +#define INT_LEAST16_MAX 32767 +#define INT_LEAST32_MAX 2147483647 +#define INT_LEAST64_MAX 9223372036854775807ll + + /* maximum values of minimum-width unsigned integer types */ +#define UINT_LEAST8_MAX 255 +#define UINT_LEAST16_MAX 65535 +#define UINT_LEAST32_MAX 4294967295u +#define UINT_LEAST64_MAX 18446744073709551615ull + + /* 7.18.2.3 */ + + /* minimum values of fastest minimum-width signed integer types */ +#define INT_FAST8_MIN (~0x7fffffff) +#define INT_FAST16_MIN (~0x7fffffff) +#define INT_FAST32_MIN (~0x7fffffff) +#define INT_FAST64_MIN (~0x7fffffffffffffffll) + + /* maximum values of fastest minimum-width signed integer types */ +#define INT_FAST8_MAX 2147483647 +#define INT_FAST16_MAX 2147483647 +#define INT_FAST32_MAX 2147483647 +#define INT_FAST64_MAX 9223372036854775807ll + + /* maximum values of fastest minimum-width unsigned integer types */ +#define UINT_FAST8_MAX 4294967295u +#define UINT_FAST16_MAX 4294967295u +#define UINT_FAST32_MAX 4294967295u +#define UINT_FAST64_MAX 18446744073709551615ull + + /* 7.18.2.4 */ + + /* minimum value of pointer-holding signed integer type */ +#define INTPTR_MIN (~0x7fffffff) + + /* maximum value of pointer-holding signed integer type */ +#define INTPTR_MAX 2147483647 + + /* maximum value of pointer-holding unsigned integer type */ +#define UINTPTR_MAX 4294967295u + + /* 7.18.2.5 */ + + /* minimum value of greatest-width signed integer type */ +#define INTMAX_MIN (~0x7fffffffffffffffll) + + /* maximum value of greatest-width signed integer type */ +#define INTMAX_MAX 9223372036854775807ll + + /* maximum value of greatest-width unsigned integer type */ +#define UINTMAX_MAX 18446744073709551615ull + + /* 7.18.3 */ + + /* limits of ptrdiff_t */ +#define PTRDIFF_MIN (~0x7fffffff) +#define PTRDIFF_MAX 2147483647 + + /* limits of sig_atomic_t */ +#define SIG_ATOMIC_MIN (~0x7fffffff) +#define SIG_ATOMIC_MAX 2147483647 + + /* limit of size_t */ +#define SIZE_MAX 4294967295u + + /* limits of wchar_t */ +#define WCHAR_MIN 0 +#define WCHAR_MAX 65535 + +#if 0 /* wint_t not yet supported */ + /* limits of wint_t */ +#define WINT_MIN ? +#define WINT_MAX ? +#endif + +#endif /* __STDC_LIMIT_MACROS */ + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) + + /* 7.18.4.1 macros for minimum-width integer constants */ +#define INT8_C(x) (x) +#define INT16_C(x) (x) +#define INT32_C(x) (x) +#define INT64_C(x) (x ## ll) + +#define UINT8_C(x) (x ## u) +#define UINT16_C(x) (x ## u) +#define UINT32_C(x) (x ## u) +#define UINT64_C(x) (x ## ull) + + /* 7.18.4.2 macros for greatest-width integer constants */ +#define INTMAX_C(x) (x ## ll) +#define UINTMAX_C(x) (x ## ull) + +#endif /* __STDC_CONSTANT_MACROS */ + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __STDINT_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __STDINT_NO_EXPORTS + using std::int8_t; + using std::int16_t; + using std::int32_t; + using std::int64_t; + using std::uint8_t; + using std::uint16_t; + using std::uint32_t; + using std::uint64_t; + using std::int_least8_t; + using std::int_least16_t; + using std::int_least32_t; + using std::int_least64_t; + using std::uint_least8_t; + using std::uint_least16_t; + using std::uint_least32_t; + using std::uint_least64_t; + using std::int_fast8_t; + using std::int_fast16_t; + using std::int_fast32_t; + using std::int_fast64_t; + using std::uint_fast8_t; + using std::uint_fast16_t; + using std::uint_fast32_t; + using std::uint_fast64_t; + using std::intptr_t; + using std::uintptr_t; + using std::intmax_t; + using std::uintmax_t; + #endif + #endif + +#endif /* __stdint_h */ + +/* end of stdint.h */ + + diff --git a/inc/C_H/stdio.h b/inc/C_H/stdio.h new file mode 100644 index 0000000..32305f5 --- /dev/null +++ b/inc/C_H/stdio.h @@ -0,0 +1,896 @@ +/* stdio.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.9 */ +/* Copyright (C) Codemist Ltd., 1988-1993 */ +/* Copyright 1991-1998 ARM Limited. All rights reserved. */ + +/* + * RCS $Revision: 1.22.2.3 $ + * Checkin $Date: 2001/05/23 21:56:08 $ + * Revising $Author: sdouglas $ + */ + +/* + * stdio.h declares two types, several macros, and many functions for + * performing input and output. For a discussion on Streams and Files + * refer to sections 4.9.2 and 4.9.3 in the above ANSI draft, or to a + * modern textbook on C. + */ + +#ifndef __stdio_h +#define __stdio_h + + #ifndef __STDIO_DECLS + #define __STDIO_DECLS + + #undef __CLIBNS + + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + + #if defined(__cplusplus) || !defined(__STRICT_ANSI__) + /* unconditional in C++ and non-strict C for consistency of debug info */ + typedef unsigned int size_t; + #elif !defined(__size_t) + #define __size_t 1 + typedef unsigned int size_t; /* see */ + #endif + + #undef NULL + #define NULL 0 /* see */ + +/* ANSI forbids va_list to be defined here */ +typedef int *__va_list[1]; /* keep in step with */ + +typedef struct __fpos_t_struct +{ unsigned long __lo; /* add hi one day */ +} fpos_t; + /* + * fpos_t is an object capable of recording all information needed to + * specify uniquely every position within a file. + */ + +typedef struct __FILE FILE; + /* + * FILE is an object capable of recording all information needed to control + * a stream, such as its file position indicator, a pointer to its + * associated buffer, an error indicator that records whether a read/write + * error has occurred and an end-of-file indicator that records whether the + * end-of-file has been reached. + * Its structure is not made known to library clients. + */ + +#define _IOFBF 0x100 /* fully buffered IO */ +#define _IOLBF 0x200 /* line buffered IO */ +#define _IONBF 0x400 /* unbuffered IO */ + + /* + * _IOBIN is the flag passed to _sys_write to denote a binary + * file. + */ +#define _IOBIN 0x04 /* binary stream */ + + /* Various default file IO buffer sizes */ +#define BUFSIZ (512) /* system buffer size (as used by setbuf) */ +#define STDIN_BUFSIZ (64) /* default stdin buffer size */ +#define STDOUT_BUFSIZ (64) /* default stdout buffer size */ +#define STDERR_BUFSIZ (16) /* default stderr buffer size */ + +#define EOF (-1) + /* + * negative integral constant, indicates end-of-file, that is, no more input + * from a stream. + */ +#define _SYS_OPEN 16 + /* _SYS_OPEN defines a limit on the number of open files that is imposed + * by this C library + */ +#define FOPEN_MAX _SYS_OPEN + /* + * an integral constant expression that is the minimum number of files that + * this implementation guarantees can be open simultaneously. + */ + +#define FILENAME_MAX 80 + /* + * an integral constant expression that is the size of an array of char + * large enough to hold the longest filename string + */ +#define L_tmpnam FILENAME_MAX + /* + * an integral constant expression that is the size of an array of char + * large enough to hold a temporary file name string generated by the + * tmpnam function. + */ + +#define SEEK_SET 0 /* start of stream (see fseek) */ +#define SEEK_CUR 1 /* current position in stream (see fseek) */ +#define SEEK_END 2 /* end of stream (see fseek) */ + +#define TMP_MAX 256 + /* + * an integral constant expression that is the minimum number of unique + * file names that shall be generated by the tmpnam function. + */ + +extern FILE __stdin, __stdout, __stderr; + +#define stdin (&__CLIBNS __stdin) + /* pointer to a FILE object associated with standard input stream */ +#define stdout (&__CLIBNS __stdout) + /* pointer to a FILE object associated with standard output stream */ +#define stderr (&__CLIBNS __stderr) + /* pointer to a FILE object associated with standard error stream */ + +extern int remove(const char * /*filename*/); + /* + * causes the file whose name is the string pointed to by filename to be + * removed. Subsequent attempts to open the file will fail, unless it is + * created anew. If the file is open, the behaviour of the remove function + * is implementation-defined. + * Returns: zero if the operation succeeds, nonzero if it fails. + */ +extern int rename(const char * /*old*/, const char * /*new*/); + /* + * causes the file whose name is the string pointed to by old to be + * henceforth known by the name given by the string pointed to by new. The + * file named old is effectively removed. If a file named by the string + * pointed to by new exists prior to the call of the rename function, the + * behaviour is implementation-defined. + * Returns: zero if the operation succeeds, nonzero if it fails, in which + * case if the file existed previously it is still known by its + * original name. + */ +extern FILE *tmpfile(void); + /* + * creates a temporary binary file that will be automatically removed when + * it is closed or at program termination. The file is opened for update. + * Returns: a pointer to the stream of the file that it created. If the file + * cannot be created, a null pointer is returned. + */ +extern char *tmpnam(char * /*s*/); + /* + * generates a string that is not the same as the name of an existing file. + * The tmpnam function generates a different string each time it is called, + * up to TMP_MAX times. If it is called more than TMP_MAX times, the + * behaviour is implementation-defined. + * Returns: If the argument is a null pointer, the tmpnam function leaves + * its result in an internal static object and returns a pointer to + * that object. Subsequent calls to the tmpnam function may modify + * the same object. if the argument is not a null pointer, it is + * assumed to point to an array of at least L_tmpnam characters; + * the tmpnam function writes its result in that array and returns + * the argument as its value. + */ + +extern int fclose(FILE * /*stream*/); + /* + * causes the stream pointed to by stream to be flushed and the associated + * file to be closed. Any unwritten buffered data for the stream are + * delivered to the host environment to be written to the file; any unread + * buffered data are discarded. The stream is disassociated from the file. + * If the associated buffer was automatically allocated, it is deallocated. + * Returns: zero if the stream was succesfully closed, or nonzero if any + * errors were detected or if the stream was already closed. + */ +extern int fflush(FILE * /*stream*/); + /* + * If the stream points to an output or update stream in which the most + * recent operation was output, the fflush function causes any unwritten + * data for that stream to be delivered to the host environment to be + * written to the file. If the stream points to an input or update stream, + * the fflush function undoes the effect of any preceding ungetc operation + * on the stream. + * Returns: nonzero if a write error occurs. + */ +extern FILE *fopen(const char * /*filename*/, const char * /*mode*/); + /* + * opens the file whose name is the string pointed to by filename, and + * associates a stream with it. + * The argument mode points to a string beginning with one of the following + * sequences: + * "r" open text file for reading + * "w" create text file for writing, or truncate to zero length + * "a" append; open text file or create for writing at eof + * "rb" open binary file for reading + * "wb" create binary file for writing, or truncate to zero length + * "ab" append; open binary file or create for writing at eof + * "r+" open text file for update (reading and writing) + * "w+" create text file for update, or truncate to zero length + * "a+" append; open text file or create for update, writing at eof + * "r+b"/"rb+" open binary file for update (reading and writing) + * "w+b"/"wb+" create binary file for update, or truncate to zero length + * "a+b"/"ab+" append; open binary file or create for update, writing at eof + * + * Opening a file with read mode ('r' as the first character in the mode + * argument) fails if the file does not exist or cannot be read. + * Opening a file with append mode ('a' as the first character in the mode + * argument) causes all subsequent writes to be forced to the current end of + * file, regardless of intervening calls to the fseek function. In some + * implementations, opening a binary file with append mode ('b' as the + * second or third character in the mode argument) may initially position + * the file position indicator beyond the last data written, because of the + * NUL padding. + * When a file is opened with update mode ('+' as the second or third + * character in the mode argument), both input and output may be performed + * on the associated stream. However, output may not be directly followed + * by input without an intervening call to the fflush fuction or to a file + * positioning function (fseek, fsetpos, or rewind), and input be not be + * directly followed by output without an intervening call to the fflush + * fuction or to a file positioning function, unless the input operation + * encounters end-of-file. Opening a file with update mode may open or + * create a binary stream in some implementations. When opened, a stream + * is fully buffered if and only if it does not refer to an interactive + * device. The error and end-of-file indicators for the stream are + * cleared. + * Returns: a pointer to the object controlling the stream. If the open + * operation fails, fopen returns a null pointer. + */ +extern FILE *freopen(const char * /*filename*/, const char * /*mode*/, + FILE * /*stream*/); + /* + * opens the file whose name is the string pointed to by filename and + * associates the stream pointed to by stream with it. The mode argument is + * used just as in the fopen function. + * The freopen function first attempts to close any file that is associated + * with the specified stream. Failure to close the file successfully is + * ignored. The error and end-of-file indicators for the stream are cleared. + * Returns: a null pointer if the operation fails. Otherwise, freopen + * returns the value of the stream. + */ +extern void setbuf(FILE * /*stream*/, char * /*buf*/); + /* + * Except that it returns no value, the setbuf function is equivalent to the + * setvbuf function invoked with the values _IOFBF for mode and BUFSIZ for + * size, or (if buf is a null pointer), with the value _IONBF for mode. + * Returns: no value. + */ +extern int setvbuf(FILE * /*stream*/, char * /*buf*/, + int /*mode*/, size_t /*size*/); + /* + * may be used after the stream pointed to by stream has been associated + * with an open file but before it is read or written. The argument mode + * determines how stream will be buffered, as follows: _IOFBF causes + * input/output to be fully buffered; _IOLBF causes output to be line + * buffered (the buffer will be flushed when a new-line character is + * written, when the buffer is full, or when input is requested); _IONBF + * causes input/output to be completely unbuffered. If buf is not the null + * pointer, the array it points to may be used instead of an automatically + * allocated buffer (the buffer must have a lifetime at least as great as + * the open stream, so the stream should be closed before a buffer that has + * automatic storage duration is deallocated upon block exit). The argument + * size specifies the size of the array. The contents of the array at any + * time are indeterminate. + * Returns: zero on success, or nonzero if an invalid value is given for + * mode or size, or if the request cannot be honoured. + */ +#ifdef __EDG__ +#pragma __printf_args +#else +#pragma check_printf_formats /* hint to the compiler to check f/s/printf format */ +#endif +extern int fprintf(FILE * /*stream*/, const char * /*format*/, ...); + /* + * writes output to the stream pointed to by stream, under control of the + * string pointed to by format that specifies how subsequent arguments are + * converted for output. If there are insufficient arguments for the format, + * the behaviour is undefined. If the format is exhausted while arguments + * remain, the excess arguments are evaluated but otherwise ignored. The + * fprintf function returns when the end of the format string is reached. + * The format shall be a multibyte character sequence, beginning and ending + * in its initial shift state. The format is composed of zero or more + * directives: ordinary multibyte characters (not %), which are copied + * unchanged to the output stream; and conversion specifiers, each of which + * results in fetching zero or more subsequent arguments. Each conversion + * specification is introduced by the character %. For a description of the + * available conversion specifiers refer to section 4.9.6.1 in the ANSI + * draft mentioned at the start of this file or to any modern textbook on C. + * The minimum value for the maximum number of characters producable by any + * single conversion is at least 509. + * Returns: the number of characters transmitted, or a negative value if an + * output error occurred. + */ +#ifdef __EDG__ +#pragma __printf_args +#endif +extern int _fprintf(FILE * /*stream*/, const char * /*format*/, ...); + /* + * is equivalent to fprintf, but does not support floating-point formats. + * You can use instead of fprintf to improve code size. + * Returns: as fprintf. + */ +#ifdef __EDG__ +#pragma __printf_args +#endif +extern int printf(const char * /*format*/, ...); + /* + * is equivalent to fprintf with the argument stdout interposed before the + * arguments to printf. + * Returns: the number of characters transmitted, or a negative value if an + * output error occurred. + */ +#ifdef __EDG__ +#pragma __printf_args +#endif +extern int _printf(const char * /*format*/, ...); + /* + * is equivalent to printf, but does not support floating-point formats. + * You can use instead of printf to improve code size. + * Returns: as printf. + */ +#ifdef __EDG__ +#pragma __printf_args +#endif +extern int sprintf(char * /*s*/, const char * /*format*/, ...); + /* + * is equivalent to fprintf, except that the argument s specifies an array + * into which the generated output is to be written, rather than to a + * stream. A null character is written at the end of the characters written; + * it is not counted as part of the returned sum. + * Returns: the number of characters written to the array, not counting the + * terminating null character. + */ +#ifdef __EDG__ +#pragma __printf_args +#endif +extern int _sprintf(char * /*s*/, const char * /*format*/, ...); + /* + * is equivalent to sprintf, but does not support floating-point formats. + * You can use instead of sprintf to improve code size. + * Returns: as sprintf. + */ +#ifndef __STRICT_ANSI__ +#ifdef __EDG__ +#pragma __printf_args +#endif +extern int snprintf(char * /*s*/, size_t /*n*/, const char * /*format*/, ...); + /* + * is equivalent to fprintf, except that the argument s specifies an array + * into which the generated output is to be written, rather than to a + * stream. The argument n specifies the size of the output array, so as to + * avoid overflowing the buffer. + * A null character is written at the end of the characters written, even + * if the formatting was not completed; it is not counted as part of the + * returned sum. At most n characters of the output buffer are used, + * _including_ the null character. + * Returns: the number of characters that would have been written to the + * array, not counting the terminating null character, if the + * array had been big enough. So if the return is >=0 and =n, the string was truncated (but there is still a null char + * at the end of what was written); if the return is <0, there was + * an error. + */ +#endif +#ifdef __EDG__ +#pragma __printf_args +#endif +extern int _snprintf(char * /*s*/, size_t /*n*/, const char * /*format*/, ...); + /* + * is equivalent to snprintf, but does not support floating-point formats. + * You can use instead of snprintf to improve code size. + * Returns: as snprintf. + */ +#ifdef __EDG__ +#pragma __scanf_args +#else +#pragma no_check_printf_formats /* back to default */ +#pragma check_scanf_formats /* hint to the compiler to check f/s/scanf format */ +#endif +extern int fscanf(FILE * /*stream*/, const char * /*format*/, ...); + /* + * reads input from the stream pointed to by stream, under control of the + * string pointed to by format that specifies the admissible input sequences + * and how thay are to be converted for assignment, using subsequent + * arguments as pointers to the objects to receive the converted input. If + * there are insufficient arguments for the format, the behaviour is + * undefined. If the format is exhausted while arguments remain, the excess + * arguments are evaluated but otherwise ignored. + * The format is composed of zero or more directives: one or more + * white-space characters; an ordinary character (not %); or a conversion + * specification. Each conversion specification is introduced by the + * character %. For a description of the available conversion specifiers + * refer to section 4.9.6.2 in the ANSI draft mentioned at the start of this + * file, or to any modern textbook on C. + * If end-of-file is encountered during input, conversion is terminated. If + * end-of-file occurs before any characters matching the current directive + * have been read (other than leading white space, where permitted), + * execution of the current directive terminates with an input failure; + * otherwise, unless execution of the current directive is terminated with a + * matching failure, execution of the following directive (if any) is + * terminated with an input failure. + * If conversions terminates on a conflicting input character, the offending + * input character is left unread in the input strem. Trailing white space + * (including new-line characters) is left unread unless matched by a + * directive. The success of literal matches and suppressed asignments is + * not directly determinable other than via the %n directive. + * Returns: the value of the macro EOF if an input failure occurs before any + * conversion. Otherwise, the fscanf function returns the number of + * input items assigned, which can be fewer than provided for, or + * even zero, in the event of an early conflict between an input + * character and the format. + */ +extern int _fscanf(FILE * /*stream*/, const char * /*format*/, ...); + /* + * is equivalent to fscanf, but does not support floating-point formats. + * You can use instead of fscanf to improve code size. + * Returns: as fscanf. + */ +#ifdef __EDG__ +#pragma __scanf_args +#endif +extern int scanf(const char * /*format*/, ...); + /* + * is equivalent to fscanf with the argument stdin interposed before the + * arguments to scanf. + * Returns: the value of the macro EOF if an input failure occurs before any + * conversion. Otherwise, the scanf function returns the number of + * input items assigned, which can be fewer than provided for, or + * even zero, in the event of an early matching failure. + */ +#ifdef __EDG__ +#pragma __scanf_args +#endif +extern int _scanf(const char * /*format*/, ...); + /* + * is equivalent to scanf, but does not support floating-point formats. + * You can use instead of scanf to improve code size. + * Returns: as scanf. + */ +#ifdef __EDG__ +#pragma __scanf_args +#endif +extern int sscanf(const char * /*s*/, const char * /*format*/, ...); + /* + * is equivalent to fscanf except that the argument s specifies a string + * from which the input is to be obtained, rather than from a stream. + * Reaching the end of the string is equivalent to encountering end-of-file + * for the fscanf function. + * Returns: the value of the macro EOF if an input failure occurs before any + * conversion. Otherwise, the scanf function returns the number of + * input items assigned, which can be fewer than provided for, or + * even zero, in the event of an early matching failure. + */ +#ifdef __EDG__ +#pragma __scanf_args +#endif +extern int _sscanf(const char * /*s*/, const char * /*format*/, ...); + /* + * is equivalent to sscanf, but does not support floating-point formats. + * You can use instead of sscanf to improve code size. + * Returns: as sscanf. + */ +#ifndef __EDG__ +#pragma no_check_scanf_formats /* back to default */ +#pragma check_vprintf_formats /* hint to the compiler to examine vf/s/snprintf format */ +#endif +extern int vprintf(const char * /*format*/, __va_list /*arg*/); + /* + * is equivalent to printf, with the variable argument list replaced by arg, + * which has been initialised by the va_start macro (and possibly subsequent + * va_arg calls). The vprintf function does not invoke the va_end function. + * Returns: the number of characters transmitted, or a negative value if an + * output error occurred. + */ +extern int _vprintf(const char * /*format*/, __va_list /*arg*/); + /* + * is equivalent to vprintf, but does not support floating-point formats. + * You can use instead of vprintf to improve code size. + * Returns: as vprintf. + */ +extern int vfprintf(FILE * /*stream*/, + const char * /*format*/, __va_list /*arg*/); + /* + * is equivalent to fprintf, with the variable argument list replaced by + * arg, which has been initialised by the va_start macro (and possibly + * subsequent va_arg calls). The vfprintf function does not invoke the + * va_end function. + * Returns: the number of characters transmitted, or a negative value if an + * output error occurred. + */ +extern int vsprintf(char * /*s*/, const char * /*format*/, __va_list /*arg*/); + /* + * is equivalent to sprintf, with the variable argument list replaced by + * arg, which has been initialised by the va_start macro (and possibly + * subsequent va_arg calls). The vsprintf function does not invoke the + * va_end function. + * Returns: the number of characters written in the array, not counting the + * terminating null character. + */ +#ifndef __STRICT_ANSI__ +extern int vsnprintf(char * /*s*/, size_t /*n*/, + const char * /*format*/, __va_list /*arg*/); + /* + * is equivalent to snprintf, with the variable argument list replaced by + * arg, which has been initialised by the va_start macro (and possibly + * subsequent va_arg calls). The vsprintf function does not invoke the + * va_end function. + * Returns: the number of characters that would have been written in the + * array, not counting the terminating null character. As + * snprintf. + */ +#endif +#ifndef __EDG__ +#pragma no_check_vprintf_formats /* back to default */ +#endif +extern int _vsprintf(char * /*s*/, const char * /*format*/, __va_list /*arg*/); + /* + * is equivalent to vsprintf, but does not support floating-point formats. + * You can use instead of vsprintf to improve code size. + * Returns: as vsprintf. + */ +extern int _vfprintf(FILE * /*stream*/, + const char * /*format*/, __va_list /*arg*/); + /* + * is equivalent to vfprintf, but does not support floating-point formats. + * You can use instead of vfprintf to improve code size. + * Returns: as vfprintf. + */ +extern int _vsnprintf(char * /*s*/, size_t /*n*/, + const char * /*format*/, __va_list /*arg*/); + /* + * is equivalent to vsnprintf, but does not support floating-point formats. + * You can use instead of vsnprintf to improve code size. + * Returns: as vsnprintf. + */ +extern int fgetc(FILE * /*stream*/); + /* + * obtains the next character (if present) as an unsigned char converted to + * an int, from the input stream pointed to by stream, and advances the + * associated file position indicator (if defined). + * Returns: the next character from the input stream pointed to by stream. + * If the stream is at end-of-file, the end-of-file indicator is + * set and fgetc returns EOF. If a read error occurs, the error + * indicator is set and fgetc returns EOF. + */ +extern char *fgets(char * /*s*/, int /*n*/, FILE * /*stream*/); + /* + * reads at most one less than the number of characters specified by n from + * the stream pointed to by stream into the array pointed to by s. No + * additional characters are read after a new-line character (which is + * retained) or after end-of-file. A null character is written immediately + * after the last character read into the array. + * Returns: s if successful. If end-of-file is encountered and no characters + * have been read into the array, the contents of the array remain + * unchanged and a null pointer is returned. If a read error occurs + * during the operation, the array contents are indeterminate and a + * null pointer is returned. + */ +extern int fputc(int /*c*/, FILE * /*stream*/); + /* + * writes the character specified by c (converted to an unsigned char) to + * the output stream pointed to by stream, at the position indicated by the + * asociated file position indicator (if defined), and advances the + * indicator appropriately. If the file position indicator is not defined, + * the character is appended to the output stream. + * Returns: the character written. If a write error occurs, the error + * indicator is set and fputc returns EOF. + */ +extern int fputs(const char * /*s*/, FILE * /*stream*/); + /* + * writes the string pointed to by s to the stream pointed to by stream. + * The terminating null character is not written. + * Returns: EOF if a write error occurs; otherwise it returns a nonnegative + * value. + */ +extern int getc(FILE * /*stream*/); + /* + * is equivalent to fgetc except that it may be implemented as an unsafe + * macro (stream may be evaluated more than once, so the argument should + * never be an expression with side-effects). + * Returns: the next character from the input stream pointed to by stream. + * If the stream is at end-of-file, the end-of-file indicator is + * set and getc returns EOF. If a read error occurs, the error + * indicator is set and getc returns EOF. + */ +#ifdef __cplusplus + inline int getchar() { return getc(stdin); } +#else + #define getchar() getc(stdin) + extern int (getchar)(void); +#endif + /* + * is equivalent to getc with the argument stdin. + * Returns: the next character from the input stream pointed to by stdin. + * If the stream is at end-of-file, the end-of-file indicator is + * set and getchar returns EOF. If a read error occurs, the error + * indicator is set and getchar returns EOF. + */ +extern char *gets(char * /*s*/); + /* + * reads characters from the input stream pointed to by stdin into the array + * pointed to by s, until end-of-file is encountered or a new-line character + * is read. Any new-line character is discarded, and a null character is + * written immediately after the last character read into the array. + * Returns: s if successful. If end-of-file is encountered and no characters + * have been read into the array, the contents of the array remain + * unchanged and a null pointer is returned. If a read error occurs + * during the operation, the array contents are indeterminate and a + * null pointer is returned. + */ +extern int putc(int /*c*/, FILE * /*stream*/); + /* + * is equivalent to fputc except that it may be implemented as aan unsafe + * macro (stream may be evaluated more than once, so the argument should + * never be an expression with side-effects). + * Returns: the character written. If a write error occurs, the error + * indicator is set and putc returns EOF. + */ +#ifdef __cplusplus + inline int putchar(int __c) { return putc(__c, stdout); } +#else + #define putchar(c) putc(c, stdout) + extern int (putchar)(int /*c*/); +#endif + /* + * is equivalent to putc with the second argument stdout. + * Returns: the character written. If a write error occurs, the error + * indicator is set and putc returns EOF. + */ +extern int puts(const char * /*s*/); + /* + * writes the string pointed to by s to the stream pointed to by stdout, and + * appends a new-line character to the output. The terminating null + * character is not written. + * Returns: EOF if a write error occurs; otherwise it returns a nonnegative + * value. + */ +extern int ungetc(int /*c*/, FILE * /*stream*/); + /* + * pushes the character specified by c (converted to an unsigned char) back + * onto the input stream pointed to by stream. The character will be + * returned by the next read on that stream. An intervening call to the + * fflush function or to a file positioning function (fseek, fsetpos, + * rewind) discards any pushed-back characters. The external storage + * corresponding to the stream is unchanged. + * One character pushback is guaranteed. If the unget function is called too + * many times on the same stream without an intervening read or file + * positioning operation on that stream, the operation may fail. + * If the value of c equals that of the macro EOF, the operation fails and + * the input stream is unchanged. + * A successful call to the ungetc function clears the end-of-file + * indicator. The value of the file position indicator after reading or + * discarding all pushed-back characters shall be the same as it was before + * the characters were pushed back. For a text stream, the value of the file + * position indicator after a successful call to the ungetc function is + * unspecified until all pushed-back characters are read or discarded. For a + * binary stream, the file position indicator is decremented by each + * successful call to the ungetc function; if its value was zero before a + * call, it is indeterminate after the call. + * Returns: the character pushed back after conversion, or EOF if the + * operation fails. + */ + +extern size_t fread(void * /*ptr*/, + size_t /*size*/, size_t /*nmemb*/, FILE * /*stream*/); + /* + * reads into the array pointed to by ptr, up to nmemb members whose size is + * specified by size, from the stream pointed to by stream. The file + * position indicator (if defined) is advanced by the number of characters + * successfully read. If an error occurs, the resulting value of the file + * position indicator is indeterminate. If a partial member is read, its + * value is indeterminate. The ferror or feof function shall be used to + * distinguish between a read error and end-of-file. + * Returns: the number of members successfully read, which may be less than + * nmemb if a read error or end-of-file is encountered. If size or + * nmemb is zero, fread returns zero and the contents of the array + * and the state of the stream remain unchanged. + */ + +extern size_t __fread_bytes_avail(void * /*ptr*/, + size_t /*count*/, FILE * /*stream*/); + /* + * reads into the array pointed to by ptr, up to count characters from the + * stream pointed to by stream. The file position indicator (if defined) + * is advanced by the number of characters successfully read. If an error + * occurs, the resulting value of the file position indicator is + * indeterminate. The ferror or feof function shall be used to + * distinguish between a read error and end-of-file. The call will block + * only if no characters are available. + * Returns: the number of characters successfully read, which may be less than + * count. If count is zero, __fread_bytes_avail returns zero and + * the contents of the array and the state of the stream remain + * unchanged. + */ + +extern size_t fwrite(const void * /*ptr*/, + size_t /*size*/, size_t /*nmemb*/, FILE * /*stream*/); + /* + * writes, from the array pointed to by ptr up to nmemb members whose size + * is specified by size, to the stream pointed to by stream. The file + * position indicator (if defined) is advanced by the number of characters + * successfully written. If an error occurs, the resulting value of the file + * position indicator is indeterminate. + * Returns: the number of members successfully written, which will be less + * than nmemb only if a write error is encountered. + */ + +extern int fgetpos(FILE * /*stream*/, fpos_t * /*pos*/); + /* + * stores the current value of the file position indicator for the stream + * pointed to by stream in the object pointed to by pos. The value stored + * contains unspecified information usable by the fsetpos function for + * repositioning the stream to its position at the time of the call to the + * fgetpos function. + * Returns: zero, if successful. Otherwise nonzero is returned and the + * integer expression errno is set to an implementation-defined + * nonzero value. + */ +extern int fseek(FILE * /*stream*/, long int /*offset*/, int /*whence*/); + /* + * sets the file position indicator for the stream pointed to by stream. + * For a binary stream, the new position is at the signed number of + * characters specified by offset away from the point specified by whence. + * The specified point is the beginning of the file for SEEK_SET, the + * current position in the file for SEEK_CUR, or end-of-file for SEEK_END. + * A binary stream need not meaningfully support fseek calls with a whence + * value of SEEK_END. + * For a text stream, either offset shall be zero, or offset shall be a + * value returned by an earlier call to the ftell function on the same + * stream and whence shall be SEEK_SET. + * The fseek function clears the end-of-file indicator and undoes any + * effects of the ungetc function on the same stream. After an fseek call, + * the next operation on an update stream may be either input or output. + * Returns: nonzero only for a request that cannot be satisfied. + */ +extern int fsetpos(FILE * /*stream*/, const fpos_t * /*pos*/); + /* + * sets the file position indicator for the stream pointed to by stream + * according to the value of the object pointed to by pos, which shall be a + * value returned by an earlier call to the fgetpos function on the same + * stream. + * The fsetpos function clears the end-of-file indicator and undoes any + * effects of the ungetc function on the same stream. After an fsetpos call, + * the next operation on an update stream may be either input or output. + * Returns: zero, if successful. Otherwise nonzero is returned and the + * integer expression errno is set to an implementation-defined + * nonzero value. + */ +extern long int ftell(FILE * /*stream*/); + /* + * obtains the current value of the file position indicator for the stream + * pointed to by stream. For a binary stream, the value is the number of + * characters from the beginning of the file. For a text stream, the file + * position indicator contains unspecified information, usable by the fseek + * function for returning the file position indicator to its position at the + * time of the ftell call; the difference between two such return values is + * not necessarily a meaningful measure of the number of characters written + * or read. + * Returns: if successful, the current value of the file position indicator. + * On failure, the ftell function returns -1L and sets the integer + * expression errno to an implementation-defined nonzero value. + */ +extern void rewind(FILE * /*stream*/); + /* + * sets the file position indicator for the stream pointed to by stream to + * the beginning of the file. It is equivalent to + * (void)fseek(stream, 0L, SEEK_SET) + * except that the error indicator for the stream is also cleared. + * Returns: no value. + */ + +extern void clearerr(FILE * /*stream*/); + /* + * clears the end-of-file and error indicators for the stream pointed to by + * stream. These indicators are cleared only when the file is opened or by + * an explicit call to the clearerr function or to the rewind function. + * Returns: no value. + */ + +extern int feof(FILE * /*stream*/); + /* + * tests the end-of-file indicator for the stream pointed to by stream. + * Returns: nonzero iff the end-of-file indicator is set for stream. + */ +extern int ferror(FILE * /*stream*/); + /* + * tests the error indicator for the stream pointed to by stream. + * Returns: nonzero iff the error indicator is set for stream. + */ +extern void perror(const char * /*s*/); + /* + * maps the error number in the integer expression errno to an error + * message. It writes a sequence of characters to the standard error stream + * thus: first (if s is not a null pointer and the character pointed to by + * s is not the null character), the string pointed to by s followed by a + * colon and a space; then an appropriate error message string followed by + * a new-line character. The contents of the error message strings are the + * same as those returned by the strerror function with argument errno, + * which are implementation-defined. + * Returns: no value. + */ + +extern int _fisatty(FILE * /*stream*/ ); + /* Returns 1 if the stream is tty (stdin), 0 otherwise. Not ANSI compliant. + */ + +extern void __use_no_semihosting_swi(void); + /* + * Referencing this symbol will cause a link-time error if any + * library functions that use semihosting SWI calls are also + * present in the link, i.e. you define it if you want to make + * sure you haven't accidentally used any such SWIs. + */ + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __STDIO_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __STDIO_NO_EXPORTS + using std::size_t; + using std::__va_list; + using std::fpos_t; + using std::FILE; + using std::__stdin; + using std::__stdout; + using std::__stderr; + using std::remove; + using std::rename; + using std::tmpfile; + using std::tmpnam; + using std::fclose; + using std::fflush; + using std::fopen; + using std::freopen; + using std::setbuf; + using std::setvbuf; + using std::fprintf; + using std::printf; + using std::sprintf; +#ifndef __STRICT_ANSI__ + using std::snprintf; + using std::_snprintf; + using std::vsnprintf; + using std::_vsnprintf; +#endif + using std::fscanf; + using std::scanf; + using std::sscanf; + using std::vprintf; + using std::vfprintf; + using std::vsprintf; + using std::fgetc; + using std::fgets; + using std::fputc; + using std::fputs; + using std::getc; + using std::getchar; + using std::gets; + using std::putc; + using std::putchar; + using std::puts; + using std::ungetc; + using std::fread; + using std::__fread_bytes_avail; + using std::fwrite; + using std::fgetpos; + using std::fseek; + using std::fsetpos; + using std::ftell; + using std::rewind; + using std::clearerr; + using std::feof; + using std::ferror; + using std::perror; + using std::_fisatty; + using std::__use_no_semihosting_swi; + #endif + #endif + +#endif + +/* end of stdio.h */ diff --git a/inc/C_H/stdlib.h b/inc/C_H/stdlib.h new file mode 100644 index 0000000..a6f180f --- /dev/null +++ b/inc/C_H/stdlib.h @@ -0,0 +1,727 @@ +/* stdlib.h: ANSI draft (X3J11 May 88) library header, section 4.10 */ +/* Copyright (C) Codemist Ltd., 1988-1993. */ +/* Copyright 1991-1998 ARM Limited. All rights reserved. */ +/* + * RCS $Revision: 1.21.2.7 $ + * Checkin $Date: 2001/10/19 15:18:20 $ + * Revising $Author: cadeniyi $ + */ + +/* + * stdlib.h declares four types, several general purpose functions, + * and defines several macros. + */ + +#ifndef __stdlib_h +#define __stdlib_h + + #ifndef __STDLIB_DECLS + #define __STDLIB_DECLS + + #undef __CLIBNS + + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) + /* unconditional in C++ and non-strict C for consistency of debug info */ + typedef unsigned int size_t; +#elif !defined(__size_t) + #define __size_t 1 + typedef unsigned int size_t; /* see */ +#endif + +#undef NULL +#define NULL 0 /* see */ + +#ifndef __cplusplus /* wchar_t is a builtin type for C++ */ + #if !defined(__STRICT_ANSI__) + /* unconditional in non-strict C for consistency of debug info */ + typedef unsigned short wchar_t; /* see */ + #elif !defined(__wchar_t) + #define __wchar_t 1 + typedef unsigned short wchar_t; /* see */ + #endif +#endif + +typedef struct div_t { int quot, rem; } div_t; + /* type of the value returned by the div function. */ +typedef struct ldiv_t { long int quot, rem; } ldiv_t; + /* type of the value returned by the ldiv function. */ +#ifndef __STRICT_ANSI__ +typedef struct lldiv_t { long long quot, rem; } lldiv_t; + /* type of the value returned by the lldiv function. */ +#endif + +#ifdef __EXIT_FAILURE +# define EXIT_FAILURE __EXIT_FAILURE + /* + * an integral expression which may be used as an argument to the exit + * function to return unsuccessful termination status to the host + * environment. + */ +#else +# define EXIT_FAILURE 1 /* unixoid */ +#endif +#define EXIT_SUCCESS 0 + /* + * an integral expression which may be used as an argument to the exit + * function to return successful termination status to the host + * environment. + */ + + /* + * Defining __USE_ANSI_EXAMPLE_RAND at compile time switches to + * the example implementation of rand() and srand() provided in + * the ANSI C standard. This implementation is very poor, but is + * provided for completeness. + */ +#ifdef __USE_ANSI_EXAMPLE_RAND +#define srand _ANSI_srand +#define rand _ANSI_rand +#define RAND_MAX 0x7fff +#else +#define RAND_MAX 0x7fffffff +#endif + /* + * RAND_MAX: an integral constant expression, the value of which + * is the maximum value returned by the rand function. + */ +#define MB_CUR_MAX 1 + /* + * a positive integer expression whose value is the maximum number of bytes + * in a multibyte character for the extended character set specified by the + * current locale (category LC_CTYPE), and whose value is never greater + * than MB_LEN_MAX. + */ + +extern double atof(const char * /*nptr*/); + /* + * converts the initial part of the string pointed to by nptr to double + * representation. + * Returns: the converted value. + */ +extern int atoi(const char * /*nptr*/); + /* + * converts the initial part of the string pointed to by nptr to int + * representation. + * Returns: the converted value. + */ +extern long int atol(const char * /*nptr*/); + /* + * converts the initial part of the string pointed to by nptr to long int + * representation. + * Returns: the converted value. + */ +#ifndef __STRICT_ANSI__ +extern long long int atoll(const char * /*nptr*/); + /* + * converts the initial part of the string pointed to by nptr to + * long long int representation. + * Returns: the converted value. + */ +#endif + +extern double strtod(const char * /*nptr*/, char ** /*endptr*/); + /* + * converts the initial part of the string pointed to by nptr to double + * representation. First it decomposes the input string into three parts: + * an initial, possibly empty, sequence of white-space characters (as + * specified by the isspace function), a subject sequence resembling a + * floating point constant; and a final string of one or more unrecognised + * characters, including the terminating null character of the input string. + * Then it attempts to convert the subject sequence to a floating point + * number, and returns the result. A pointer to the final string is stored + * in the object pointed to by endptr, provided that endptr is not a null + * pointer. + * Returns: the converted value if any. If no conversion could be performed, + * zero is returned. If the correct value is outside the range of + * representable values, plus or minus HUGE_VAL is returned + * (according to the sign of the value), and the value of the macro + * ERANGE is stored in errno. If the correct value would cause + * underflow, zero is returned and the value of the macro ERANGE is + * stored in errno. + */ +extern long int strtol(const char * /*nptr*/, char **/*endptr*/, int /*base*/); + /* + * converts the initial part of the string pointed to by nptr to long int + * representation. First it decomposes the input string into three parts: + * an initial, possibly empty, sequence of white-space characters (as + * specified by the isspace function), a subject sequence resembling an + * integer represented in some radix determined by the value of base, and a + * final string of one or more unrecognised characters, including the + * terminating null character of the input string. Then it attempts to + * convert the subject sequence to an integer, and returns the result. + * If the value of base is 0, the expected form of the subject sequence is + * that of an integer constant (described in ANSI Draft, section 3.1.3.2), + * optionally preceded by a '+' or '-' sign, but not including an integer + * suffix. If the value of base is between 2 and 36, the expected form of + * the subject sequence is a sequence of letters and digits representing an + * integer with the radix specified by base, optionally preceded by a plus + * or minus sign, but not including an integer suffix. The letters from a + * (or A) through z (or Z) are ascribed the values 10 to 35; only letters + * whose ascribed values are less than that of the base are permitted. If + * the value of base is 16, the characters 0x or 0X may optionally precede + * the sequence of letters and digits following the sign if present. + * A pointer to the final string is stored in the object + * pointed to by endptr, provided that endptr is not a null pointer. + * Returns: the converted value if any. If no conversion could be performed, + * zero is returned and nptr is stored in *endptr. + * If the correct value is outside the range of + * representable values, LONG_MAX or LONG_MIN is returned + * (according to the sign of the value), and the value of the + * macro ERANGE is stored in errno. + */ +extern unsigned long int strtoul(const char * /*nptr*/, + char ** /*endptr*/, int /*base*/); + /* + * converts the initial part of the string pointed to by nptr to unsigned + * long int representation. First it decomposes the input string into three + * parts: an initial, possibly empty, sequence of white-space characters (as + * determined by the isspace function), a subject sequence resembling an + * unsigned integer represented in some radix determined by the value of + * base, and a final string of one or more unrecognised characters, + * including the terminating null character of the input string. Then it + * attempts to convert the subject sequence to an unsigned integer, and + * returns the result. If the value of base is zero, the expected form of + * the subject sequence is that of an integer constant (described in ANSI + * Draft, section 3.1.3.2), optionally preceded by a '+' or '-' sign, but + * not including an integer suffix. If the value of base is between 2 and + * 36, the expected form of the subject sequence is a sequence of letters + * and digits representing an integer with the radix specified by base, + * optionally preceded by a '+' or '-' sign, but not including an integer + * suffix. The letters from a (or A) through z (or Z) stand for the values + * 10 to 35; only letters whose ascribed values are less than that of the + * base are permitted. If the value of base is 16, the characters 0x or 0X + * may optionally precede the sequence of letters and digits following the + * sign, if present. A pointer to the final string is stored in the object + * pointed to by endptr, provided that endptr is not a null pointer. + * Returns: the converted value if any. If no conversion could be performed, + * zero is returned and nptr is stored in *endptr. + * If the correct value is outside the range of + * representable values, ULONG_MAX is returned, and the value of + * the macro ERANGE is stored in errno. + */ + +#ifndef __STRICT_ANSI__ +extern long long int strtoll(const char * /*restrict*/ /*nptr*/, + char ** /*restrict*/ /*endptr*/, int /*base*/); + /* + * as strtol but returns a long long int value. If the correct value is + * outside the range of representable values, LLONG_MAX or LLONG_MIN is + * returned (according to the sign of the value), and the value of the + * macro ERANGE is stored in errno. + */ +extern unsigned long long int strtoull(const char * /*restrict*/ /*nptr*/, + char ** /*restrict*/ /*endptr*/, int /*base*/); + /* + * as strtoul but returns an unsigned long long int value. If the correct + * value is outside the range of representable values, ULLONG_MAX is returned, + * and the value of the macro ERANGE is stored in errno. + */ +#endif + +extern int rand(void); + /* + * Computes a sequence of pseudo-random integers in the range 0 to RAND_MAX. + * Uses an additive generator (Mitchell & Moore) of the form: + * Xn = (X[n-24] + X[n-55]) MOD 2^31 + * This is described in section 3.2.2 of Knuth, vol 2. It's period is + * in excess of 2^55 and its randomness properties, though unproven, are + * conjectured to be good. Empirical testing since 1958 has shown no flaws. + * Returns: a pseudo-random integer. + */ +extern void srand(unsigned int /*seed*/); + /* + * uses its argument as a seed for a new sequence of pseudo-random numbers + * to be returned by subsequent calls to rand. If srand is then called with + * the same seed value, the sequence of pseudo-random numbers is repeated. + * If rand is called before any calls to srand have been made, the same + * sequence is generated as when srand is first called with a seed value + * of 1. + */ + +extern void *calloc(size_t /*nmemb*/, size_t /*size*/); + /* + * allocates space for an array of nmemb objects, each of whose size is + * 'size'. The space is initialised to all bits zero. + * Returns: either a null pointer or a pointer to the allocated space. + */ +extern void free(void * /*ptr*/); + /* + * causes the space pointed to by ptr to be deallocated (i.e., made + * available for further allocation). If ptr is a null pointer, no action + * occurs. Otherwise, if ptr does not match a pointer earlier returned by + * calloc, malloc or realloc or if the space has been deallocated by a call + * to free or realloc, the behaviour is undefined. + */ +extern void *malloc(size_t /*size*/); + /* + * allocates space for an object whose size is specified by 'size' and whose + * value is indeterminate. + * Returns: either a null pointer or a pointer to the allocated space. + */ +extern void *realloc(void * /*ptr*/, size_t /*size*/); + /* + * changes the size of the object pointed to by ptr to the size specified by + * size. The contents of the object shall be unchanged up to the lesser of + * the new and old sizes. If the new size is larger, the value of the newly + * allocated portion of the object is indeterminate. If ptr is a null + * pointer, the realloc function behaves like a call to malloc for the + * specified size. Otherwise, if ptr does not match a pointer earlier + * returned by calloc, malloc or realloc, or if the space has been + * deallocated by a call to free or realloc, the behaviour is undefined. + * If the space cannot be allocated, the object pointed to by ptr is + * unchanged. If size is zero and ptr is not a null pointer, the object it + * points to is freed. + * Returns: either a null pointer or a pointer to the possibly moved + * allocated space. + */ +typedef int (*__heapprt)(void *, char const *, ...); +extern void __heapstats(int (* /*dprint*/)(void * /*param*/, + char const * /*format*/, ...), + void * /*param*/); + /* + * reports current heap statistics (eg. number of free blocks in + * the free-list). Output is as implementation-defined free-form + * text, provided via the dprint function. `param' gives an + * extra data word to pass to dprint. You can call + * __heapstats(fprintf,stdout) by casting fprintf to the above + * function type; the typedef `__heapprt' is provided for this + * purpose. + * + * `dprint' will not be called while the heap is being examined, + * so it can allocate memory itself without trouble. + */ +extern int __heapvalid(int (* /*dprint*/)(void * /*param*/, + char const * /*format*/, ...), + void * /*param*/, int /*verbose*/); + /* + * performs a consistency check on the heap. Errors are reported + * through dprint, like __heapstats. If `verbose' is nonzero, + * full diagnostic information on the heap state is printed out. + * + * This routine probably won't work if the heap isn't a + * contiguous chunk (for example, if __user_heap_extend has been + * overridden). + * + * `dprint' may be called while the heap is being examined or + * even in an invalid state, so it must perform no memory + * allocation. In particular, if `dprint' calls (or is) a stdio + * function, the stream it outputs to must already have either + * been written to or been setvbuf'ed, or else the system will + * allocate buffer space for it on the first call to dprint. + */ +extern void abort(void); + /* + * causes abnormal program termination to occur, unless the signal SIGABRT + * is being caught and the signal handler does not return. Whether open + * output streams are flushed or open streams are closed or temporary + * files removed is implementation-defined. + * An implementation-defined form of the status 'unsuccessful termination' + * is returned to the host environment by means of a call to + * raise(SIGABRT). + */ +extern int atexit(void (* /*func*/)(void)); + /* + * registers the function pointed to by func, to be called without its + * arguments at normal program termination. It is possible to register at + * least 32 functions. + * Returns: zero if the registration succeeds, nonzero if it fails. + */ +extern void exit(int /*status*/); + /* + * causes normal program termination to occur. If more than one call to the + * exit function is executed by a program, the behaviour is undefined. + * First, all functions registered by the atexit function are called, in the + * reverse order of their registration. + * Next, all open output streams are flushed, all open streams are closed, + * and all files created by the tmpfile function are removed. + * Finally, control is returned to the host environment. If the value of + * status is zero or EXIT_SUCCESS, an implementation-defined form of the + * status 'successful termination' is returned. If the value of status is + * EXIT_FAILURE, an implementation-defined form of the status + * 'unsuccessful termination' is returned. Otherwise the status returned + * is implementation-defined. + */ + +extern char *getenv(const char * /*name*/); + /* + * searches the environment list, provided by the host environment, for a + * string that matches the string pointed to by name. The set of environment + * names and the method for altering the environment list are + * implementation-defined. + * Returns: a pointer to a string associated with the matched list member. + * The array pointed to shall not be modified by the program, but + * may be overwritten by a subsequent call to the getenv function. + * If the specified name cannot be found, a null pointer is + * returned. + */ +extern int system(const char * /*string*/); + /* + * passes the string pointed to by string to the host environment to be + * executed by a command processor in an implementation-defined manner. + * A null pointer may be used for string, to inquire whether a command + * processor exists. + * + * Returns: If the argument is a null pointer, the system function returns + * non-zero only if a command processor is available. If the + * argument is not a null pointer, the system function returns an + * implementation-defined value. + */ + +extern void *bsearch(const void * /*key*/, const void * /*base*/, + size_t /*nmemb*/, size_t /*size*/, + int (* /*compar*/)(const void *, const void *)); + /* + * searches an array of nmemb objects, the initial member of which is + * pointed to by base, for a member that matches the object pointed to by + * key. The size of each member of the array is specified by size. + * The contents of the array shall be in ascending sorted order according to + * a comparison function pointed to by compar, which is called with two + * arguments that point to the key object and to an array member, in that + * order. The function shall return an integer less than, equal to, or + * greater than zero if the key object is considered, respectively, to be + * less than, to match, or to be greater than the array member. + * Returns: a pointer to a matching member of the array, or a null pointer + * if no match is found. If two members compare as equal, which + * member is matched is unspecified. + */ +extern void qsort(void * /*base*/, size_t /*nmemb*/, size_t /*size*/, + int (* /*compar*/)(const void *, const void *)); + /* + * sorts an array of nmemb objects, the initial member of which is pointed + * to by base. The size of each object is specified by size. + * The contents of the array shall be in ascending order according to a + * comparison function pointed to by compar, which is called with two + * arguments that point to the objects being compared. The function shall + * return an integer less than, equal to, or greater than zero if the first + * argument is considered to be respectively less than, equal to, or greater + * than the second. If two members compare as equal, their order in the + * sorted array is unspecified. + */ + +extern int abs(int /*j*/); + /* + * computes the absolute value of an integer j. If the result cannot be + * represented, the behaviour is undefined. + * Returns: the absolute value. + */ + +extern div_t div(int /*numer*/, int /*denom*/); + /* + * computes the quotient and remainder of the division of the numerator + * numer by the denominator denom. If the division is inexact, the resulting + * quotient is the integer of lesser magnitude that is the nearest to the + * algebraic quotient. If the result cannot be represented, the behaviour is + * undefined; otherwise, quot * denom + rem shall equal numer. + * Returns: a structure of type div_t, comprising both the quotient and the + * remainder. the structure shall contain the following members, + * in either order. + * int quot; int rem; + */ +extern long int labs(long int /*j*/); + /* + * computes the absolute value of an long integer j. If the result cannot be + * represented, the behaviour is undefined. + * Returns: the absolute value. + */ +#ifdef __cplusplus + extern "C++" inline long abs(long int x) { return labs(x); } +#endif + +extern ldiv_t ldiv(long int /*numer*/, long int /*denom*/); + /* + * computes the quotient and remainder of the division of the numerator + * numer by the denominator denom. If the division is inexact, the sign of + * the resulting quotient is that of the algebraic quotient, and the + * magnitude of the resulting quotient is the largest integer less than the + * magnitude of the algebraic quotient. If the result cannot be represented, + * the behaviour is undefined; otherwise, quot * denom + rem shall equal + * numer. + * Returns: a structure of type ldiv_t, comprising both the quotient and the + * remainder. the structure shall contain the following members, + * in either order. + * long int quot; long int rem; + */ +#ifdef __cplusplus + extern "C++" inline ldiv_t div(long int __numer, long int __denom) { + return ldiv(__numer, __denom); + } +#endif + +#ifndef __STRICT_ANSI__ +extern long long llabs(long long /*j*/); + /* + * computes the absolute value of a long long integer j. If the + * result cannot be represented, the behaviour is undefined. + * Returns: the absolute value. + */ +#ifdef __cplusplus + extern "C++" inline long long abs(long long x) { return llabs(x); } +#endif + +extern lldiv_t lldiv(long long /*numer*/, long long /*denom*/); + /* + * computes the quotient and remainder of the division of the numerator + * numer by the denominator denom. If the division is inexact, the sign of + * the resulting quotient is that of the algebraic quotient, and the + * magnitude of the resulting quotient is the largest integer less than the + * magnitude of the algebraic quotient. If the result cannot be represented, + * the behaviour is undefined; otherwise, quot * denom + rem shall equal + * numer. + * Returns: a structure of type lldiv_t, comprising both the quotient and the + * remainder. the structure shall contain the following members, + * in either order. + * long long quot; long long rem; + */ +#ifdef __cplusplus + extern "C++" inline lldiv_t div(long long __numer, long long __denom) { + return lldiv(__numer, __denom); + } +#endif +#endif + +/* + * ARM real-time divide functions for guaranteed performance + */ +typedef struct __sdiv32by16 { int quot, rem; } __sdiv32by16; +typedef struct __udiv32by16 { unsigned int quot, rem; } __udiv32by16; + /* used int so that values return in separate regs, although 16-bit */ +typedef struct __sdiv64by32 { int rem, quot; } __sdiv64by32; + +__value_in_regs extern __sdiv32by16 __rt_sdiv32by16( + int /*numer*/, + short int /*denom*/); + /* + * Signed divide: (16-bit quot), (16-bit rem) = (32-bit) / (16-bit) + */ +__value_in_regs extern __udiv32by16 __rt_udiv32by16( + unsigned int /*numer*/, + unsigned short /*denom*/); + /* + * Unsigned divide: (16-bit quot), (16-bit rem) = (32-bit) / (16-bit) + */ +__value_in_regs extern __sdiv64by32 __rt_sdiv64by32( + int /*numer_h*/, unsigned int /*numer_l*/, + int /*denom*/); + /* + * Signed divide: (32-bit quot), (32-bit rem) = (64-bit) / (32-bit) + */ + +/* + * ARM floating-point mask/status function (for both hardfp and softfp) + */ +extern unsigned int __fp_status(unsigned int /*mask*/, unsigned int /*flags*/); + /* + * mask and flags are bit-fields which correspond directly to the + * floating point status register in the FPE/FPA and fplib. + * __fp_status returns the current value of the status register, + * and also sets the writable bits of the word + * (the exception control and flag bytes) to: + * + * new = (old & ~mask) ^ flags; + */ +#define __fpsr_IXE 0x100000 +#define __fpsr_UFE 0x80000 +#define __fpsr_OFE 0x40000 +#define __fpsr_DZE 0x20000 +#define __fpsr_IOE 0x10000 + +#define __fpsr_IXC 0x10 +#define __fpsr_UFC 0x8 +#define __fpsr_OFC 0x4 +#define __fpsr_DZC 0x2 +#define __fpsr_IOC 0x1 + +/* + * Multibyte Character Functions. + * The behaviour of the multibyte character functions is affected by the + * LC_CTYPE category of the current locale. For a state-dependent encoding, + * each function is placed into its initial state by a call for which its + * character pointer argument, s, is a null pointer. Subsequent calls with s + * as other than a null pointer cause the internal state of the function to be + * altered as necessary. A call with s as a null pointer causes these functions + * to return a nonzero value if encodings have state dependency, and a zero + * otherwise. After the LC_CTYPE category is changed, the shift state of these + * functions is indeterminate. + */ +extern int mblen(const char * /*s*/, size_t /*n*/); + /* + * If s is not a null pointer, the mblen function determines the number of + * bytes compromising the multibyte character pointed to by s. Except that + * the shift state of the mbtowc function is not affected, it is equivalent + * to mbtowc((wchar_t *)0, s, n); + * Returns: If s is a null pointer, the mblen function returns a nonzero or + * zero value, if multibyte character encodings, respectively, do + * or do not have state-dependent encodings. If s is not a null + * pointer, the mblen function either returns a 0 (if s points to a + * null character), or returns the number of bytes that compromise + * the multibyte character (if the next n of fewer bytes form a + * valid multibyte character), or returns -1 (they do not form a + * valid multibyte character). + */ +extern int mbtowc(wchar_t * /*pwc*/, const char * /*s*/, size_t /*n*/); + /* + * If s is not a null pointer, the mbtowc function determines the number of + * bytes that compromise the multibyte character pointed to by s. It then + * determines the code for value of type wchar_t that corresponds to that + * multibyte character. (The value of the code corresponding to the null + * character is zero). If the multibyte character is valid and pwc is not a + * null pointer, the mbtowc function stores the code in the object pointed + * to by pwc. At most n bytes of the array pointed to by s will be examined. + * Returns: If s is a null pointer, the mbtowc function returns a nonzero or + * zero value, if multibyte character encodings, respectively, do + * or do not have state-dependent encodings. If s is not a null + * pointer, the mbtowc function either returns a 0 (if s points to + * a null character), or returns the number of bytes that + * compromise the converted multibyte character (if the next n of + * fewer bytes form a valid multibyte character), or returns -1 + * (they do not form a valid multibyte character). + */ +extern int wctomb(char * /*s*/, wchar_t /*wchar*/); + /* + * determines the number of bytes need to represent the multibyte character + * corresponding to the code whose value is wchar (including any change in + * shift state). It stores the multibyte character representation in the + * array object pointed to by s (if s is not a null pointer). At most + * MB_CUR_MAX characters are stored. If the value of wchar is zero, the + * wctomb function is left in the initial shift state). + * Returns: If s is a null pointer, the wctomb function returns a nonzero or + * zero value, if multibyte character encodings, respectively, do + * or do not have state-dependent encodings. If s is not a null + * pointer, the wctomb function returns a -1 if the value of wchar + * does not correspond to a valid multibyte character, or returns + * the number of bytes that compromise the multibyte character + * corresponding to the value of wchar. + */ + +/* + * Multibyte String Functions. + * The behaviour of the multibyte string functions is affected by the LC_CTYPE + * category of the current locale. + */ +extern size_t mbstowcs(wchar_t * /*pwcs*/, const char * /*s*/, size_t /*n*/); + /* + * converts a sequence of multibyte character that begins in the initial + * shift state from the array pointed to by s into a sequence of + * corresponding codes and stores not more than n codes into the array + * pointed to by pwcs. No multibyte character that follow a null character + * (which is converted into a code with value zero) will be examined or + * converted. Each multibyte character is converted as if by a call to + * mbtowc function, except that the shift state of the mbtowc function is + * not affected. No more than n elements will be modified in the array + * pointed to by pwcs. If copying takes place between objects that overlap, + * the behaviour is undefined. + * Returns: If an invalid multibyte character is encountered, the mbstowcs + * function returns (size_t)-1. Otherwise, the mbstowcs function + * returns the number of array elements modified, not including + * a terminating zero code, if any. + */ +extern size_t wcstombs(char * /*s*/, const wchar_t * /*pwcs*/, size_t /*n*/); + /* + * converts a sequence of codes that correspond to multibyte characters + * from the array pointed to by pwcs into a sequence of multibyte + * characters that begins in the initial shift state and stores these + * multibyte characters into the array pointed to by s, stopping if a + * multibyte character would exceed the limit of n total bytes or if a + * null character is stored. Each code is converted as if by a call to the + * wctomb function, except that the shift state of the wctomb function is + * not affected. No more than n elements will be modified in the array + * pointed to by s. If copying takes place between objects that overlap, + * the behaviour is undefined. + * Returns: If a code is encountered that does not correspond to a valid + * multibyte character, the wcstombs function returns (size_t)-1. + * Otherwise, the wcstombs function returns the number of bytes + * modified, not including a terminating null character, if any. + */ + +extern void __use_realtime_heap(void); +extern void __use_realtime_division(void); +extern void __use_two_region_memory(void); +extern void __use_no_heap(void); +extern void __use_no_heap_region(void); + +extern char const *__C_library_version_string(void); +extern int __C_library_version_number(void); + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __STDLIB_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __STDLIB_NO_EXPORTS + #ifndef __STRICT_ANSI__ + using std::atoll; + using std::strtoll; + using std::strtoull; + using std::lldiv_t; + #endif + using std::div_t; + using std::ldiv_t; + using std::atof; + using std::atoi; + using std::atol; + using std::strtod; + using std::strtol; + using std::strtoul; + using std::rand; + using std::srand; + using std::calloc; + using std::free; + using std::malloc; + using std::realloc; + using std::__heapprt; + using std::__heapstats; + using std::__heapvalid; + using std::abort; + using std::atexit; + using std::exit; + using std::getenv; + using std::system; + using std::bsearch; + using std::qsort; + using std::abs; + using std::div; + using std::labs; + using std::ldiv; + #ifndef __STRICT_ANSI__ + using std::llabs; + using std::lldiv; + #endif + using std::__sdiv32by16; + using std::__udiv32by16; + using std::__sdiv64by32; + using std::__rt_sdiv32by16; + using std::__rt_udiv32by16; + using std::__rt_sdiv64by32; + using std::__fp_status; + using std::mblen; + using std::mbtowc; + using std::wctomb; + using std::mbstowcs; + using std::wcstombs; + using std::__use_realtime_heap; + using std::__use_two_region_memory; + using std::__C_library_version_string; + using std::__C_library_version_number; + using std::size_t; + #endif + #endif +#endif +/* end of stdlib.h */ diff --git a/inc/C_H/string.h b/inc/C_H/string.h new file mode 100644 index 0000000..7d47450 --- /dev/null +++ b/inc/C_H/string.h @@ -0,0 +1,359 @@ +/* string.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.11 */ +/* Copyright (C) Codemist Ltd., 1988-1993. */ +/* Copyright 1991-1993 ARM Limited. All rights reserved. */ +/* version 0.04 */ + +/* + * RCS $Revision: 1.10.2.2 $ + * Checkin $Date: 2001/05/23 21:56:08 $ + */ + +/* + * string.h declares one type and several functions, and defines one macro + * useful for manipulating character arrays and other objects treated as + * character arrays. Various methods are used for determining the lengths of + * the arrays, but in all cases a char * or void * argument points to the + * initial (lowest addresses) character of the array. If an array is written + * beyond the end of an object, the behaviour is undefined. + */ + +#ifndef __string_h +#define __string_h + + #ifndef __STRING_DECLS + #define __STRING_DECLS + + #undef __CLIBNS + + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) + /* unconditional in C++ and non-strict C for consistency of debug info */ + typedef unsigned int size_t; +#elif !defined(__size_t) + #define __size_t 1 + typedef unsigned int size_t; /* see */ +#endif + +#undef NULL +#define NULL 0 /* see */ + +extern void *memcpy(void * /*s1*/, const void * /*s2*/, size_t /*n*/); + /* + * copies n characters from the object pointed to by s2 into the object + * pointed to by s1. If copying takes place between objects that overlap, + * the behaviour is undefined. + * Returns: the value of s1. + */ +extern void *memmove(void * /*s1*/, const void * /*s2*/, size_t /*n*/); + /* + * copies n characters from the object pointed to by s2 into the object + * pointed to by s1. Copying takes place as if the n characters from the + * object pointed to by s2 are first copied into a temporary array of n + * characters that does not overlap the objects pointed to by s1 and s2, + * and then the n characters from the temporary array are copied into the + * object pointed to by s1. + * Returns: the value of s1. + */ +extern char *strcpy(char * /*s1*/, const char * /*s2*/); + /* + * copies the string pointed to by s2 (including the terminating nul + * character) into the array pointed to by s1. If copying takes place + * between objects that overlap, the behaviour is undefined. + * Returns: the value of s1. + */ +extern char *strncpy(char * /*s1*/, const char * /*s2*/, size_t /*n*/); + /* + * copies not more than n characters (characters that follow a null + * character are not copied) from the array pointed to by s2 into the array + * pointed to by s1. If copying takes place between objects that overlap, + * the behaviour is undefined. + * Returns: the value of s1. + */ + +extern char *strcat(char * /*s1*/, const char * /*s2*/); + /* + * appends a copy of the string pointed to by s2 (including the terminating + * null character) to the end of the string pointed to by s1. The initial + * character of s2 overwrites the null character at the end of s1. + * Returns: the value of s1. + */ +extern char *strncat(char * /*s1*/, const char * /*s2*/, size_t /*n*/); + /* + * appends not more than n characters (a null character and characters that + * follow it are not appended) from the array pointed to by s2 to the end of + * the string pointed to by s1. The initial character of s2 overwrites the + * null character at the end of s1. A terminating null character is always + * appended to the result. + * Returns: the value of s1. + */ + +/* + * The sign of a nonzero value returned by the comparison functions is + * determined by the sign of the difference between the values of the first + * pair of characters (both interpreted as unsigned char) that differ in the + * objects being compared. + */ + +extern int memcmp(const void * /*s1*/, const void * /*s2*/, size_t /*n*/); + /* + * compares the first n characters of the object pointed to by s1 to the + * first n characters of the object pointed to by s2. + * Returns: an integer greater than, equal to, or less than zero, according + * as the object pointed to by s1 is greater than, equal to, or + * less than the object pointed to by s2. + */ +extern int strcmp(const char * /*s1*/, const char * /*s2*/); + /* + * compares the string pointed to by s1 to the string pointed to by s2. + * Returns: an integer greater than, equal to, or less than zero, according + * as the string pointed to by s1 is greater than, equal to, or + * less than the string pointed to by s2. + */ +extern int strncmp(const char * /*s1*/, const char * /*s2*/, size_t /*n*/); + /* + * compares not more than n characters (characters that follow a null + * character are not compared) from the array pointed to by s1 to the array + * pointed to by s2. + * Returns: an integer greater than, equal to, or less than zero, according + * as the string pointed to by s1 is greater than, equal to, or + * less than the string pointed to by s2. + */ +extern int strcoll(const char * /*s1*/, const char * /*s2*/); + /* + * compares the string pointed to by s1 to the string pointed to by s2, both + * interpreted as appropriate to the LC_COLLATE category of the current + * locale. + * Returns: an integer greater than, equal to, or less than zero, according + * as the string pointed to by s1 is greater than, equal to, or + * less than the string pointed to by s2 when both are interpreted + * as appropriate to the current locale. + */ + +extern size_t strxfrm(char * /*s1*/, const char * /*s2*/, size_t /*n*/); + /* + * transforms the string pointed to by s2 and places the resulting string + * into the array pointed to by s1. The transformation function is such that + * if the strcmp function is applied to two transformed strings, it returns + * a value greater than, equal to or less than zero, corresponding to the + * result of the strcoll function applied to the same two original strings. + * No more than n characters are placed into the resulting array pointed to + * by s1, including the terminating null character. If n is zero, s1 is + * permitted to be a null pointer. If copying takes place between objects + * that overlap, the behaviour is undefined. + * Returns: The length of the transformed string is returned (not including + * the terminating null character). If the value returned is n or + * more, the contents of the array pointed to by s1 are + * indeterminate. + */ + + +#ifdef __cplusplus +extern const void *memchr(const void * /*s*/, int /*c*/, size_t /*n*/); +extern "C++" inline void *memchr(void * __s, int __c, size_t __n) + { return /*const_cast*/(void *)( + memchr(/*const_cast*/(const void *)(__s), __c, __n)); } +#else +extern void *memchr(const void * /*s*/, int /*c*/, size_t /*n*/); +#endif + /* + * locates the first occurence of c (converted to an unsigned char) in the + * initial n characters (each interpreted as unsigned char) of the object + * pointed to by s. + * Returns: a pointer to the located character, or a null pointer if the + * character does not occur in the object. + */ + +#ifdef __cplusplus +extern const char *strchr(const char * /*s*/, int /*c*/); +extern "C++" inline char *strchr(char * __s, int __c) + { return /*const_cast*/(char *)( + strchr(/*const_cast*/(const char *)(__s), __c)); } +#else +extern char *strchr(const char * /*s*/, int /*c*/); +#endif + /* + * locates the first occurence of c (converted to an char) in the string + * pointed to by s (including the terminating null character). + * Returns: a pointer to the located character, or a null pointer if the + * character does not occur in the string. + */ + +extern size_t strcspn(const char * /*s1*/, const char * /*s2*/); + /* + * computes the length of the initial segment of the string pointed to by s1 + * which consists entirely of characters not from the string pointed to by + * s2. The terminating null character is not considered part of s2. + * Returns: the length of the segment. + */ + +#ifdef __cplusplus +extern const char *strpbrk(const char * /*s1*/, const char * /*s2*/); +extern "C++" inline char *strpbrk(char * __s1, const char * __s2) + { return /*const_cast*/(char *)( + strpbrk(/*const_cast*/(const char *)(__s1), __s2)); } +#else +extern char *strpbrk(const char * /*s1*/, const char * /*s2*/); +#endif + /* + * locates the first occurence in the string pointed to by s1 of any + * character from the string pointed to by s2. + * Returns: returns a pointer to the character, or a null pointer if no + * character form s2 occurs in s1. + */ + +#ifdef __cplusplus +extern const char *strrchr(const char * /*s*/, int /*c*/); +extern "C++" inline char *strrchr(char * __s, int __c) + { return /*const_cast*/(char *)( + strrchr(/*const_cast*/(const char *)(__s), __c)); } +#else +extern char *strrchr(const char * /*s*/, int /*c*/); +#endif + /* + * locates the last occurence of c (converted to a char) in the string + * pointed to by s. The terminating null character is considered part of + * the string. + * Returns: returns a pointer to the character, or a null pointer if c does + * not occur in the string. + */ + +extern size_t strspn(const char * /*s1*/, const char * /*s2*/); + /* + * computes the length of the initial segment of the string pointed to by s1 + * which consists entirely of characters from the string pointed to by S2 + * Returns: the length of the segment. + */ + +#ifdef __cplusplus +extern const char *strstr(const char * /*s1*/, const char * /*s2*/); +extern "C++" inline char *strstr(char * __s1, const char * __s2) + { return /*const_cast*/(char *)( + strstr(/*const_cast*/(const char *)(__s1), __s2)); } +#else +extern char *strstr(const char * /*s1*/, const char * /*s2*/); +#endif + /* + * locates the first occurence in the string pointed to by s1 of the + * sequence of characters (excluding the terminating null character) in the + * string pointed to by s2. + * Returns: a pointer to the located string, or a null pointer if the string + * is not found. + */ + +extern char *strtok(char * /*s1*/, const char * /*s2*/); + /* + * A sequence of calls to the strtok function breaks the string pointed to + * by s1 into a sequence of tokens, each of which is delimited by a + * character from the string pointed to by s2. The first call in the + * sequence has s1 as its first argument, and is followed by calls with a + * null pointer as their first argument. The separator string pointed to by + * s2 may be different from call to call. + * The first call in the sequence searches for the first character that is + * not contained in the current separator string s2. If no such character + * is found, then there are no tokens in s1 and the strtok function returns + * a null pointer. If such a character is found, it is the start of the + * first token. + * The strtok function then searches from there for a character that is + * contained in the current separator string. If no such character is found, + * the current token extends to the end of the string pointed to by s1, and + * subsequent searches for a token will fail. If such a character is found, + * it is overwritten by a null character, which terminates the current + * token. The strtok function saves a pointer to the following character, + * from which the next search for a token will start. + * Each subsequent call, with a null pointer as the value for the first + * argument, starts searching from the saved pointer and behaves as + * described above. + * Returns: pointer to the first character of a token, or a null pointer if + * there is no token. + */ + +extern void *memset(void * /*s*/, int /*c*/, size_t /*n*/); + /* + * copies the value of c (converted to an unsigned char) into each of the + * first n charactes of the object pointed to by s. + * Returns: the value of s. + */ +extern char *strerror(int /*errnum*/); + /* + * maps the error number in errnum to an error message string. + * Returns: a pointer to the string, the contents of which are + * implementation-defined. The array pointed to shall not be + * modified by the program, but may be overwritten by a + * subsequent call to the strerror function. + */ +extern size_t strlen(const char * /*s*/); + /* + * computes the length of the string pointed to by s. + * Returns: the number of characters that precede the terminating null + * character. + */ + +extern void __use_iso8859_locale(void); +extern void __use_iso8859_ctype(void); +extern void __use_iso8859_collate(void); +extern void __use_iso8859_monetary(void); +extern void __use_iso8859_numeric(void); + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __STRING_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __STRING_NO_EXPORTS + using std::size_t; + using std::memcpy; + using std::memmove; + using std::strcpy; + using std::strncpy; + using std::strcat; + using std::strncat; + using std::memcmp; + using std::strcmp; + using std::strncmp; + using std::strcoll; + using std::strxfrm; + using std::memchr; + using std::strchr; + using std::strcspn; + using std::strpbrk; + using std::strrchr; + using std::strspn; + using std::strstr; + using std::strtok; + using std::memset; + using std::strerror; + using std::strlen; + #ifdef __locale_selectors_declared + using std::__use_iso8859_locale; + using std::__use_iso8859_ctype; + using std::__use_iso8859_collate; + using std::__use_iso8859_monetary; + using std::__use_iso8859_numeric; + #endif + #endif + #endif + +#endif + +/* end of string.h */ + + + + diff --git a/inc/C_H/time.h b/inc/C_H/time.h new file mode 100644 index 0000000..fd63439 --- /dev/null +++ b/inc/C_H/time.h @@ -0,0 +1,240 @@ +/* time.h: ANSI 'C' (X3J11 Oct 88) library header, section 4.12 */ +/* Copyright (C) Codemist Ltd., 1988-1993. */ +/* Copyright 1991-1993 ARM Limited. All rights reserved. */ +/* version 0.03 */ + +/* + * time.h declares two macros, four types and several functions for + * manipulating time. Many functions deal with a calendar time that + * represents the current date (according to the Gregorian + * calendar) and time. Some functions deal with local time, which + * is the calendar time expressed for some specific time zone, and + * with Daylight Savings Time, which is a temporary change in the + * algorithm for determining local time. + */ + +/* + * RCS $Revision: 1.8.2.2 $ + * Checkin $Date: 2001/05/23 21:56:08 $ + * Revising $Author: sdouglas $ + */ + +#ifndef __time_h +#define __time_h + + #ifndef __TIME_DECLS + #define __TIME_DECLS + + #undef __CLIBNS + + #ifdef __cplusplus + #ifdef __EDG_RUNTIME_USES_NAMESPACES + namespace std { + #define __CLIBNS std:: + #else + #define __CLIBNS :: + #endif /* ifdef __EDG_RUNTIME_USES_NAMESPACES */ + + extern "C" { + #else + #define __CLIBNS + #endif /* __cplusplus */ + +#if defined(__cplusplus) || !defined(__STRICT_ANSI__) + /* unconditional in C++ and non-strict C for consistency of debug info */ + typedef unsigned int size_t; +#elif !defined(__size_t) + #define __size_t 1 + typedef unsigned int size_t; /* see */ +#endif + +#undef NULL +#define NULL 0 /* see */ + + /* CLOCKS_PER_SEC: the number per second of the value returned by the + * clock function. */ +#ifdef __CLK_TCK +# define CLOCKS_PER_SEC __CLK_TCK +#else +# define CLOCKS_PER_SEC 100 +#endif +#ifndef __STRICT_ANSI__ +#define CLK_TCK CLOCKS_PER_SEC +#endif + +typedef unsigned int clock_t; /* cpu time type */ +typedef unsigned int time_t; /* date/time in unix secs past 1-Jan-70 */ + +struct tm { + int tm_sec; /* seconds after the minute, 0 to 60 + (0 - 60 allows for the occasional leap second) */ + int tm_min; /* minutes after the hour, 0 to 59 */ + int tm_hour; /* hours since midnight, 0 to 23 */ + int tm_mday; /* day of the month, 1 to 31 */ + int tm_mon; /* months since January, 0 to 11 */ + int tm_year; /* years since 1900 */ + int tm_wday; /* days since Sunday, 0 to 6 */ + int tm_yday; /* days since January 1, 0 to 365 */ + int tm_isdst; /* Daylight Savings Time flag */ +}; + /* struct tm holds the components of a calendar time, called the broken-down + * time. The value of tm_isdst is positive if Daylight Savings Time is in + * effect, zero if Daylight Savings Time is not in effect, and negative if + * the information is not available. + */ + +extern clock_t clock(void); + /* determines the processor time used. + * Returns: the implementation's best approximation to the processor time + * used by the program since program invocation. The time in + * seconds is the value returned divided by the value of the macro + * CLK_TCK. The value (clock_t)-1 is returned if the processor time + * used is not available. + */ +extern double difftime(time_t /*time1*/, time_t /*time0*/); + /* + * computes the difference between two calendar times: time1 - time0. + * Returns: the difference expressed in seconds as a double. + */ +extern time_t mktime(struct tm * /*timeptr*/); + /* + * converts the broken-down time, expressed as local time, in the structure + * pointed to by timeptr into a calendar time value with the same encoding + * as that of the values returned by the time function. The original values + * of the tm_wday and tm_yday components of the structure are ignored, and + * the original values of the other components are not restricted to the + * ranges indicated above. On successful completion, the values of the + * tm_wday and tm_yday structure components are set appropriately, and the + * other components are set to represent the specified calendar time, but + * with their values forced to the ranges indicated above; the final value + * of tm_mday is not set until tm_mon and tm_year are determined. + * Returns: the specified calendar time encoded as a value of type time_t. + * If the calendar time cannot be represented, the function returns + * the value (time_t)-1. + */ +extern time_t time(time_t * /*timer*/); + /* + * determines the current calendar time. The encoding of the value is + * unspecified. + * Returns: the implementations best approximation to the current calendar + * time. The value (time_t)-1 is returned if the calendar time is + * not available. If timer is not a null pointer, the return value + * is also assigned to the object it points to. + */ + +extern char *asctime(const struct tm * /*timeptr*/); + /* + * converts the broken-down time in the structure pointed to by timeptr into + * a string in the form "Sun Sep 16 01:03:52 1973\n\0". + * Returns: a pointer to the string containing the date and time. + */ +extern char *ctime(const time_t * /*timer*/); + /* + * converts the calendar time pointed to by timer to local time in the form + * of a string. It is equivalent to asctime(localtime(timer)); + * Returns: the pointer returned by the asctime function with that + * broken-down time as argument. + */ +extern struct tm *gmtime(const time_t * /*timer*/); + /* + * converts the calendar time pointed to by timer into a broken-down time, + * expressed as Greenwich Mean Time (GMT). + * Returns: a pointer to that object or a null pointer if GMT not available. + */ +extern struct tm *localtime(const time_t * /*timer*/); + /* + * converts the calendar time pointed to by timer into a broken-down time, + * expressed a local time. + * Returns: a pointer to that object. + */ +extern size_t strftime(char * /*s*/, size_t /*maxsize*/, + const char * /*format*/, const struct tm * /*timeptr*/); + /* + * places characters into the array pointed to by s as controlled by the + * string pointed to by format. The format string consists of zero or more + * directives and ordinary characters. A directive consists of a % character + * followed by a character that determines the directive's behaviour. All + * ordinary characters (including the terminating null character) are copied + * unchanged into the array. No more than maxsize characters are placed into + * the array. Each directive is replaced by appropriate characters as + * described in the following list. The appropriate characters are + * determined by the LC_TIME category of the current locale and by the + * values contained in the structure pointed to by timeptr. + * %a is replaced by the locale's abbreviated weekday name. + * %A is replaced by the locale's full weekday name. + * %b is replaced by the locale's abbreviated month name. + * %B is replaced by the locale's full month name. + * %c is replaced by the locale's appropriate date and time representation. + * %d is replaced by the day of the month as a decimal number (01-31). + * %H is replaced by the hour (24-hour clock) as a decimal number (00-23). + * %I is replaced by the hour (12-hour clock) as a decimal number (01-12). + * %j is replaced by the day of the year as a decimal number (001-366). + * %m is replaced by the month as a decimal number (01-12). + * %M is replaced by the minute as a decimal number (00-59). + * %p is replaced by the locale's equivalent of either AM or PM designations + * associated with a 12-hour clock. + * %S is replaced by the second as a decimal number (00-61). + * %U is replaced by the week number of the year (Sunday as the first day of + * week 1) as a decimal number (00-53). + * %w is replaced by the weekday as a decimal number (0(Sunday) - 6). + * %W is replaced by the week number of the year (Monday as the first day of + * week 1) as a decimal number (00-53). + * %x is replaced by the locale's appropriate date representation. + * %X is replaced by the locale's appropriate time representation. + * %y is replaced by the year without century as a decimal number (00-99). + * %Y is replaced by the year with century as a decimal number. + * %Z is replaced by the timezone name or abbreviation, or by no characters + * if no time zone is determinable. + * %% is replaced by %. + * If a directive is not one of the above, the behaviour is undefined. + * Returns: If the total number of resulting characters including the + * terminating null character is not more than maxsize, the + * strftime function returns the number of characters placed into + * the array pointed to by s not including the terminating null + * character. otherwise, zero is returned and the contents of the + * array are indeterminate. + */ + + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + } /* namespace std */ + #endif + #endif /* __TIME_DECLS */ + + #ifdef __EDG_RUNTIME_USES_NAMESPACES + #ifndef __TIME_NO_EXPORTS + using std::clock_t; + using std::time_t; + using std::tm; + using std::tm; + using std::clock; + using std::difftime; + using std::mktime; + using std::time; + using std::asctime; + using std::ctime; + using std::gmtime; + using std::localtime; + using std::strftime; + #endif + #endif + +#endif + +/* end of time.h */ + + + + + + + + + + + + + diff --git a/inc/agps_service.h b/inc/agps_service.h new file mode 100644 index 0000000..e38e5ad --- /dev/null +++ b/inc/agps_service.h @@ -0,0 +1,101 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: agps_service.h + * Author: 梁震 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. 创建agps_service模块 + 2. 销毁agps_service模块 + 3. agps_service模块定时处理入口 + * History: + 1. Date: 2019-03-01 + Author: 梁震 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __agps_service_H__ +#define __agps_service_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "socket.h" + + +typedef enum +{ + AGPS_REQ_TIMING = 0xDA, // 校时 + AGPS_ACK_TIMING = 0xDB, // 校时响应 + AGPS_REQ_EPO = 0xDC, // 请求epo数据 + AGPS_EPO_ACK = 0xDD, + AGPS_REQ_TAIDOU = 0xDE, // 请求泰斗A-GNSS文件数据 + AGPS_TAIDOU_ACK = 0xDF, + AGPS_REQ_ZKW = 0xEA, // 请求中科微A-GNSS文件数据 //AT6558 + AGPS_ZKW_ACK = 0xEB, +}ProtocolAGPSEnum; + +/** + * Function: 创建agps_service模块 + * Description:创建agps_service模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE agps_service_create(bool first_create); + +/** + * Function: 销毁agps_service模块 + * Description:销毁agps_service模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE agps_service_destroy(void); + +/** + * Function: agps_service模块定时处理入口 + * Description:agps_service模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 1秒钟调用1次 + */ +GM_ERRCODE agps_service_timer_proc(void); + + +void agps_service_connection_failed(void); +void agps_service_connection_ok(void); +void agps_service_close_for_reconnect(void); +float agps_service_get_unfix_lng(void); +float agps_service_get_unfix_lat(void); + +typedef enum +{ + AGPS_TO_GPS_LNGLAT_TIME, + AGPS_TO_GPS_DATA, +}AgpsToGpsEnum; + + +/** + * Function: gps模块请求写参考数据 + * Description: gps准备好后,请求agps模块写数据, 如果此时agps模块无数据,将等到准备好后再写, + * Input: type:数据类型;re_download:是否重新下载数据 + * Output: 无 + * Return: true——有数据没写完;false——已经写完最后一片数据 + * Others: 无 + */ +bool agps_service_require_to_gps(AgpsToGpsEnum type,bool re_download); + +void agps_service_delele_file(void); + +#endif + + diff --git a/inc/applied_math.h b/inc/applied_math.h new file mode 100644 index 0000000..62fa050 --- /dev/null +++ b/inc/applied_math.h @@ -0,0 +1,234 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: applied_math.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-02-28 + * Description: 应用数学运算 + * Others: + * Function List: + 1. 获取数值的符号 + 2. 四舍五入取整 + 3. 三维向量取模 + 4. 二维向量取模 + 5. 三维向量的归一化处理 + 6. 二维向量的归一化处理 + 7. 三维向量内积(点积) + 8. 二维向量内积(点积) + 9. 三维向量叉积 + 10.三维向量之间的夹角 + 11.根据经纬度计算两点间距离 + 12.计算普通CRC校验值 + 13.计算EPO CRC校验值 + * History: + 1. Date: 2019-02-28 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __APPLIED_MATH_H__ +#define __APPLIED_MATH_H__ + +#include "gm_type.h" + +#define GRAVITY_CONSTANT 9.80665 + +#define MSEC_PER_SECONDS 1000 + +#define SECONDS_PER_MIN 60 + +#define MINS_PER_HOUR 60 + +#define SECONDS_PER_HOUR (SECONDS_PER_MIN*MINS_PER_HOUR) + +#define HOURS_PER_DAY 24 + +#define DAYS_PER_YEAR 365 + +#define SECONDS_PER_DAY (HOURS_PER_DAY * SECONDS_PER_HOUR) + +#define SECONDS_PER_YEAR (SECONDS_PER_HOUR*HOURS_PER_DAY*DAYS_PER_YEAR) + + +//二维向量类型及指针类型 +typedef struct +{ + float x; + float y; +} Vector2D, *PVector2D; + +//三维向量类型及指针类型 +typedef struct +{ + float x; + float y; + float z; +} Vector3D, *PVector3D; + +/** + * Function: 获取数值的符号 + * Description:获取双精度浮点型变量的符号 + * Input: value——输入的双精度浮点型变量 + * Output: 无 + * Return: 1——正数;-1——负数;0——0值 + * Others: + */ +char applied_math_get_sign(double value); + +/** + * Function: 四舍五入取整 + * Description:获取双精度浮点型变量的四舍五入整数值 + * Input: value——输入的双精度浮点型变量 + * Output: 无 + * Return: 取整后的整型值 + * Others: + */ +S32 applied_math_round(double value); + +/** + * Function: 三维向量取模 + * Description:三维向量取模 + * Input: v——输入的三维向量 + * Output: 无 + * Return: 三维向量的模 + * Others: + */ +double applied_math_get_magnitude_3d(Vector3D v); + +/** + * Function: 二维向量求模 + * Description:二维向量求模 + * Input: v——输入的三维向量 + * Output: 无 + * Return: 二维向量的模 + * Others: + */ +double applied_math_get_magnitude_2d(Vector2D v); + +/** + * Function: 三维向量的归一化处理 + * Description:三维向量的的各个分量除以向量的模 + * Input: v——输入的三维向量 + * Output: 无 + * Return: 三维向量的归一化向量 + * Others: + */ +Vector3D applied_math_normalize_3d(Vector3D v); + +/** + * Function: 二维向量的归一化处理 + * Description:二维向量的的各个分量除以向量的模 + * Input: v——输入的三维向量 + * Output: 无 + * Return: 二维向量的归一化向量 + * Others: + */ +Vector2D applied_math_normalize_2d(Vector2D v); + +/** + * Function: 三维向量内积(点积) + * Description:求两个三维向量的内积 + * Input: a——第一个三维向量;b——第二个三维向量 + * Output: 无 + * Return: 三维向量的内积(点积) + * Others: + */ +float applied_math_inner_product_3d(Vector3D a, Vector3D b); + +/** + * Function: 二维向量内积(点积) + * Description:求两个二维向量的内积 + * Input: a——第一个二维向量;b——第二个二维向量 + * Output: 无 + * Return: 二维向量的内积(点积) + * Others: + */ +float applied_math_inner_product_2d(Vector2D a, Vector2D b); + +/** + * Function: 三维向量叉积 + * Description:求两个三维向量的叉积 + * Input: a——第一个三维向量;b——第二个三维向量 + * Output: 无 + * Return: 三维向量的叉积 + * Others: + */ +Vector3D applied_math_cross_product_3d(Vector3D u, Vector3D v); + +/** + * Function: 三维向量之间的夹角 + * Description:求两个三维向量之间的夹角 + * Input: a——第一个三维向量;b——第二个三维向量 + * Output: 无 + * Return: 夹角(单位为度,四舍五入取整),范围[0,180] + * Others: + */ +U8 applied_math_get_angle_3d(Vector3D a, Vector3D b); + +/** + * Function: 圆周上两个角度之间的夹角 + * Description: + * Input: angle_degree1——第1个角度(单位度);angle_degree2——第2个角度(单位度) + * Output: 无 + * Return: 夹角,范围[0,180] + * Others: + */ +U16 applied_math_get_angle_diff(U16 angle_degree1, U16 angle_degree2); + +/** + * Function: 根据经纬度计算两点间距离 + * Description:根据起始和结束的经纬度坐标,求两点之间的距离 + * Input: start_lng——起始点经度;start_lat——起始点纬度;end_lng——结束点经度;end_lat——结束点纬度; + * Output: 无 + * Return: 距离(单位为米) + * Others: + */ +double applied_math_get_distance(double start_lng, double start_lat, double end_lng, double end_lat); + +/** + * Function: 计算普通CRC校验值 + * Description:计算一段数据的16位CRC校验值 + * Input: p_data——数据起始地址;len——数据长度 + * Output: 无 + * Return: CRC校验值 + * Others: + */ +U16 applied_math_calc_common_crc16(const U8* p_data, U32 len); + +/** + * Function: 计算EPO CRC校验值 + * Description:计算一段数据的16位CRC校验值 + * Input: p_data——数据起始地址;offset——偏移量;len——数据长度;pre_val—— + * Output: 无 + * Return: CRC校验值 + * Others: + */ +U32 applied_math_calc_epo_crc16(const U8* p_data, U32 len, U32 pre_val); + +/** + * Function: 一阶滞后滤波 + * Description:优点:对周期性干扰具有良好的抑制作用适用于波动频率较高的场合 + 缺点:相位滞后,灵敏度低,不能消除滤波频率高于采样频率的 1/2 的干扰信号 + * Input: last_value——历史值;new_value——实时值;len——数据长度;alpha(0,1]——滤波系数 + * Output: 无 + * Return: 滤波后的值 + * Others: + */ +float applied_math_lowpass_filter(const float last_value, const float new_value, float alpha); + +/** + * Function: 计算平均值 + * Description: + * Input: p_array——数组指针;len——数组长度 + * Output: 无 + * Return: 数组平均值 + * Others: + */ +float applied_math_avage(const float* p_array,const U16 len); + +#endif + diff --git a/inc/auto_test.h b/inc/auto_test.h new file mode 100644 index 0000000..da8e720 --- /dev/null +++ b/inc/auto_test.h @@ -0,0 +1,112 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: auto_test.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-05-25 + * Description: + * Others: + * Function List: + 1. 创建auto_test模块 + 2. 销毁auto_test模块 + 3. auto_test模块定时处理入口 + * History: + 1. Date: 2019-05-25 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __AUTO_TEST_H__ +#define __AUTO_TEST_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "system_state.h" + + + /** + * Function: 创建auto_test模块 + * Description:创建auto_test模块 + * Input: is_self_check:true——自检;false——自动化测试 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE auto_test_create(bool is_self_check); + + /** + * Function: 销毁auto_test模块 + * Description:销毁auto_test模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE auto_test_destroy(void); + +/** + * Function: 自检结果恢复默认值 + * Description: + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 恢复出厂设置时调用 + */ +GM_ERRCODE auto_test_reset(void); + + + /** + * Function: auto_test模块定时处理入口 + * Description:auto_test模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 1秒调用1次 + */ +GM_ERRCODE auto_test_timer_proc(void); + +/** + * Function: 获取自检结果 + * Description: + * Input: result:自检结果json字符串 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void auto_test_get_result(bool is_history,char* json_str); + +/** + * Function: acc开计数器 + * Description: + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void auto_test_acc_on(void); + +/** + * Function: acc关闭计数器 + * Description: + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void auto_test_acc_off(void); + +/** + * Function: 修复GSM校准值 + * Description:03设备校准值大于540修改为540,05设备校准值大于520修改为520 + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void auto_test_repair_ramp(void); +#endif + diff --git a/inc/bms.h b/inc/bms.h new file mode 100644 index 0000000..abcfb4e --- /dev/null +++ b/inc/bms.h @@ -0,0 +1,70 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: bms.h + * Author: 李耀轩 + * Version: 1.0 + * Date: 2019-07-22 + * Description: + * Others: + * Function List: + 1. 创建bms模块 + 2. 销毁bms模块 + 3. bms模块定时处理入口 + * History: + 1. Date: 2019-07-22 + Author: 李耀轩 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __BMS_H_ +#define __BMS_H_ +#include "error_code.h" +#include "gm_type.h" + + + +/** + * Function: 创建bms模块 + * Description:创建bms模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE bms_create(void); + +/** + * Function: 销毁bms模块 + * Description:销毁bms模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE bms_destroy(void); + +/** + * Function: bms模块定时处理入口 + * Description:bms模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 1秒钟调用1次 + */ +GM_ERRCODE bms_timer_proc(void); + + +GM_ERRCODE bms_cmd_write(char *cmd, u8 len); + +GM_ERRCODE bms_msg_receive(char* p_cmd, u16 cmd_len); + +GM_ERRCODE bms_uart_receive_data(char* p_cmd, u16 cmd_len, char* p_rsp, void * pmsg); + + +#endif /*__BMS_H_*/ + + diff --git a/inc/call.h b/inc/call.h new file mode 100644 index 0000000..dd966a0 --- /dev/null +++ b/inc/call.h @@ -0,0 +1,73 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: sms.h + * Author: 李耀轩 + * Version: 1.0 + * Date: 2019-03-07 + * Description: + * Others: + * Function List: + 1. 创建call模块 + 2. 销毁call模块 + 3. call模块定时处理入口 + * History: + 1. Date: 2019-03-07 + Author: 李耀轩 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __CALL_H__ +#define __CALL_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "gm_call.h" + +/** + * Function: 创建call模块 + * Description:创建call模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE call_create(void); + +/** + * Function: 销毁call模块 + * Description:销毁call模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE call_destroy(void); + +/** + * Function: call模块定时处理入口 + * Description:call模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 1秒钟调用1次 + */ +GM_ERRCODE call_timer_proc(void); + + + +/** + * Function: 发送短信 + * Description: + * Input: + * dist_number[in]:拨打号码参数指针 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gm_make_phone_call(const u8 *dist_number); + +#endif diff --git a/inc/circular_queue.h b/inc/circular_queue.h new file mode 100644 index 0000000..3630941 --- /dev/null +++ b/inc/circular_queue.h @@ -0,0 +1,231 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: circular_queue.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-07 + * Description: 循环队列,存放整型和浮点型数据,循环覆盖写 + * Others: + * Function List: + 1. 创建circular_queue + 2. 销毁circular_queue + 3. 获取队列容量 + 4. 队列是否为空 + 5. 清空队列 + 6. 队列是否已满 + 7. 获取队列长度 + 8. 入队 + 9. 出队 + 10.获取队列头元素 + 11.获取队列尾元素 + 12.获取队列第n个元素 + * History: + 1. Date: 2019-03-07 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __CIRCULAR_QUEUE_H__ +#define __CIRCULAR_QUEUE_H__ + +#include "gm_type.h" +#include "error_code.h" + +typedef enum +{ + GM_QUEUE_TYPE_INT = 0, + GM_QUEUE_TYPE_FLOAT = 1 +} GM_QUEUE_TYPE; + +//使用者不要直接使用结构体成员变量 +typedef struct +{ + float* f_buf; + S32* i_buf; + + //指向第一个元素 + U16 head; + + //指向最后一个元素的下一个位置 + U16 tail; + + //队列容量 + U16 capacity; +} CircularQueue, *PCircularQueue; + +/** + * Function: 创建CircularQueue + * Description:不要直接使用结构体内的成员变量 + * Input: capacity:队列容量(单元个数,不是字节数);type:整型或者浮点型 + * Output: p_queue:指向队列的指针 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE circular_queue_create(PCircularQueue p_queue, const U16 capacity, const GM_QUEUE_TYPE type); + +/** + * Function: 销毁CircularQueue + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针;type:整型或者浮点型 + * Output: p_queue:指向队列的指针 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +void circular_queue_destroy(PCircularQueue p_queue, GM_QUEUE_TYPE type); + +/** + * Function: 获取队列的容量 + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针 + * Output: 无 + * Return: 队列的容量 + * Others: + */ +U16 circular_queue_get_capacity(const PCircularQueue p_queue); + +/** + * Function: 队列是否为空 + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针 + * Output: 无 + * Return: true——空;false——不空 + * Others: + */ +bool circular_queue_is_empty(const PCircularQueue p_queue); + +/** + * Function: 清空队列(注意不是销毁) + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针 + * Output: p_queue:指向队列的指针 + * Return: 无 + * Others: + */ +void circular_queue_empty(PCircularQueue p_queue); + +/** + * Function: 队列是否已满 + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针 + * Output: 无 + * Return: true——满;false——未满 + * Others: + */ +bool circular_queue_is_full(const PCircularQueue p_queue); + +/** + * Function: 获取队列长度 + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针 + * Output: 无 + * Return: 队列长度 + * Others: + */ +U16 circular_queue_get_len(const PCircularQueue p_queue); + +/** + * Function: 浮点型数据入队 + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针;value:入队的数据 + * Output: p_queue:指向队列的指针 + * Return: 无 + * Others: 如果队列已满,会覆盖队头数据 + */ +void circular_queue_en_queue_f(PCircularQueue p_queue, float value); + +/** + * Function: 整型数据入队 + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针;value:入队的数据 + * Output: p_queue:指向队列的指针 + * Return: 无 + * Others: 如果队列已满,会覆盖队头数据 + */ +void circular_queue_en_queue_i(PCircularQueue p_queue, S32 value); + +/** + * Function: 浮点型数据出队 + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针;p_value:出队的数据指针 + * Output: p_queue:指向队列的指针 + * Return: true——成功;false——失败(队列空) + * Others: + */ +bool circular_queue_de_queue_f(PCircularQueue p_queue, float* p_value); + +/** + * Function: 整型数据出队 + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针;p_value:出队的数据指针 + * Output: p_queue:指向队列的指针 + * Return: true——成功;false——失败(队列空) + * Others: + */ +bool circular_queue_de_queue_i(PCircularQueue p_queue, S32* p_value); + +/** + * Function: 获取队头元素(浮点型) + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针 + * Output: p_value:数据指针 + * Return: true——成功;false——失败(队列空) + * Others: + */ +bool circular_queue_get_head_f(const PCircularQueue p_queue, float* p_value); + +/** + * Function: 获取队头元素(整型) + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针 + * Output: p_value:数据指针 + * Return: true——成功;false——失败(队列空) + * Others: + */ +bool circular_queue_get_head_i(const PCircularQueue p_queue, S32* p_value); + +/** + * Function: 获取队尾元素(浮点型) + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针 + * Output: p_value:数据指针 + * Return: true——成功;false——失败(队列空) + * Others: + */ +bool circular_queue_get_tail_f(const PCircularQueue p_queue, float* p_value); + +/** + * Function: 获取队尾元素(整型) + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针 + * Output: p_value:数据指针 + * Return: true——成功;false——失败(队列空) + * Others: + */ +bool circular_queue_get_tail_i(const PCircularQueue p_queue, S32* p_value); + +/** + * Function: 获取第index(从0开始)个元素(浮点型) + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针 + * Output: p_value:数据指针 + * Return: true——成功;false——失败(队列空) + * Others: + */ +bool circular_queue_get_by_index_f(const PCircularQueue p_queue, const U16 index, float* p_value); + +/** + * Function: 获取第index(从0开始)个元素(整型) + * Description:不要直接使用结构体内的成员变量 + * Input: p_queue:指向队列的指针 + * Output: p_value:数据指针 + * Return: true——成功;false——失败(队列空) + * Others: + */ +bool circular_queue_get_by_index_i(const PCircularQueue p_queue, const U16 index, S32* p_value); + +#endif + diff --git a/inc/command.h b/inc/command.h new file mode 100644 index 0000000..9bb6479 --- /dev/null +++ b/inc/command.h @@ -0,0 +1,54 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: command.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. 创建command模块 + 2. 销毁command模块 + 3. command模块定时处理入口 + * History: + 1. Date: 2019-03-01 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __COMMAND_H__ +#define __COMMAND_H__ + +#include +#include "error_code.h" + +#define CMD_MAX_LEN 1024 + + +typedef enum +{ + COMMAND_UART = 0, + COMMAND_SMS = 1, + COMMAND_GPRS = 2, +}CommandReceiveFromEnum; + +/** + * Function: 配置指令入口函数 + * Description:配置指令入口函数 + * Input: from[in]:输入数据来源CommandReceiveFromEnum + * p_cmd[in]: 输入数据指针 + * src_len[in]: 输入数据长度 + pinfo: 短信原始信息 + * Output: p_rsp[out]:输出数据指针 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE command_on_receive_data(CommandReceiveFromEnum from, char* p_cmd, u16 src_len, char* p_rsp, void * pmsg); + + +#endif + diff --git a/inc/config_save.h b/inc/config_save.h new file mode 100644 index 0000000..a52f3eb --- /dev/null +++ b/inc/config_save.h @@ -0,0 +1,11 @@ +#ifndef __CONFIG_SAVE_H__ +#define __CONFIG_SAVE_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "socket.h" +#include "applied_math.h" + +#endif + + diff --git a/inc/config_service.h b/inc/config_service.h new file mode 100644 index 0000000..9a0aecb --- /dev/null +++ b/inc/config_service.h @@ -0,0 +1,791 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: config_service.h + * Author: 梁震 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. 创建config_service模块 + 2. 销毁config_service模块 + 3. config_service模块定时处理入口 + * History: + 1. Date: 2019-03-01 + Author: 梁震 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __CONFIG_SERVICE_H__ +#define __CONFIG_SERVICE_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "socket.h" +#include "gps.h" + +//发布版修改这个数字 +#define VERSION_NUMBER "2.0.70" + + +#define APN_DEFAULT "CMNET" +#define APN_USER_DEFAULT "" +#define APN_PWD_DEFAULT "" +#define GOOME_IMEI_DEFAULT "866717048888889" +#define UPDATE_OEM_CODE "GOOME" +#define UPDATE_DEVICE_CODE "DEVICEID00001" +#define UPDATE_BOOT_CODE "FFFFFFFF" +#define CONFIG_LITE_SERVER_ADDERSS "litedev.gmiot.net:10021" +#define CONFIG_LITE_SERVER_IP "119.23.109.222" +#define CONFIG_GOOCAR_SERVER_ADDERSS "gs03.szdatasource.com:8821" +#define CONFIG_GOOCAR_SERVER_IP "54.222.183.200" +#define CONFIG_FACTORY_SERVER_ADDERSS "factorytest.gpsorg.net:8821" +#define CONFIG_SERVER_ADDERSS "config.gpsorg.net:39996" +#define CONFIG_SERVER_IP "47.106.251.151" +#define CONFIG_AGPS_SERVER_ADDERSS "agps.srv.gpsorg.net:8866" +#define CONFIG_AGPS_SERVER_IP "119.23.200.49" +#define CONFIG_LOG_SERVER_ADDERSS "firmwarelog.gpsorg.net:39998" +#define CONFIG_LOG_SERVER_IP "47.106.251.151" +#define GOOME_UPDATE_SERVER_DNS "firmware.gpsorg.net:39999" +#define GOOME_UPDATE_SERVER_IP "47.106.251.151" + +#define CONFIG_CMD_MAX_LEN 10 +#define CONFIG_STRING_MAX_LEN 100 + +#define CONFIG_UPLOAD_TIME_MAX 10800ul +#define CONFIG_UPLOAD_TIME_DEFAULT 10 +#define CONFIG_UPLOAD_TIME_MIN 3 +#define CONFIG_SPEEDTHR_MAX 180 +#define CONFIG_SPEEDTHR_MIN 5 +#define CONFIG_STATIC_TIME_MAX 500 +#define CONFIG_ACCTHR_MAX 2.0f +#define CONFIG_ACCTHR_MIN 0.1f +#define CONFIG_BRAKETHR_MAX 3.0f +#define CONFIG_BRAKETHR_MIN 0.5f +#define CONFIG_CRASHLTHR_MAX 6.0f +#define CONFIG_CRASHLTHR_MIN 1.0f +#define CONFIG_CRASHMTHR_MAX 8.0f +#define CONFIG_CRASHMTHR_MIN 4.0f +#define CONFIG_CRASHHTHR_MAX 15.0f +#define CONFIG_CRASHHTHR_MIN 8.0f +#define CONFIG_TURNTHR_MAX 5.0f +#define CONFIG_TURNTHR_MIN 0.1f +#define CONFIG_STATICTHR_MAX 1.0f +#define CONFIG_STATICTHR_MIN 0.0f +#define CONFIG_RUNTHR_MAX 1.0f +#define CONFIG_RUNTHR_MIN 0.0f +#define CONFIG_QUAKETHR_MAX 1.0f +#define CONFIG_QUAKETHR_MIN 0.0f +#define CONFIG_LOW_VOLTHR_MAX 15.0f +#define CONFIG_LOW_VOLTHR_MIN 0.0f +#define GOOME_LITEDEV_DNS ".gmiot.net" +#define GOOME_GPSOO_DNS ".szdatasource.com" +#define GOOME_HEARTBEAT_MAX 360ul +#define GOOME_HEARTBEAT_DEFAULT 180ul +#define GOOME_HEARTBEAT_MIN 3 +#define GOOME_SLEEPTIME_MAX 30 +#define GOOME_SLEEPTIME_DEFAULT 5 +#define GOOME_SLEEPTIME_MIN 0 +#define CONFIG_ANGLETIME_MAX 0xFF +#define CONFIG_ANGLETIME_DEFAULT 10 +#define CONFIG_ANGLETIME_MIN 0 +#define CONFIG_SHAKECOUT_MAX 100 +#define CONFIG_SHAKECOUT_DEFAULT 5 +#define CONFIG_SHAKECOUT_MIN 1 +#define CONFIG_AUTODEFDELAY_MAX 1200 +#define CONFIG_AUTODEFDELAY_DEFAULT 300 +#define CONFIG_AUTODEFDELAY_MIN 1 +#define CONFIG_SHAKEALARMDELAY_MAX 1200 +#define CONFIG_SHAKEALARMDELAY_DEFAULT 30 +#define CONFIG_SHAKEALARMDELAY_MIN 1 +#define CONFIG_SHAKEALARMINTERVAL_MAX 3600 +#define CONFIG_SHAKEALARMINTERVAL_DEFAULT 1800 +#define CONFIG_SHAKEALARMINTERVAL_MIN 1 + +#define GOOME_MAPS_URL_DEFAULT "http://ditu.google.cn/maps?q=" +//部标厂商标志. 后面可通过参数配置来修改. +#define LOW_VOLTAGE_ALARM_PERCENT 0.8 +#define JT_OEM_ID "11111" +#define JT_DEV_ID "9887125" +#define JT_VEHICLE_NUMBER "粤B99988" +#define GB_ATTYPE_STANDARD 0x00 //标准 +#define GB_ATTYPE_CUSTOM 0x01 //补充 +#define LBS_UPLOAD_DEFAULT 60 +#define GPS_NOT_FIXED_DEFAULT 60 + + +typedef enum +{ + //为兼容的原因, 这些配置要连在一起 BEGIN + CFG_SERVERADDR, // 主服务器地址,xxx.xxx.xxx.xxx:port = 0 + CFG_UPLOADTIME, // 上传gps间隔 + CFG_SPEEDTHR, // 超速阀值 + CFG_PROTOCOL, // ConfigProtocolEnum + CFG_CUTOFFALM_DISABLE, // 断电报警开关 0,打开,1:关闭 + CFG_LOWBATTALM_DISABLE, // 电池低电报警开关 0,打开,1:关闭 + CFG_SLEEP_TIME, // 休眠时间 + CFG_CUTOILFUNC, // 断油电功能开关 + CFG_ACCFUNC, // ACC功能开关 + CFG_DEVICETYPE, // 设备型号 //= 10 + CFG_SERVERLOCK, // 是否锁IP(域名) + CFG_BATTUPLOAD_DISABLE, // 是否上传电量 1 :不上传 0:上传 默认0 + CFG_VIBSETWAY, // 震动报警是否手动设防 + CFG_VOLTAGETHR, // 工作电压阈值 + CFG_GSENNUM, // 加速度传感器数量 + CFG_GSENRANGE, // 加速度传感器量程 + CFG_HBPROTOCOL, // 心跳协议ConfigHearUploadEnum + CFG_SEN_RAPID_ACLR, // ACC阈值 ACCTHR + CFG_SEN_EMERGENCY_BRAKE, // 急刹车阈值 BRAKETHR + CFG_SEN_SLIGHT_COLLISION, // 轻微碰撞阈值 CRASHTHR_L //= 20 + CFG_SEN_NORMAL_COLLISION, // 一般碰撞阈值 CRASHTHR_M + CFG_SEN_SERIOUS_COLLISION,// 严重碰撞阈值 CRASHTHR_H + CFG_SEN_SUDDEN_TURN, // 急转弯阈值 TURNTHR + CFG_SEN_STATIC, // 静止阈值 STATICTHR + CFG_SEN_RUN, // 运动阈值 RUNTHR + CFG_SEN_QUAKE_ALARM, // 震动报警阈值 QUAKETHR + CFG_SEN_LOWVOlTAGE_ALARM, // 低于最高电压百分多少算低电压(目前没用) LOWVOLPERT + CFG_JT_HBINTERVAL, // 部标位置数据心跳的发送间隔 替代CFG_HBTPOSTHR + //为兼容的原因, 这些配置连在一起 END + + //中心号(28) + CFG_CENTER_NUMBER, + + //以下四个number的id要连在一起 + CFG_USER1_NUMBER, // = 30 + CFG_USER2_NUMBER, + CFG_USER3_NUMBER, + CFG_USER4_NUMBER, + + //1 agps 0 epo 由于有CFG_GPS_TYPE,该配置已无用 + CFG_OPEN_APGS, + + //GPS关闭:0——不关闭,1——关闭 + CFG_GPS_CLOSE, + + //GPS模块型号[TYPE_INT]:0——未知;1——内置GPS模块(串口速率115200);2——泰斗(串口速率9600);3-中科微(串口速率9600),added by bruce + CFG_GPS_TYPE, + + //GPS定位检测时间,默认5秒 + CFG_GPS_UPDATE_TIME, + + CFG_WAIT_GPS_TIME, + + CFG_LBS_INTERVAL, + + CFG_HEART_INTERVAL, // = 40 + + //最小SNR + CFG_MIN_SNR, + + //安装方向显示时间, 默认10分钟, 0xFF一直显示 + CFG_SEN_ANGLE_SHOW_TIME, + + //拐点角度阈值[TYPE_INT],默认20度 + CFG_TURN_ANGLE, + + //在多少秒内[TYPE_BYTE],默认10秒 + CFG_AWAKE_CHECK_TIME, + + //接上,震动几次开始唤醒[TYPE_BYTE],默认3次 + CFG_AWAKE_COUNT, + + //传感器中断灵敏度[TYPE_INT],1-127, 1最灵敏,默认2 + CFG_SHAKE_LEVEL, + + //G-SENSOR震动阈值(mg)[TYPE_INT],默认40mg + CFG_SHAKE_THRESHOLD, + + //震动报警判断次数,默认5次 + CFG_SHAKE_COUNT, + + //震动检测间隔时间,默认10秒 + CFG_SHAKE_CHECK_TIME, + + //自动设防模式下震动报警延时,默认120秒 + CFG_SHAKE_ALARM_DELAY, // = 50 + + //震动报警间隔(单位分钟),默认30分钟 + CFG_SHAKE_ALARM_INTERVAL, + + //ACC OFF后多久设防,默认300秒 + CFG_AUTO_DEFENCE_DELAY, + + //静止上传检测时间默认20秒 + CFG_STATIC_CHECK_TIME, + + //静止上传检测最小速度默认6km + CFG_STATIC_CHECK_SPEED, + + //静止上传检测次数默认3次 + CFG_STATIC_CHECK_COUNT, + + // 上传时间间隔内,小速度漂移距离(56) + CFG_DISTANCE_FOR_LOW_SPEED, + + // 是否关闭防漂移, 0打开防漂移 ,1 关闭防漂移 + CFG_CLOSE_DRIFT_DETECT, + + // 超速报警开关, 1打开 , 0 关闭 + CFG_SPEED_ALARM_ENABLE, + + CFG_SPEED_CHECK_TIME, + + //断电报警检测时间(默认5秒) + CFG_POWER_CHECK_TIME, // = 60 + + //断电报警最小充电时间 + CFG_POWER_CHARGE_MIN_TIME, + + //断电报警ACC跳变检测时间 + CFG_POWER_ACC_CHECK_TIME, + + //断电报警方式 00: 只GPRS方式 01:SMS+GPRS 10: GPRS+SMS+CALL 11:GPRS+CALL 默认:01 + CFG_POWER_ALARM_MODE, + CFG_SENSOR_ALARM_MODE, // g_sensor 报警方式 00: 只GPRS方式 01:SMS+GPRS 10: GPRS+SMS+CALL 11:GPRS+CALL 默认:01 + + //打开GPS多久后AGPS准备好要重新打开GPS + CFG_REOPEN_GSP_TIME, + + //ACC错误检测时间最小 10分钟,最大24小时 + CFG_ACC_CHECK_TIME, + + //是否应用层管理电池 + CFG_APP_BATTERT_MGR, + + //0——发送所有sos;1——只发送第一个报警号码 + CFG_ALARM_SMS_ONE, + + //开机充电延迟时间(外部控制用):分钟; + CFG_CHARGE_DELAY, + + /*配置服务器地址,xxx.xxx.xxx.xxx:port*/ + CFG_CFGSERVERADDR, //=70 + + /*测试服务器地址,xxx.xxx.xxx.xxx:port*/ + CFG_TEST_SERVERADDR, + + /*AGPS服务器地址,xxx.xxx.xxx.xxx:port*/ + CFG_AGPSSERVERADDR, + + /*日志服务器地址,xxx.xxx.xxx.xxx:port*/ + CFG_LOGSERVERADDR, + + /*更新服务器地址,xxx.xxx.xxx.xxx:port*/ + CFG_UPDATESERVERADDR, + + /*文件服务器地址,xxx.xxx.xxx.xxx:port*/ + CFG_UPDATEFILESERVER, + + + CFG_MAP_URL, // 地图url + CFG_PROTOCOL_VER, // APP协议号 + CFG_SIM, // sim号 + CFG_APN_CHECK, // 自适应APN开关 + CFG_APN_NAME, //80 + CFG_APN_USER, + CFG_APN_PWD, + + //语言 + // concox 语言 无报警中文:0x00 0x01 无报警英文:0x00 0x02 + // goome 01 中文 00 英文 + CFG_LANGUAGE, + + //时区[TYPE_BYTE] + CFG_TIME_ZONE, + + //0 自动设防模式,1 手动设防模式,默认自动设防 + CFG_IS_MANUAL_DEFENCE, + //0 关闭震动报警,1 打开震动报警,默认关闭 + CFG_IS_SHAKE_ALARM_ENABLE, + //休眠时是否把串口设置为IO口状态 0: 不设置 1:设置 默认 0 + CFG_IS_UART_IO_WHEN_SLEEP, + //串口2波特率 0:115200 1:9600 + CFG_IS_UART_9600, //90 + //是否平滑处理轨迹 + CFG_SMOOTH_TRACK, + //是否支持90V电源,added by bruce + CFG_IS_90V_POWER, + //是否支持断油路功能 0:不支持, 1:支持 + CFG_IS_RELAY_ENABLE, + //基站上传开关默认关闭 + CFG_IS_LBS_ENABLE, + // 静止上传定位点开关 默认关闭 + CFG_IS_STATIC_UPLOAD, + //是否开启车辆移动报警 + CFG_IS_MOVEALARM_ENABLE, + //是否开启加速度报警(急加速、急减速、急转弯报警) + CFG_IS_ACLRALARM_ENABLE, + //是否打开BMS功能,默认关闭 + CFG_BMS, + //BMS版本 + CFG_BMS_VER, + + + CFG_CUSTOM_CODE, //客户代码 + CFG_TERM_MODEL, //终端型号ID + CFG_TERM_VERSION, //终端当前版本号 //100 + CFG_TERM_BOOT_CHECK, //终端当前版本BOOT校验码 + + //部标 是否已注册,只在设备开电后注册一次,改设备号则要重新注册 + CFG_JT_ISREGISTERED, + // 部标协议类型 + CFG_JT_AT_TYPE, + // 终端ID + CFG_JT_DEVICE_ID, + // 车牌号码 + CFG_JT_VEHICLE_NUMBER, + // 车牌颜色 + CFG_JT_VEHICLE_COLOR, + // 厂商ID + CFG_JT_OEM_ID, + // 省域ID + CFG_JT_PROVINCE, + // 市域ID + CFG_JT_CITY, + //验证码 + CFG_JT_AUTH_CODE, // 110 + + //当前是否测试模式 + CFG_IS_TEST_MODE, + + CFG_PARAM_MAX +}ConfigParamEnum; + +typedef enum +{ + TYPE_NONE = 0x00, + TYPE_INT = 0x01, + TYPE_SHORT = 0x02, + TYPE_STRING = 0x03, + TYPE_BOOL = 0X04, + TYPE_FLOAT = 0X05, + TYPE_BYTE = 0x06, + TYPE_MAX +}ConfigParamDataType; + +typedef enum +{ + CFG_CMD_REQ = 0x13, + CFG_CMD_ACK = 0x92, + CFG_CMD_RESULT = 0x14, + CFG_CMD_MAX +}ConfigCmdEnum; + +typedef enum +{ + CFG_CMD_REQ_ALL = 0x00, + CFG_CMD_REQ_ONCE = 0x01, + CFG_CMD_REQ_PERMANENT= 0x02, +}ConfigCmdReqType; + +typedef enum +{ + HEART_SMART = 0x00, //0x03 or 0x07 + HEART_NORMAL = 0x01, //0x03 + HEART_EXPAND = 0x02, //0x07 + HEART_MAX +}ConfigHearUploadEnum; + + +typedef struct +{ + ConfigParamDataType type; + union + { + u8* str; + u32 i; + u16 s; + u8 b; + float f; + }data; + u16 len; +} ConfigParamItems; + + +typedef enum +{ + PROTOCOL_NONE = 0x00, + PROTOCOL_GOOME = 0x01, + PROTOCOL_CONCOX = 0x02, + PROTOCOL_JT808 = 0x03, + PROTOCOL_BSJ = 0x04, + PROTOCOL_MAX +}ConfigProtocolEnum; + + +typedef enum +{ + PROTOCOL_VER_GT02 = 0x01,//康凯斯V3协议版本 GT02D + PROTOCOL_VER_JT808 = 0x01,//标准808协议 + PROTOCOL_VER_GT06 = 0x02,//康凯斯GT06协议 + PROTOCOL_VER_CMCC_JT808 = 0x02, //四川移动808协议 + PROTOCOL_APP_MAX +}ConfigProtocolVer; + + +typedef enum +{ + DEVICE_NONE = 0, + DEVICE_GS03A, //4线单sensor + DEVICE_AS03A, //4线单sensor + DEVICE_GS03B, //2线单sensor 无电池 + DEVICE_AS03B, //2线单sensor 无电池 + DEVICE_GS03F,//2线单sensor 有电池 + DEVICE_AS03F,//2线单sensor 有电池 + DEVICE_GS07A,//4线单sensor 90V + DEVICE_AS07A,//4线单sensor 90V + DEVICE_GS07B,//2线单sensor 有电池90V + DEVICE_AS07B,//2线单sensor 有电池90V + DEVICE_GS03I, //2线双sensor 无电池 + DEVICE_AS03I, //2线双sensor 无电池 + DEVICE_GS03H, //4线双sensor + DEVICE_GS05A, //4线单sensor 90V + DEVICE_GS05B, //2线单sensor 无电池 90V + DEVICE_GS05F, //2线单sensor 电池90V + DEVICE_GS05I, //2线双sensor 无电池 + DEVICE_GS05H, //4线双sensor + DEVICE_GM06E,//同GS03A,客户定制 + DEVICE_GS10, //5V供电 单sensor 无电池 BMS + + DEVICE_MAX, +}ConfigDeviceTypeEnum; + + +//断电报警方式 00: 只GPRS方式 01:SMS+GPRS 10: GPRS+SMS+CALL 11:GPRS+CALL 默认:01 +typedef enum +{ + PWRALM_GPRS = 0, + PWRALM_GPRS_SMS = 1, + PWRALM_GPRS_SMS_CALL = 2, + PWRALM_GPRS_CALL = 3, +}PowerAlarmMode; + +/** + * Function: 创建config_service模块 + * Description:创建config_service模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE config_service_create(void); + +/** + * Function: 销毁config_service模块 + * Description:销毁config_service模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE config_service_destroy(void); + +/** + * Function: config_service模块定时处理入口 + * Description:config_service模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 1秒钟调用1次 + */ +GM_ERRCODE config_service_timer_proc(void); + + +/** + * Function: + * Description: 配置socket连接正常 + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void config_service_connection_ok(void); + +/** + * Function: + * Description: 配置socket连接失败 + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void config_service_connection_failed(void); +void config_service_close_for_reconnect(void); + + + +/** + * Function: + * Description: 获取指定id对应的配置 + * Input: id:配置id type:数据类型 + * Output: 无 + * Return: 数据长度 + * Others: 该函数只有字符串类型的配置, 不知道长度里, 需要先调用以获知长度 + */ +u16 config_service_get_length(ConfigParamEnum id, ConfigParamDataType type); + +/** + * Function: + * Description: 根据id与type 获取配置到buf中. + * Input: id:配置id type:数据类型 buf:输出,用来存储配置数据 len:buf长度 + * Output: 无 + * Return: 无 + * Others: 无 + */ +GM_ERRCODE config_service_get(ConfigParamEnum id, ConfigParamDataType type, void* buf, u16 len); + +/** + * Function: + * Description: 根据id与type 把 buf中的内容 设置到config_service模块 + * Input: id:配置id type:数据类型 buf:用来存储配置数据 len:buf长度 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void config_service_set(ConfigParamEnum id, ConfigParamDataType type, const void* buf, u16 len); + +/** + * Function: + * Description: 此函数可代替config_service_get, 特别是string类型, 会少掉字符串拷贝的时间 + * Input: id:配置id + * Output: 无 + * Return: 指向id对应配置的指针 + * Others: 无 + */ +void* config_service_get_pointer(ConfigParamEnum id); + + +/** + * Function: + * Description: 获取当前协议配置 + * Input: 无 + * Output: 无 + * Return: 当前协议 + * Others: 无 + */ +ConfigProtocolEnum config_service_get_app_protocol(void); + +/** + * Function: + * Description: 获取当前心跳协议配置 + * Input: 无 + * Output: 无 + * Return: 心跳协议 + * Others: 无 + */ +ConfigHearUploadEnum config_service_get_heartbeat_protocol(void); + +/** + * Function: + * Description: 获取当前时区配置 + * Input: 无 + * Output: 无 + * Return: 时区 + * Others: 无 + */ +S8 config_service_get_zone(void); + + +/** + * Function: + * Description: 用何种心跳协议 + * Input: 无 + * Output: 无 + * Return: 心跳协议 + * Others: 无 + */ +bool config_service_is_main_server_goome(void); + + + +/** + * Function: + * Description: 告警只发送给一个号码 + * Input: 无 + * Output: 无 + * Return: 心跳协议 + * Others: 无 + */ +bool config_service_is_alarm_sms_to_one(void); + +/** + * Function: + * Description: 获取短信发送号码 + * Input: 无 + * Output: 无 + * Return: 号码长度 + * Others: 无 + */ +u8 config_service_get_sos_number(u8 index, u8 *buf, u16 len); + + + +/** + * Function: + * Description: 是否启用agps, 如果不是, 表示启用epo + * Input: 无 + * Output: 无 + * Return: 1 apgs 0 epo + * Others: 无 + */ +bool config_service_is_agps(void); + + + +/** + * Function: + * Description: 获取当前gps类型 + * Input: 无 + * Output: 无 + * Return: 时区 + * Others: 无 + */ +GPSChipType config_service_get_gps_type(void); + + + +/** + * Function: + * Description: 从本地配置文件中获取配置信息 + * Input: configs列表指针 + * Output: configs列表指针 + * Return: GM_SUCCESS 成功, 其它失败 + * Others: 无 + */ +GM_ERRCODE config_service_read_from_local(void); + +/** + * Function: + * Description: 保存配置到本地文件中 + * Input: configs列表指针 + * Output: 无 + * Return: GM_SUCCESS 成功, 其它失败 + * Others: 无 + */ +GM_ERRCODE config_service_save_to_local(void); + + +/** + * Function: 设置设备型号 + * Description: 设置当前设备型号 + * Input: configs列表指针 + * Output: configs列表指针 + * Return: GM_SUCCESS 成功, 其它失败 + * Others: 无 + */ +void config_service_set_device(ConfigDeviceTypeEnum type); + + +/** + * Function: 根据ID获取设备型号 + * Description:获取设备型号(字符串) + * Input: 设备型号 + * Output: + * Return: 设备型号(字符串) + * Others: 无 + */ +const char * config_service_get_device_type(u16 index); + +/** + * Function: + * Description: 获取设备型号ID + * Input: 设备型号(字符串) + * Output: + * Return: 设备型号ID + * Others: 无 + */ +ConfigDeviceTypeEnum config_service_get_device_type_id(const char* dev_type); + +/** + * Function: + * Description: 恢复出厂设置 + * Input: configs列表指针 is_all(是不是包括ip地址设置) + * Output: configs列表指针 + * Return: GM_SUCCESS 成功, 其它失败 + * Others: 无 + */ +void config_service_restore_factory_config(bool is_all); + +/** + * Function: + * Description: 设置测试模式 + * Input: state:true——进入测试模式;false——退出测试模式 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void config_service_set_test_mode(bool state); + + +/** + * Function: + * Description: 判断当前是不是测试模式 + * Input: 无 + * Output: 无 + * Return: true 测试模式 , false 非测试模式 + * Others: 无 + */ +bool config_service_is_test_mode(void); + +/** + * Function: + * Description: 判断当前的imei是否写死在代码中的默认imei + * Input: 无 + * Output: 无 + * Return: true GOOME_IMEI_DEFAULT , false 非 GOOME_IMEI_DEFAULT + * Others: 无 + */ +bool config_service_is_default_imei(void); + +/** + * Function: + * Description: 设置设备的sim号 + * Input: sim + * Output: GM_SUCCESS 成功, 其它失败 + * Return: 无 + * Others: 无 + */ +GM_ERRCODE config_service_set_device_sim(u8 *pdata); + + +/** + * Function: + * Description: 改变ip地址 + * Input: idx:配置id,其值是(xxx.xxx.xxx.xxx:port)形式; buf: dns ;len: dns长度 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void config_service_change_ip(ConfigParamEnum idx, u8 *buf, u16 len); + +/** + * Function: + * Description: 改变port + * Input: idx:配置id,其值是(xxx.xxx.xxx.xxx:port)形式; port:端 口 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void config_service_change_port(ConfigParamEnum idx, u16 port); + + +/* + +*/ +/** + * Function: + * Description: 升级使用的socket类型 + * Input: 无 + * Output: 无 + * Return: 升级使用的socket类型 + * Others: 无 + */ +StreamType config_service_update_socket_type(void); + +#endif + + diff --git a/inc/error_code.h b/inc/error_code.h new file mode 100644 index 0000000..94a1db9 --- /dev/null +++ b/inc/error_code.h @@ -0,0 +1,39 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: error_code.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-02-28 + * Description: 各模块公共错误码定义 + * Others: 成功为0,未知错误码为-1,其它已知错误码均为负整数 + * Function List: + * History: + 1. Date: 2019-02-28 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __ERROR_CODE_H__ +#define __ERROR_CODE_H__ + +typedef enum +{ + GM_SUCCESS = 0, //成功 + GM_UNKNOWN = -1, //未知错误 + GM_NOT_INIT = -2, //未初始化 + GM_MEM_NOT_ENOUGH = -3, //内存不足 + GM_PARAM_ERROR = -4, //参数错误 + GM_EMPTY_BUF = -5, //没有数据 + GM_ERROR_STATUS = -6, //状态错误 + GM_HARD_WARE_ERROR = -7, //硬件错误 + GM_SYSTEM_ERROR = -8, //系统错误 + GM_WILL_DELAY_EXEC = -9, //延迟执行 + GM_NET_ERROR = -10, //网络错误 +}GM_ERRCODE; + +#endif + diff --git a/inc/fifo.h b/inc/fifo.h new file mode 100644 index 0000000..82ea93d --- /dev/null +++ b/inc/fifo.h @@ -0,0 +1,62 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: fifo.h + * Author: 李耀轩 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. + 2. + 3. + * History: + 1. Date: 2019-03-01 + Author: 李耀轩 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __FILO_H__ +#define __FILO_H__ + +#include "gm_type.h" +#include "error_code.h" + + +#define MAX_FIFO_MSG_LEN 4096 + +typedef struct +{ + u32 read_idx; + u32 write_idx; + u32 size; /* total size */ + u32 msg_count; + u8* base_addr; +}FifoType; + + +GM_ERRCODE fifo_init(FifoType * fifo, u32 size); +GM_ERRCODE fifo_reset(FifoType * fifo); +GM_ERRCODE fifo_delete(FifoType * fifo); + +u32 fifo_get_msg_length(FifoType * fifo); + +GM_ERRCODE fifo_insert(FifoType * fifo, u8 *data, u32 len); +GM_ERRCODE fifo_retrieve(FifoType * fifo, u8 *data, u32 *len_p); +GM_ERRCODE fifo_peek(FifoType * fifo, u8 *data, u32 len); +GM_ERRCODE fifo_pop_len(FifoType * fifo, u32 len); + +//取出最大长度为*len_p的数据 +GM_ERRCODE fifo_peek_and_get_len(FifoType * fifo, u8 *data, u32 *len_p); + + +//取出最大长度为*len_p的数据,遇到split_by就停止,返回的数据包含until_char +GM_ERRCODE fifo_peek_until(FifoType* fifo, u8* data, u16* len_p, const u8 until_char); +#endif + + + diff --git a/inc/g_sensor.h b/inc/g_sensor.h new file mode 100644 index 0000000..6038c64 --- /dev/null +++ b/inc/g_sensor.h @@ -0,0 +1,228 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: g_sensor.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-01 + * Description: 运动传感器数据处理,控制GPS休眠与唤醒、判断运动状态(用于控制GPS是否产生数据)、相关报警 + * Others: 唤醒与休眠逻辑: + (1)任意1轴加速度差值大于40mg,传感器中断(任意一轴的差值大于16mg),以上两种事件10s钟监测到3次以上唤醒 + (2)连续5分钟没有监测到唤醒的条件休眠 + * Function List: + 1. 创建g_sensor模块 + 2. 销毁g_sensor模块 + 3. g_sensor模块定时处理入口 + 4. 获取g_sensor阈值 + 5. 设置g_sensor阈值 + 6. 获取g-sensor状态 + * History: + 1. Date: 2019-03-01 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __G_SENSOR_H__ +#define __G_SENSOR_H__ + +#include "gm_type.h" +#include "error_code.h" + + +//10秒钟内监测到3次以上震动唤醒 +#define SHAKE_COUNT_TO_AWAKE 3 +#define SHAKE_TIME_SECONDS 10 + + +//运动传感器最大数值,需要根据传感器型号调整 +#define G_SENSOR_MAX_VALUE 2047 + +//运动传感器最大量程,需要根据传感器型号进行调整 +#define G_SENSOR_RANGE 2.0 + +//传感器采样频率(每秒次数) +#define G_SENSOR_SAMPLE_FREQ 100 + +#define MIN_CRUISE_SPEED 20 + +typedef enum +{ + GSENSOR_TYPE_UNKNOWN = 0, //未知 + GSENSOR_TYPE_SC7A20 = 0x11, //批量生产使用中 + GSENSOR_TYPE_BMA253 = 0xFA, //已停产 + GSENSOR_TYPE_DA213 = 0x13, //测试通过,未批量生产 +}GSensorType; + + +typedef enum +{ + THRESHOLD_INDEX_FOR_RAPID_ACLR = 0, + THRESHOLD_INDEX_FOR_EMERGENCY_BRAKE = 1, + THRESHOLD_INDEX_FOR_SLIGHT_COLLISION = 2, + THRESHOLD_INDEX_FOR_NORMAL_COLLISION = 3, + THRESHOLD_INDEX_FOR_SERIOUS_COLLISION = 4, + THRESHOLD_INDEX_FOR_LOWVOlTAGE_ALARM = 5, + THRESHOLD_INDEX_FOR_QUAKE_ALARM = 6, + THRESHOLD_INDEX_FOR_STATIC = 7, + THRESHOLD_INDEX_FOR_RUN = 8, + THRESHOLD_INDEX_FOR_SUDDEN_TURN = 9, + THRESHOLD_ARRAY_LEN = 10, +}THRESHOLD_INDEX; + +typedef enum +{ + NO_COLLISION = 0, + SLIGHT_COLLISION = 1, + NORMAL_COLLISION = 2, + SERIOUS_COLLISION = 3 +}COLLISION_LEVEL; + +//角度变化超过30度认为发生了突变 +#define MIN_ANGLE_RANGE 30 + +//学习时长20秒 +#define STUDY_TIME_SEC 20 + +//首次运行至少需要多少条数据 +#define MIN_STUDY_GRAVITY_TIMES (STUDY_TIME_SEC*G_SENSOR_SAMPLE_FREQ) + +//传感器存储数据长度 +#define G_SENSOR_BUF_LEN MIN_STUDY_GRAVITY_TIMES + +//传感器存储数据长度 +#define G_SHAKE_BUF_LEN 50 + + +//急加速阈值0.4g->0.8 +#define RAPID_ACLR_THRESHOLD 0.8 + +//急刹车阈值0.7g->1.5 +#define EMERGENCY_BRAKE_THRESHOLD 1.5 + +//急转弯阈值0.3g->0.6 +#define SUDDEN_TURN_THRESHOLD 0.6 + +//[3g,5g)轻微碰撞(人不会受伤);[5g,10g)中等碰撞(人受轻伤);[10g,+∞)严重碰撞(人受重伤) +#define SLIGHT_COLLISION_MIN_ACLR 4.0 +#define NORMAL_COLLISION_MIN_ACLR 6.0 +#define SERIOUS_COLLISION_MIN_ACLR 10.0 + +//角度记录条数(2分钟数据) +#define ANGLE_RECORD_NUM (SECONDS_PER_MIN) +#define TURN_OVER_ANGLE 45 +#define REMOVE_ANGLE 30 + +//震动报警车辆垂直方向加速度阈值0.02g +#define QUAKE_ACLR_THRESHOLD 0.02 + +//运动转静止时车辆水平方向加速度阈值10mg +#define STATIC_ACLR_THRESHOLD 0.01 + +//静止转为运动状态的车辆水平方向加速度阈值20mg +#define RUN_ACLR_THRESHOLD 0.020 + +//连续加速度值小于阈值的次数,判断为静止:20秒,每秒钟100次 +#define MIN_LOW_ACLR_NUM (STUDY_TIME_SEC*G_SENSOR_SAMPLE_FREQ) + +//高加速度超过次数重置重力加速度:2分钟=120秒,每秒钟100次 +#define RESET_GRAVTITY_NUM (2*60*G_SENSOR_SAMPLE_FREQ) + +//连续MIN_CRUISE_SPEED_TIME秒匀速运动,即使加速度很小也不判为静止 +#define MIN_CRUISE_SPEED_TIME 5 + +/** + * Function: 创建g_sensor模块 + * Description:创建g_sensor模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE g_sensor_create(void); + +/** + * Function: 销毁g_sensor模块 + * Description:销毁g_sensor模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE g_sensor_destroy(void); + +/** + * Function: 重置无振动时间 + * Description:外部打开GPS模块要调用这个函数,否则可能很快又休眠了 + * Input: 无 + * Output: 无 + * Return: 无 + * Others: + */ +void g_sensor_reset_noshake_time(void); + +/** + * Function: g_sensor模块定时处理入口 + * Description:时间周期10ms + * Input: 无 + * Output: 无 + * Return: 无 + * Others: + */ +void g_sensor_timer_proc(void); + +/** + * Function: 获取传感器与水平面的夹角 + * Description:单位为度,范围[0,180] + * Input: 无 + * Output: 无 + * Return: 传感器与水平面的夹角 + * Others: + */ +U8 g_sensor_get_angle(void); + +/** + * Function: 获取传感器型号字符串 + * Description: + * Input: type:传感器型号,max_len:数组最大长度 + * Output: p_type_str:型号内容 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE g_sensor_get_typestr(GSensorType type,char* p_type_str,const U8 max_len); + + +/** + * Function: 获取传感器错误次数 + * Description: + * Input: 无 + * Output: 无 + * Return: 错误次数 + * Others: + */ +U32 g_sensor_get_error_count(void); + +/** + * Function: 获取传震动事件次数(读取数据) + * Description: + * Input: 无 + * Output: 无 + * Return: 震动事件次数 + * Others: + */ +U8 g_sensor_get_shake_event_count_when_read(void); + +/** + * Function: 获取传震动事件次数(中断) + * Description: + * Input: 无 + * Output: 无 + * Return: 震动事件次数 + * Others: + */ +U8 g_sensor_get_shake_event_count_when_eint(void); + +#endif + diff --git a/inc/goome_sdk_inc/gm_adc.h b/inc/goome_sdk_inc/gm_adc.h new file mode 100644 index 0000000..a13bdd9 --- /dev/null +++ b/inc/goome_sdk_inc/gm_adc.h @@ -0,0 +1,11 @@ + + +#ifndef __GM_ADC_H__ +#define __GM_ADC_H__ + +extern U32 GM_ReadAdc0(void); +extern U32 GM_ReadAdc1(void); +extern U32 GM_AdcRead(U8 adc_channel, U32 *adc_read_data); + +#endif + diff --git a/inc/goome_sdk_inc/gm_aidingEpo.h b/inc/goome_sdk_inc/gm_aidingEpo.h new file mode 100644 index 0000000..3521ffb --- /dev/null +++ b/inc/goome_sdk_inc/gm_aidingEpo.h @@ -0,0 +1,22 @@ + + +#ifndef __GM_AIDINGEPO_H__ +#define __GM_AIDINGEPO_H__ + + +extern s32 GM_EpoInit(PsFuncPtr epocallBack); + +extern s32 GM_GpsSendCmd(char* cmd);//给GPS发送指令,不用加校验 + +extern void GM_GpsUtcTime (int iYr,int iMo,int iDay,int iHr,int iMi,int iSe) ; + +//设置 GPS时间 UTC +extern void GM_GpsEpoPos(float lat,float lon,int alt); + +// 设置 参考坐标,经度,纬度,范围, 年,月,天,时,分,秒 +extern void GM_GpsPwrOn(void); + +extern void GM_GpsPwrOff(void); + +#endif + diff --git a/inc/goome_sdk_inc/gm_app.h b/inc/goome_sdk_inc/gm_app.h new file mode 100644 index 0000000..42988c1 --- /dev/null +++ b/inc/goome_sdk_inc/gm_app.h @@ -0,0 +1,48 @@ + +#ifndef _MAIN_H_ +#define _MAIN_H_ +#include "gm_type.h" +#include "string.h" +/**----------------------------------------------------------------------------* + ** Dependencies * + **---------------------------------------------------------------------------*/ +typedef struct _dll_func_entry +{ + U32 Func_Entry_Code; + union + { + U32 Func_Index; + U32 Func_RunTime_Addr; + } Func_Info; +}dll_func_entry; + + +typedef struct _dll_header_struct +{ + U32 version; + U32 feature; + U32 App_Main_Entry_Offset; + U32 APP_RO_Size; + U32 APP_RW_Size; + U32 APP_ZI_Size; + dll_func_entry* APP_func_entry; +} dll_header_struct; + + +typedef struct _dll_struct +{ + dll_header_struct header; + void* mem_block; + S32 app_code_base_addr; + S32 app_data_base_addr; + S32 app_zi_base_addr; + S32 app_main_entry_addr; + S32 export_func_count; + S32* export_funcs; + +}dll_struct; + +typedef void (*DLL_main_func)(dll_struct* dll); + +#endif //_MAIN_H_ + diff --git a/inc/goome_sdk_inc/gm_call.h b/inc/goome_sdk_inc/gm_call.h new file mode 100644 index 0000000..595a9c6 --- /dev/null +++ b/inc/goome_sdk_inc/gm_call.h @@ -0,0 +1,39 @@ +/***************************************************************************** +* Copyright Statement: +* -------------------- +* www.goome.net* + +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_gpio.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * GPIO API defines. + * + * Author: + * ------- + * ------- + * + *============================================================================ + * HISTORY + *---------------------------------------------------------------------------- + * + ****************************************************************************/ + +#ifndef __GM_CALL_H__ +#define __GM_CALL_H__ + + +extern void GM_CallAnswer(PsFuncPtr callback); +extern void GM_CallHangUp(void); +extern s32 GM_MakeCall(U8* Number,PsFuncPtr callback); + +#endif diff --git a/inc/goome_sdk_inc/gm_callback.h b/inc/goome_sdk_inc/gm_callback.h new file mode 100644 index 0000000..7dcb893 --- /dev/null +++ b/inc/goome_sdk_inc/gm_callback.h @@ -0,0 +1,54 @@ +/***************************************************************************** +* Copyright Statement: +* -------------------- +* www.goome.net +* +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_callback.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * Timer related APIs + * + * Author: + * ------- + * ------- + * + *============================================================================ + * HISTORY + *---------------------------------------------------------------------------- + * + ****************************************************************************/ + + +#ifndef __GM_CALLBACK_H__ +#define __GM_CALLBACK_H__ + +#include + +typedef enum { + GM_CB_UART1_RECEIVE, + GM_CB_UART2_RECEIVE, + GM_CB_UART3_RECEIVE, + GM_CB_SMS_RECEIVE, + GM_CB_CALL_RECEIVE, + GM_CB_FAKE_CELL_RECEIVE, + GM_CB_RECEIVE_END +}GmCallbackIdEnum; + +extern S32 GM_RegisterCallBack(GmCallbackIdEnum call_back_id,U32 call_back_function); + + +#endif /*__GM_CALLBACK_H__*/ + + + + diff --git a/inc/goome_sdk_inc/gm_eint.h b/inc/goome_sdk_inc/gm_eint.h new file mode 100644 index 0000000..0f4f6a2 --- /dev/null +++ b/inc/goome_sdk_inc/gm_eint.h @@ -0,0 +1,48 @@ +#ifndef __GM_EINT_H__ +#define __GM_EINT_H__ + +#include "gm_gpio.h" + +#define EDGE_SENSITIVE KAL_TRUE +#define LEVEL_SENSITIVE KAL_FALSE + + +typedef enum{ + GM_EINT0 = 0, + GM_EINT1, + GM_EINT2, + GM_EINT3, + GM_EINT4, + GM_EINT5, + GM_EINT6, + GM_EINT7, + GM_EINT8, + GM_EINT9, + GM_EINT10, + GM_EINT11, + GM_EINT12, + GM_EINT13, + GM_EINT14, + GM_EINT15, + GM_EINT16, + GM_EINT17, + GM_EINT18, + GM_EINT19, + GM_EINT20, + GM_EINT21, + GM_EINT22, + GM_EINT23, + GM_EINT24, + + GM_EINT_MAX +}Enum_EintName; + + +extern s32 GM_EintPinInit(Enum_PinName pinName); +extern s32 GM_EintSetPolarity(Enum_EintName eintPinName,BOOL eint_polarity); +extern s32 GM_EintRegister(Enum_EintName eintPinName, PsFuncPtr callback_eint, BOOL eint_polarity, BOOL sens); + + + +#endif + diff --git a/inc/goome_sdk_inc/gm_fs.h b/inc/goome_sdk_inc/gm_fs.h new file mode 100644 index 0000000..f5b992d --- /dev/null +++ b/inc/goome_sdk_inc/gm_fs.h @@ -0,0 +1,129 @@ +/***************************************************************************** +* www.goome.net +* +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_fs.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * Timer related APIs + * + * Author: + * ------- + * ------- + * + *============================================================================ + * HISTORY + *---------------------------------------------------------------------------- + * + ****************************************************************************/ + +#ifndef __GM_FS_H__ +#define __GM_FS_H__ + +#include +/**************************************************************************** + * Type of file access permitted + ***************************************************************************/ +#define GM_FS_READ_WRITE 0x00000000L +#define GM_FS_READ_ONLY 0x00000100L +#define GM_FS_CREATE 0x00010000L +#define GM_FS_CREATE_ALWAYS 0x00020000L +#define GM_FS_OPEN_SHARED 0x00000200L + + +/**************************************************************************** + * Type of file move permitted + ***************************************************************************/ +#define GM_FS_MOVE_COPY 0x00000001 // Move file|folder by copy +#define GM_FS_MOVE_KILL 0x00000002 // Delete the moved file|folder after moving +#define GM_FS_MOVE_OVERWRITE 0x00010000 // Overwrite the existed file in destination path when move file|folder + +#define GM_FS_ATTR_DIR 0x10 +#define GM_FS_ATTR_ARCHIVE 0x20 + +/**************************************************************************** + * + ***************************************************************************/ +#define GM_FS_FILE_TYPE 0x00000004 +#define GM_FS_DIR_TYPE 0x00000008 +#define GM_FS_RECURSIVE_TYPE 0x00000010 + + + +extern int GM_FS_Open(const U16 * FileName, UINT Flag); +extern int GM_FS_Close(int FileHandle); +extern int GM_FS_Read(int FileHandle, void * DataPtr, UINT Length, UINT * Read); +extern int GM_FS_Write(int FileHandle, void * DataPtr, UINT Length, UINT * Written); +extern int GM_FS_Seek(int FileHandle, int Offset, int Whence); +extern int GM_FS_Commit(int FileHandle); +extern int GM_FS_GetFileSize(int FileHandle, UINT * Size); +extern int GM_FS_GetFilePosition(int FileHandle, UINT * Position); +extern int GM_FS_Delete(const U16 * FileName); +extern int GM_FS_CheckFile(const U16 * FileName); +extern int GM_FS_GetCurrentDir(U16 * DirName, UINT MaxLength); +extern int GM_FS_SetCurrentDir(const U16 * DirName); +extern int GM_FS_CreateDir(const U16 * DirName); +extern int GM_FS_RemoveDir(const U16 * DirName); +extern int GM_FS_Rename(const U16 * FileName, const U16 * NewName); +extern int GM_FS_XDelete(const U16 * FullPath, UINT Flag, U8 *RecursiveStack, const UINT StackSize); +extern S32 GM_GetDiskFreeSpace(U16 *DriveName, U32 *free_space); + + + +#ifdef DFLSDJG +// error codes +#define RTF_NO_ERROR 0 +#define RTF_ERROR_RESERVED -1 +#define RTF_PARAM_ERROR -2 +#define RTF_INVALID_FILENAME -3 +#define RTF_DRIVE_NOT_FOUND -4 +#define RTF_TOO_MANY_FILES -5 +#define RTF_NO_MORE_FILES -6 +#define RTF_WRONG_MEDIA -7 +#define RTF_INVALID_FILE_SYSTEM -8 +#define RTF_FILE_NOT_FOUND -9 +#define RTF_INVALID_FILE_HANDLE -10 +#define RTF_UNSUPPORTED_DEVICE -11 +#define RTF_UNSUPPORTED_DRIVER_FUNCTION -12 +#define RTF_CORRUPTED_PARTITION_TABLE -13 +#define RTF_TOO_MANY_DRIVES -14 +#define RTF_INVALID_FILE_POS -15 +#define RTF_ACCESS_DENIED -16 +#define RTF_STRING_BUFFER_TOO_SMALL -17 +#define RTF_GENERAL_FAILURE -18 +#define RTF_PATH_NOT_FOUND -19 +#define RTF_FAT_ALLOC_ERROR -20 +#define RTF_ROOT_DIR_FULL -21 +#define RTF_DISK_FULL -22 +#define RTF_TIMEOUT -23 +#define RTF_BAD_SECTOR -24 +#define RTF_DATA_ERROR -25 +#define RTF_MEDIA_CHANGED -26 +#define RTF_SECTOR_NOT_FOUND -27 +#define RTF_ADDRESS_MARK_NOT_FOUND -28 +#define RTF_DRIVE_NOT_READY -29 +#define RTF_WRITE_PROTECTION -30 +#define RTF_DMA_OVERRUN -31 +#define RTF_CRC_ERROR -32 +#define RTF_DEVICE_RESOURCE_ERROR -33 +#define RTF_INVALID_SECTOR_SIZE -34 +#define RTF_OUT_OF_BUFFERS -35 +#define RTF_FILE_EXISTS -36 +#define RTF_LONG_FILE_POS -37 +#define RTF_FILE_TOO_LARGE -38 +#define RTF_BAD_DIR_ENTRY -39 +#define RTF_ATTR_CONFLICT -40 // Recoverable support: Can't specify FS_PROTECTION_MODE and FS_NONBLOCK_MODE +#define RTF_CHECKDISK_RETRY -41 // Recoverable support: used for CROSSLINK +#define RTF_LACK_OF_PROTECTION_SPACE -42 +#endif + +#endif diff --git a/inc/goome_sdk_inc/gm_gpio.h b/inc/goome_sdk_inc/gm_gpio.h new file mode 100644 index 0000000..8e232b4 --- /dev/null +++ b/inc/goome_sdk_inc/gm_gpio.h @@ -0,0 +1,265 @@ +/***************************************************************************** +* Copyright Statement: +* -------------------- +* www.goome.net +* +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_gpio.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * GPIO API defines. + * + * Author: + * ------- + * ------- + * + *============================================================================ + * HISTORY + *---------------------------------------------------------------------------- + * + ****************************************************************************/ + + +#ifndef __GM_GPIO_H__ +#define __GM_GPIO_H__ + +#include "gm_type.h" +/**************************************************************************** + * Enumeration for GPIO Pins available. + ***************************************************************************/ +typedef enum{ + GM_GPIO0 = 0, + GM_GPIO1, + GM_GPIO2, + GM_GPIO3, + GM_GPIO4, + GM_GPIO5, + GM_GPIO6, + GM_GPIO7, + GM_GPIO8, + GM_GPIO9, + GM_GPIO10, + GM_GPIO11, + GM_GPIO12, + GM_GPIO13, + GM_GPIO14, + GM_GPIO15, + GM_GPIO16, + GM_GPIO17, + GM_GPIO18, + GM_GPIO19, + GM_GPIO20, + GM_GPIO21, + GM_GPIO22, + GM_GPIO23, + GM_GPIO24, + GM_GPIO25, + GM_GPIO26, + GM_GPIO27, + GM_GPIO28, + GM_GPIO29, + GM_GPIO30, + GM_GPIO31, + GM_GPIO32, + GM_GPIO33, + GM_GPIO34, + GM_GPIO35, + GM_GPIO36, + GM_GPIO37, + GM_GPIO38, + GM_GPIO39, + GM_GPIO40, + GM_GPIO41, + GM_GPIO42, + GM_GPIO43, + GM_GPIO44, + GM_GPIO45, + GM_GPIO46, + GM_GPIO47, + GM_GPIO48, + GM_GPIO49, + GM_GPIO50, + GM_GPIO51, + GM_GPIO52, + GM_GPIO53, + GM_GPIO54, + GM_GPIO55, + GM_GPIO56, + GM_GPIO57, + + GM_GPIO_MAX + +}Enum_PinName; + + +#if 1 // Dec-08-2016 +#define UART1_RXD_PIN 10 +#define UART1_TXD_PIN 11 + +#define UART2_RXD_PIN 12 +#define UART2_TXD_PIN 17 + +#define UART3_RXD_PIN 0 +#define UART3_TXD_PIN 1 +#endif + + + +typedef enum{ + PINDIRECTION_IN = 0, + PINDIRECTION_OUT = 1 +}Enum_PinDirection; + +typedef enum{ + PINLEVEL_LOW = 0, + PINLEVEL_HIGH = 1 +}Enum_PinLevel; + +typedef enum{ + PINPULLSEL_DISABLE = 0, // Disable pull selection + PINPULLSEL_PULLDOWN = 1, // Pull-down + PINPULLSEL_PULLUP = 2 // Pull-up +}Enum_PinPullSel; + + + + +/***************************************************************** +* Function: GM_GpioInit +* +* Description: +* This function enables the GPIO function of the specified pin, +* and initialize the configurations, including direction, +* level and pull selection. +* +* Parameters: +* pinName: +* Pin name, one value of Enum_PinName. +* dir: +* The initial direction of GPIO, one value of Enum_PinDirection. +* level: +* The initial level of GPIO, one value of Enum_PinLevel. +* pullSel: +* Pull selection, one value of Enum_PinPullSel. +* Return: +* GM_RET_OK, this function succeeds. +* GM_RET_ERR_NOSUPPORTPIN, the input GPIO is invalid. +* GM_RET_ERR_PINALREADYSUBCRIBE, the GPIO is in use in +* other place. For example this GPIO has been using as EINT. +*****************************************************************/ +extern s32 GM_GpioInit(Enum_PinName pinName, + Enum_PinDirection dir, + Enum_PinLevel level, + Enum_PinPullSel pullSel + ); + +/***************************************************************** +* Function: GM_GpioSetLevel +* +* Description: +* This function sets the level of the specified GPIO. +* +* Parameters: +* pinName: +* Pin name, one value of Enum_PinName. +* level: +* The initial level of GPIO, one value of Enum_PinLevel. +* Return: +* GM_RET_OK, this function succeeds. +* GM_RET_ERR_NOSUPPORTPIN, the input GPIO is invalid. +* GM_RET_ERR_NORIGHTOPERATE, can't operate,Maybe the GPIO not Init +* GM_RET_ERR_NOGPIOMODE, the input GPIO is not GPIO mode +*****************************************************************/ +extern s32 GM_GpioSetLevel(Enum_PinName pinName, Enum_PinLevel level); + +/***************************************************************** +* Function: GM_GpioGetLevel +* +* Description: +* This function gets the level of the specified GPIO. +* +* Parameters: +* pinName: +* Pin name, one value of Enum_PinName. +* Return: +* The level value of the specified GPIO, which is +* nonnegative integer. +* GM_RET_ERR_NOSUPPORTPIN, the input GPIO is invalid. +*****************************************************************/ +extern s32 GM_GpioGetLevel(Enum_PinName pinName); + + + + + +extern char GM_GetGpioMode(kal_uint16 port); + +/***************************************************************** +* Function: GM_GpioSetDirection +* +* Description: +* This function sets the direction of the specified GPIO. +* +* Parameters: +* pinName: +* Pin name, one value of Enum_PinName. +* dir: +* The initial direction of GPIO, one value of Enum_PinDirection. +* Return: +* GM_RET_OK indicates this function successes. +* GM_RET_ERR_NOSUPPORTPIN, the input GPIO is invalid. +* GM_RET_ERR_NORIGHTOPERATE, can't operate,Maybe the GPIO not Init +* GM_RET_ERR_NOGPIOMODE, the input GPIO is not GPIO mode +*****************************************************************/ +extern s32 GM_GpioSetDirection(Enum_PinName pinName, Enum_PinDirection dir); + +/***************************************************************** +* Function: GM_GpioGetDirection +* +* Description: +* This function gets the direction of the specified GPIO. +* +* Parameters: +* pinName: +* Pin name, one value of Enum_PinName. +* Return: +* The direction of the specified GPIO, which is +* nonnegative integer.. +* GM_RET_ERR_NOSUPPORTPIN, the input GPIO is invalid. +* GM_RET_ERR_NORIGHTOPERATE, can't operate,Maybe the GPIO not Init +* GM_RET_ERR_NOGPIOMODE, the input GPIO is not GPIO mode +*****************************************************************/ +extern s32 GM_GpioGetDirection(Enum_PinName pinName); + +/***************************************************************** +* Function: GM_GpioSetPullSelection +* +* Description: +* This function sets the pull selection of the specified GPIO. +* +* Parameters: +* pinName: +* Pin name, one value of Enum_PinName. +* Enum_PinPullSel: +* Pull selection, one value of Enum_PinPullSel. +* Return: +* GM_RET_OK indicates this function successes. +* GM_RET_ERR_NOSUPPORTPIN, the input GPIO is invalid. +* GM_RET_ERR_NORIGHTOPERATE, can't operate,Maybe the GPIO not Init +* GM_RET_ERR_NOGPIOMODE, the input GPIO is not GPIO mode +*****************************************************************/ +extern s32 GM_GpioSetPullSelection(Enum_PinName pinName, Enum_PinPullSel pullSel); + + + +#endif // __GM_GPIO_H__ + diff --git a/inc/goome_sdk_inc/gm_gprs.h b/inc/goome_sdk_inc/gm_gprs.h new file mode 100644 index 0000000..1a156ba --- /dev/null +++ b/inc/goome_sdk_inc/gm_gprs.h @@ -0,0 +1,155 @@ +/***************************************************************************** +* Copyright Statement: +* -------------------- +* www.goome.net +* +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_gprs.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * GPIO API defines. + * + * Author: + * ------- + * ------- + * + *============================================================================ + * HISTORY + *---------------------------------------------------------------------------- + * + ****************************************************************************/ + + +#ifndef __GM_GPRS_H__ +#define __GM_GPRS_H__ + + +#define MAX_GPRS_USER_NAME_LEN 32 +#define MAX_GPRS_PASSWORD_LEN 32 +#define MAX_GPRS_APN_LEN 100 +#define MAX_GPRS_MESSAGE_LEN 1048576 +#define MAX_GPRS_PART_MESSAGE_TIMEOUT 3 + +#define SW_DNS_REQUEST_ID 0x055A5121 + +typedef struct { + u8 apnName[MAX_GPRS_APN_LEN]; + u8 apnUserId[MAX_GPRS_USER_NAME_LEN]; + u8 apnPasswd[MAX_GPRS_PASSWORD_LEN]; + u8 authtype; // pap or chap + +} ST_GprsConfig; + + + +/* event */ +typedef enum +{ + GM_SOC_READ = 0x01, /* Notify for read */ + GM_SOC_WRITE = 0x02, /* Notify for write */ + GM_SOC_ACCEPT = 0x04, /* Notify for accept */ + GM_SOC_CONNECT = 0x08, /* Notify for connect */ + GM_SOC_CLOSE = 0x10 /* Notify for close */ +} gm_soc_event_enum; + +/* Socket return codes, negative values stand for errors */ +typedef enum +{ + GM_SOC_SUCCESS = 0, /* success */ + GM_SOC_ERROR = -1, /* error */ + GM_SOC_WOULDBLOCK = -2, /* not done yet */ + GM_SOC_LIMIT_RESOURCE = -3, /* limited resource */ + GM_SOC_INVALID_SOCKET = -4, /* invalid socket */ + GM_SOC_INVALID_ACCOUNT = -5, /* invalid account id */ + GM_SOC_NAMETOOLONG = -6, /* address too long */ + GM_SOC_ALREADY = -7, /* operation already in progress */ + GM_SOC_OPNOTSUPP = -8, /* operation not support */ + GM_SOC_CONNABORTED = -9, /* Software caused connection abort */ + GM_SOC_INVAL = -10, /* invalid argument */ + GM_SOC_PIPE = -11, /* broken pipe */ + GM_SOC_NOTCONN = -12, /* socket is not connected */ + GM_SOC_MSGSIZE = -13, /* msg is too long */ + GM_SOC_BEARER_FAIL = -14, /* bearer is broken */ + GM_SOC_CONNRESET = -15, /* TCP half-write close, i.e., FINED */ + GM_SOC_DHCP_ERROR = -16, /* DHCP error */ + GM_SOC_IP_CHANGED = -17, /* IP has changed */ + GM_SOC_ADDRINUSE = -18, /* address already in use */ + GM_SOC_CANCEL_ACT_BEARER = -19, /* cancel the activation of bearer */ + + GM_LOG_LOGIN_FAIL = -115, // Dec-08-2016 登录无应答 5 + GM_LOG_CONFIG_PARAM = -116, // 4 参数配置 4 + GM_LOG_ACK_ERR = -117, // 3 +120 3 + GM_LOG_HEART_ERROR = -118, // 2, + GM_LOG_SIM_DROP = -119, // 1, +} gm_soc_error_enum; + + +typedef struct +{ + kal_uint8 ref_count; + kal_uint16 msg_len; + kal_int8 socket_id; /* socket ID */ + gm_soc_event_enum event_type; /* soc_event_enum */ + kal_bool result; /* notification result. KAL_TRUE: success, KAL_FALSE: error */ + gm_soc_error_enum error_cause; /* used only when EVENT is close/connect */ + kal_int32 detail_cause; /* refer to ps_cause_enum if error_cause is + * SOC_BEARER_FAIL */ +} gm_soc_notify_ind_struct; + + + + + + +extern S32 GM_ApnConfig(ST_GprsConfig* apn, S32 *account_id); +extern s32 GM_GetApnMatch(kal_uint8 *dtcnt); +extern s32 GM_DeleteApn(kal_uint8 *Apn); +extern u8 GM_GetHostByName(const char *hostName, U32 acctId, u8 *result); +extern int GM_SocketCreate(U32 account_id,U8 socType); +extern U32 GM_SocketConnect(S32 request_id, const char *hostName, U16 dstPort,U32 acctId, U32 access_id,U8 socType); +extern S32 GM_SocketRecv (int socketId, const char *buf, S32 len); +extern int GM_SocketClose(int socketId); +extern S32 GM_SocketSend(int socketId, const char *buf, S32 len); +extern s32 GM_SocketRegisterCallBack(PsFuncPtr callback); + +extern u8 GM_GetBearerStatus(s32 *bear_status); +extern s32 GM_AccountIdClose(void); +extern char GM_GetSetFlightMode(char is_set, char *on_off); +extern u8 GM_CloseBearerAppId(u8 is_close_bearer, kal_int8 *result); +extern u8 GM_GetLocalIP(u8 *local_ip); +/***************************************************************** +* Function: GM_ConvertIpAddr +* +* Description: +* This function checks whether an IP address is valid +* IP address or not. If 'yes', each segment of the +* IP address string will be converted into integer to +* store in ipaddr parameter. +* +* Parameters: +* addrString: +* [in] IP address string. +* +* ipaddr: +* [out] Point to a IPv4 address, each byte stores the IP +digit +* converted from the corresponding IP string. +* +* Return: +* If no error occurs, this function returns SOC_SUCCESS (0). +* Otherwise, a value of Enum_SocErrCode is returned. +*****************************************************************/ +extern s32 GM_ConvertIpAddr(u8 *addrString, u8* ipAddr); + + + +#endif diff --git a/inc/goome_sdk_inc/gm_iic.h b/inc/goome_sdk_inc/gm_iic.h new file mode 100644 index 0000000..ca10fd8 --- /dev/null +++ b/inc/goome_sdk_inc/gm_iic.h @@ -0,0 +1,14 @@ + +#ifndef __GM_IIC_H__ +#define __GM_IIC_H__ + +extern s32 GM_I2cSetMode(kal_uint8 i2c_mode); +extern s32 GM_I2cGetMode(void); +extern BOOL GM_I2cReadBytes(u8 RegAddr, u8 *pBuffer, u16 len); +extern BOOL GM_I2cWriteBytes(u8 RegAddr, u8 *pData, u16 len); +extern BOOL GM_I2cWriteByte(kal_uint8 RegAddr, kal_uint8 Data); +extern s32 GM_I2cConfig(u8 slaveAddr, u32 speed); +extern s32 GM_I2cInit(kal_uint8 is_hw, kal_uint8 slaveAddr_R, kal_uint8 slaveAddr_W, kal_uint8 pin_scl, kal_uint8 pin_sda); + +#endif /*__GM_IIC_H__*/ + diff --git a/inc/goome_sdk_inc/gm_memory.h b/inc/goome_sdk_inc/gm_memory.h new file mode 100644 index 0000000..3dae90e --- /dev/null +++ b/inc/goome_sdk_inc/gm_memory.h @@ -0,0 +1,62 @@ +/***************************************************************************** +* +* www.goome.net +* +*****************************************************************************/ + + +#ifndef __GM_MEMORY_H__ +#define __GM_MEMORY_H__ + +#include "gm_type.h" + +extern char goome_memoryInit(void); + +/***************************************************************** +* Function: GM_MemoryAlloc +* +* Description: +* Allocates memory with the specified size in the memory heap. +* Parameters: +* Size: +* [in]Number of bytes of memory to be allocated. +* Return: +* A pointer of void type to the allocated space. +*****************************************************************/ +extern void* GM_MemoryAlloc (u32 size); + + +/***************************************************************** +* Function: GM_MemoryRealloc +* +* Description: +* e-allocate a memory buffer +* Parameters: +* Ptr: +* [in]old memory buffer pointer. +* size: +* [in]request memory size. +* Return: +* re-allocated memory buffer pointer. return NULL if no memory available. +* +*****************************************************************/ +extern void *GM_MemoryRealloc (void *ptr, u32 size); + + +/***************************************************************** +* Function: GM_MemoryFree +* +* Description: +* Free memory +* Parameters: +* Ptr: +* [in]Previously allocated memory block to be freed. +* Return: +* none +* +*****************************************************************/ +extern void GM_MemoryFree (void *ptr); + + +#endif // End of __GM_MEMORY_H__ + diff --git a/inc/goome_sdk_inc/gm_network.h b/inc/goome_sdk_inc/gm_network.h new file mode 100644 index 0000000..985b07a --- /dev/null +++ b/inc/goome_sdk_inc/gm_network.h @@ -0,0 +1,135 @@ +/***************************************************************************** +* Copyright Statement: +* -------------------- +* www.goome.net +* +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_network.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * Timer related APIs + * + * Author: + * ------- + * ------- + * + *============================================================================ + * HISTORY + *---------------------------------------------------------------------------- + * + ****************************************************************************/ + +#ifndef __GM_NETWORK_H__ +#define __GM_NETWORK_H__ + +#include "gm_type.h" + + +typedef enum +{ + GM_ACTIVE_CARD_EMPTY = 0, + GM_ACTIVE_CARD_SIM1, + GM_ACTIVE_CARD_SIM2 +}GM_SIM_ENUM; + + + +typedef struct +{ + U16 mcc; // simCC; 460: 0x1CC 国家代码 + U16 mnc; // simNC; 00: 移动 01: 营运商 + U16 lac; // wLac; 小区编号Lca 区号262C + U16 ci; // wLci 小区ID CellId 塔号 EBA + U16 arfcn; + U8 bsic; + U8 rxlev; +}gm_cell_id_struct; + + +typedef struct +{ + gm_cell_id_struct serv_info; + kal_uint8 ta; + kal_uint8 nbr_cell_num; + gm_cell_id_struct nbr_cell_info[6]; +}gm_cell_info_struct; + + +#define MAX_PLMN_LEN 6 + +typedef struct +{ + kal_uint8 ref_count; + kal_uint16 msg_len; + kal_uint8 status; /* l4c_rac_response_enum */ + kal_uint8 plmn[MAX_PLMN_LEN+1]; + kal_uint8 gsm_state; + kal_uint8 gprs_state; + kal_uint8 gprs_status; /* l4c_gprs_status_enum */ + kal_uint8 rat; + kal_uint8 cell_support_egprs; + kal_uint8 lac[2]; + kal_uint8 rac; + kal_uint16 cell_id; + kal_uint8 cause; + kal_uint8 data_speed_support; + kal_bool is_on_hplmn; + kal_uint8 domain; /* domain_id_enum */ +}mmi_nw_attach_ind_struct; + + + +#ifdef DSFSD +typedef enum +{ + SRV_NW_INFO_SIM_DN_STATUS_NONE = 0x00, /* No coverage */ + SRV_NW_INFO_SIM_DN_STATUS_COVERAGE = 0x01, /* In coverage */ + SRV_NW_INFO_SIM_DN_STATUS_ATTACHED = 0x02, /* Attached */ + SRV_NW_INFO_SIM_DN_STATUS_PDP_ACTIVATED = 0x04, /* PDP activated */ +#ifdef __MMI_NW_INFO_DN_STATUS_ULINK_DLINK_ICONS__ + SRV_NW_INFO_SIM_DN_STATUS_UPLINK = 0x08, /* DN uplink */ + SRV_NW_INFO_SIM_DN_STATUS_DOWNLINK = 0x10, /* DN downlink */ +#endif // __MMI_NW_INFO_DN_STATUS_ULINK_DLINK_ICONS__ + SRV_NW_INFO_SIM_DN_STATUS_END_OF_ENUM +} srv_nw_info_sim_dn_status_enum; +#endif + + +typedef struct +{ + u16 mcc; + u16 mnc; + char apn[30]; + char usrname[30]; + char usrpass[30]; +}goome_auto_apn_struct; + + + +extern GM_SIM_ENUM gm_get_active_card(void); +extern s32 GM_CheckSimValid(void);//查询是否插卡 +extern u8 GM_GetImsi(char *imsi_data); +extern void GM_GetImei(PsFuncPtr funcPtr); +extern void GM_GetPlmn(char *plmn); //查询SIM卡MCCMNC +extern s32 GM_GetServiceAvailability(void); //查询网络是否注册 +extern s32 GM_GetSignalValue (void);/*以整数表示的百分比*/ +extern s32 GM_GetLbsInfo(PsFuncPtr handler_func_ptr); +extern void GM_GetIccid(PsFuncPtr CallBack);//获取ICCID +extern u32 GM_GetPdpStatus(void); // 获取PDP状态 +extern u32 GM_GetGsmStatus(void); // 获取G网连接状态 CREG +extern u32 GM_GetCregStatus(u8 *status); +extern s32 GM_GetBarcode(u8* pdata); +extern kal_uint8 GM_GetFakeCellFeature (kal_bool *feature); +extern s32 GM_AutoApnCheck(goome_auto_apn_struct *Apn); + +#endif + diff --git a/inc/goome_sdk_inc/gm_power.h b/inc/goome_sdk_inc/gm_power.h new file mode 100644 index 0000000..1f71d23 --- /dev/null +++ b/inc/goome_sdk_inc/gm_power.h @@ -0,0 +1,193 @@ + +/***************************************************************************** +* Copyright Statement: +* -------------------- +* www.goome.net +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_power.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * System related APIs + * + * Author: + * ------- + * ------- + * + *============================================================================ + * HISTORY + *---------------------------------------------------------------------------- + * + ****************************************************************************/ + +#ifndef __GM_POWER_H__ +#define __GM_POWER_H__ + + +typedef enum { + LED_LIGHT_LEVEL0 =0 , /* turn off */ + LED_LIGHT_LEVEL1 , + LED_LIGHT_LEVEL2 , + LED_LIGHT_LEVEL3 , + LED_LIGHT_LEVEL4 , + LED_LIGHT_LEVEL5 , + LED_LIGHT_LEVEL_MAX +}gpio_device_led_level_typedef; + + +/* Enum of charger current List */ +typedef enum +{ + PMU_CHARGE_CURRENT_0_00_MA = 0, + PMU_CHARGE_CURRENT_50_00_MA = 5000, + PMU_CHARGE_CURRENT_62_50_MA = 6250, + PMU_CHARGE_CURRENT_70_00_MA = 7000, + PMU_CHARGE_CURRENT_75_00_MA = 7500, + PMU_CHARGE_CURRENT_87_50_MA = 8750, + PMU_CHARGE_CURRENT_99_00_MA = 9900, + PMU_CHARGE_CURRENT_100_00_MA = 10000, + PMU_CHARGE_CURRENT_133_00_MA = 13300, + PMU_CHARGE_CURRENT_150_00_MA = 15000, + PMU_CHARGE_CURRENT_200_00_MA = 20000, + PMU_CHARGE_CURRENT_225_00_MA = 22500, + PMU_CHARGE_CURRENT_250_00_MA = 25000, + PMU_CHARGE_CURRENT_300_00_MA = 30000, + PMU_CHARGE_CURRENT_350_00_MA = 35000, + PMU_CHARGE_CURRENT_366_00_MA = 36600, + PMU_CHARGE_CURRENT_400_00_MA = 40000, + PMU_CHARGE_CURRENT_425_00_MA = 42500, + PMU_CHARGE_CURRENT_433_00_MA = 43300, + PMU_CHARGE_CURRENT_450_00_MA = 45000, + PMU_CHARGE_CURRENT_466_00_MA = 46600, + PMU_CHARGE_CURRENT_500_00_MA = 50000, + PMU_CHARGE_CURRENT_533_00_MA = 53300, + PMU_CHARGE_CURRENT_550_00_MA = 55000, + PMU_CHARGE_CURRENT_600_00_MA = 60000, + PMU_CHARGE_CURRENT_650_00_MA = 65000, + PMU_CHARGE_CURRENT_666_00_MA = 66600, + PMU_CHARGE_CURRENT_700_00_MA = 70000, + PMU_CHARGE_CURRENT_733_00_MA = 73300, + PMU_CHARGE_CURRENT_750_00_MA = 75000, + PMU_CHARGE_CURRENT_800_00_MA = 80000, + PMU_CHARGE_CURRENT_850_00_MA = 85000, + PMU_CHARGE_CURRENT_866_00_MA = 86600, + PMU_CHARGE_CURRENT_900_00_MA = 90000, + PMU_CHARGE_CURRENT_933_00_MA = 93300, + PMU_CHARGE_CURRENT_950_00_MA = 95000, + PMU_CHARGE_CURRENT_1000_00_MA = 100000, + PMU_CHARGE_CURRENT_1066_00_MA = 106600, + PMU_CHARGE_CURRENT_1100_00_MA = 110000, + PMU_CHARGE_CURRENT_1200_00_MA = 120000, + PMU_CHARGE_CURRENT_1300_00_MA = 130000, + PMU_CHARGE_CURRENT_1400_00_MA = 140000, + PMU_CHARGE_CURRENT_1500_00_MA = 150000, + PMU_CHARGE_CURRENT_1600_00_MA = 160000, + PMU_CHARGE_CURRENT_1800_00_MA = 180000, + PMU_CHARGE_CURRENT_2000_00_MA = 200000, + PMU_CHARGE_CURRENT_MAX +}PMU_CHR_CURRENT_ENUM; + + + +typedef enum { + VBAT_UEM_CHR_OUT=0, + VBAT_UEM_CHR_OUT_FIRST=1, + VBAT_UEM_CHR_IN=2, + VBAT_UEM_CHR_IN_FISRT=3 +}VBAT_UEM_CHR_ENUM; + + + + +typedef enum { + CHARGER_PLUG_IN = 0, + CHARGER_PLUG_OUT = 1, + CHARGER_UNINIT = 0xff +}CHARGER_IN_OUT_STATUS; + + +/* Enum of Charger type */ +typedef enum +{ + PW_AC_CHR=0, /* AC CHARGER */ + PW_USB_CHR, /* USB CHARGER */ + PW_AC_NON_STD_CHR, /* NON-STANDARD AC CHARGER */ + PW_USB_CHARGING_HOST_CHR, /* USB CHARGING HOST */ + PW_NO_CHR // Indicate NO charger +}CHR_DET_TYPE_ENUM; + + +typedef enum{ + PWRKEYPWRON = 0, /* power on reason is powerkey */ + CHRPWRON = 1, /* power on reason is charger in */ + RTCPWRON = 2, /* power on reason is rtc alarm */ + CHRPWROFF = 3, /* reserved */ + WDTRESET = 4, /* reserved */ + ABNRESET = 5, /* power on reason is abnormal reboot */ + USBPWRON = 6, /* power on reason is usb cable in */ + USBPWRON_WDT = 7, /* power on reason is usb cable in and abnormal reboot*/ + PRECHRPWRON = 8, /* power on reason is precharger power on*/ + UNKNOWN_PWRON = 0xF9 /* power on reason is unknown*/ +}PW_CTRL_POWER_ON_REASON; + + + + +typedef struct +{ + kal_int32 VBAT; + kal_int32 ICHARGE; + kal_int32 BATTMP; + kal_int32 VCHARGER; + kal_int32 ISense_Offset; + kal_uint8 bat_state; + kal_uint8 pmictrl_state; + kal_uint8 BatType; + kal_uint8 highfull; + VBAT_UEM_CHR_ENUM VBAT_UEM; // state of UEM VBAT measurement + CHARGER_IN_OUT_STATUS chr_plug; //充电插入 + CHR_DET_TYPE_ENUM chr_type; + kal_bool is_chr_valid; + PW_CTRL_POWER_ON_REASON power_on_type; + kal_uint8 reserved; +}gm_chr_status_struct; + + + +extern s32 GM_SystemReboot(void); +extern s32 GM_SystemPowerOff(void); +extern s32 ZG_SleepEnable(void); +extern s32 ZG_SleepDisable(void); +extern s32 GM_IsinkBacklightCtrl(u8 status, kal_uint8 gpio_dev_level); +extern s32 GM_KpledLevelCtrl(u8 status, kal_uint8 gpio_dev_level); +extern s32 GM_GetChrStatus(kal_uint8* chr_status); +extern s32 GM_ChrCurrentConfig(kal_int32 chr_current); +extern s32 GM_ChrCurrentGet(void); +/***************************************************************** +* Function: GM_PowerKeyRegister +* +* Description: +* Register the callback for PWRKEY indication. +* the callback function will be triggered when the power +* KEY pressed down or release. +* +* Parameters: +* callback_pwrKey: +* callback function for PWRKEY indication. +* +* Return: +* GM_RET_OK indicates this function successes. +* GM_RET_ERR_INVALID_PARAMETER, indicates the wrong input parameter. +*****************************************************************/ +extern s32 GM_PowerKeyRegister(PsFuncPtr callback_pwrKey); + + +#endif /*__GM_POWER_H__*/ diff --git a/inc/goome_sdk_inc/gm_record.h b/inc/goome_sdk_inc/gm_record.h new file mode 100644 index 0000000..11b0eac --- /dev/null +++ b/inc/goome_sdk_inc/gm_record.h @@ -0,0 +1,23 @@ + +#ifndef __GM_RECORD_H_ +#define __GM_RECORD_H_ + + +typedef enum +{ + MDI_RECORD_FAIL = 1, + MDI_RECORD_SUCCESS, + MDI_RECORD_TERMINATED, + MDI_RECORD_DISC_FULL, + MDI_RECORD_END_OF_FILE, + MDI_RECORD_NO_SPACE +}record_result_enum; + + +extern s32 GM_StopRecord(void); +extern s32 GM_StartRecord(void *fileName, kal_uint8 quality, kal_uint32 size_limit, kal_uint32 time_limit); +extern s32 GM_RecordRegister(PsFuncPtr record_cb_func); +extern s32 GM_GetRecordIntensity(u32 channel); + +#endif /*__GM_RECORD_H_*/ + diff --git a/inc/goome_sdk_inc/gm_sms.h b/inc/goome_sdk_inc/gm_sms.h new file mode 100644 index 0000000..34b7fd3 --- /dev/null +++ b/inc/goome_sdk_inc/gm_sms.h @@ -0,0 +1,50 @@ +/***************************************************************************** +* Copyright Statement: +* -------------------- +* www.goome.net +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_sms.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * System related APIs + * + * Author: + * ------- + * ------- + * + *============================================================================ + * HISTORY + *---------------------------------------------------------------------------- + * + ****************************************************************************/ + +#ifndef __GM_SMS_H__ +#define __GM_SMS_H__ + +typedef enum +{ + GM_DEFAULT_DCS = 0x00, /* GSM 7-bit */ + GM_8BIT_DCS = 0x04, /* 8-bit */ + GM_UCS2_DCS = 0x08 /* UCS2 */ +} ENUM_SMSAL_DCS; + +typedef struct +{ + char asciiNum[22]; + U8 smstype; + S32 messageLen; + char* content; +} gm_sms_new_msg_struct; + +extern s32 GM_SendSMS(char* pAsciiDstNumber, char * pSMSContent, ENUM_SMSAL_DCS contentDcs, PsFuncPtr callback); + +#endif /*__GM_SMS_H__*/ diff --git a/inc/goome_sdk_inc/gm_spi.h b/inc/goome_sdk_inc/gm_spi.h new file mode 100644 index 0000000..4bd2e1e --- /dev/null +++ b/inc/goome_sdk_inc/gm_spi.h @@ -0,0 +1,42 @@ + +#ifndef GM_SPI_H +#define GM_SPI_H + +#define SPI_CS_PIN 8 /*GPO GPIO_8*/ +#define SPI_CLK_PIN 55 /*GPO GPIO_11*/ +#define SPI_DIN_PIN 3 /*GPO GPIO_3*/ +#define SPI_DOUT_PIN 2 /*GPI GPIO_2*/ + + +/***************************** FLASH API *****************************/ +#define SPI_FLASH_PAGE_SIZE 256 +#define SPI_FLASH_SECTOR_SIZE 4096 //扇区大小4k +#define SPI_RES_FILE_READ_SIZE 4096 + +#define MANAGE_ADDR_USER 0x00 //参数空间 +#define MANAGE_ADDR_MAX_SECTOR 7 // 最大扇区数n*4096 +#define MANAGE_ADDR_PAGE_SIZE 2048 //以1024byte为一单位 + +#define FLASH_CMD_READ_ID 0x9F /* Read identification */ +#define FLASH_CMD_READ 0x03 /* Read from Memory instruction Read Data */ +#define FLASH_CMD_READ_SR 0x05 /* Read Status Register instruction */ + +#define FLASH_CMD_WRITE_EN 0x06 /* Write enable instruction */ +#define FLASH_CMD_PAGE_WRITE 0x02 /* Write to Memory instruction Page Program */ + +#define FLASH_CMD_SECTOR_ERASE 0x20 /*Sector Erase instruction */ +#define FLASH_CMD_BLOCK_ERASE1 0x52 /* Block Erase instruction 32K*/ +#define FLASH_CMD_BLOCK_ERASE2 0xD8 /* Block Erase instruction 64K*/ +#define FLASH_CMD_CHIP_ERASE 0xC7 /* Whole Chip Erase instruction */ + +#define FLASH_OP_TIMEOUT 5000 //500 /* flash operation time out */ +#define FLASH_WIP_FLAG 0x01 /* Write In Progress (WIP) flag */ + + +extern s32 GM_SpiReadData(u8* pBuffer, u32 Addr, u16 Length); +extern s32 GM_SpiWriteData(u8* pBuffer, u32 Addr, u16 Length); +extern u32 GM_SpiFlashReadID(void); +extern s32 GM_SpiPinInit(u8 cs_pin, u8 clk_pin, u8 din_pin, u8 dout_pin, u8 cs_pin_val); + +#endif /*GM_SPI_H*/ + diff --git a/inc/goome_sdk_inc/gm_stdlib.h b/inc/goome_sdk_inc/gm_stdlib.h new file mode 100644 index 0000000..e81f5bc --- /dev/null +++ b/inc/goome_sdk_inc/gm_stdlib.h @@ -0,0 +1,39 @@ +/***************************************************************************** +* +* www.goome.net +* +*****************************************************************************/ + + + +#ifndef __GM_STDLIB_H__ +#define __GM_STDLIB_H__ + +#include "gm_type.h" +#include "stdio.h" + +extern s32 GM_atoi(const char* s); +extern double GM_atof(const char* s); +extern void* GM_memset(void* dest, u8 value, u32 size); +extern void* GM_memcpy(void* dest, const void* src, u32 size); +extern s32 GM_memcmp(const void* dest, const void*src, u32 size); +extern void* GM_memmove(void* dest, const void* src, u32 size); +extern char* GM_strcpy(char* dest, const char* src); +extern char* GM_strncpy(char* dest, const char* src, u32 size); +extern char* GM_strcat(char* s1, const char* s2); +extern char* GM_strncat(char* s1, const char* s2, u32 size); +extern s32 GM_strcmp(const char*s1, const char*s2); +extern s32 GM_strncmp(const char* s1, const char* s2, u32 size); +extern char* GM_strchr(const char* s1, s32 ch); +extern u32 GM_strlen(const char* str); +extern char* GM_strstr(const char* s1, const char* s2); +extern s32 GM_sprintf(char *, const char *, ...); +extern s32 GM_snprintf(char *, u32, const char *, ...); +extern s32 GM_vsprintf(char*, const char*, __va_list); +extern s32 GM_sscanf(const char*, const char*, ...); +extern s32 GM_toupper(s32 c); +extern s32 GM_tolower(s32 c); +extern s32 GM_isdigit(char c); + + +#endif // __GM_STDLIB_H__ diff --git a/inc/goome_sdk_inc/gm_system.h b/inc/goome_sdk_inc/gm_system.h new file mode 100644 index 0000000..eb6010f --- /dev/null +++ b/inc/goome_sdk_inc/gm_system.h @@ -0,0 +1,223 @@ +/***************************************************************************** +* Copyright Statement: +* -------------------- +* www.goome.net +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_system.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * System related APIs + * + * Author: + * ------- + * ------- + * + *============================================================================ + * HISTORY + *---------------------------------------------------------------------------- + * + ****************************************************************************/ + +#ifndef __GM_SYSTEM_H__ +#define __GM_SYSTEM_H__ + +#include "gm_type.h" +#include "gm_gprs.h" + + +#define PROFILE_NUM 16 +#define ARFCN_SECTION_NUM 12 + +#define NVRAM_EF_BAND_INFO_SIZE 6 +#define NVRAM_EF_MM_EQPLMN_LOCIGPRS_SIZE 52 + + +typedef enum +{ + NVRAM_EF_IMEI_IMEISV_LID = 1, + NVRAM_EF_L1_RAMPTABLE_GSM850_LID, + NVRAM_EF_L1_RAMPTABLE_GSM900_LID, + NVRAM_EF_L1_RAMPTABLE_DCS1800_LID, + NVRAM_EF_L1_RAMPTABLE_PCS1900_LID, + NVRAM_EF_PORT_SETTING_LID, + NVRAM_EF_GM_CUSTOMER_PARAM_LID, + NVRAM_EF_RAC_PREFERENCE_LID, //149 + NVRAM_EF_CLASSMARK_RACAP_LID, + NVRAM_EF_BAND_INFO_LID, + NVRAM_EF_MM_EQPLMN_LOCIGPRS_LID, + + NVRAM_MAX +}goome_nvram_lib_enum; + + + +typedef struct +{ + unsigned char point[2][16]; + +} sRAMPAREADATA; + +typedef struct +{ + signed short max_arfcn; + unsigned short mid_level; + unsigned short hi_weight; + unsigned short low_weight; + +} sARFCN_SECTION; + + + +typedef struct +{ + signed long lowest_power; + unsigned short power[16]; + sRAMPAREADATA ramp[ PROFILE_NUM ]; + sARFCN_SECTION arfcn_weight[ ARFCN_SECTION_NUM ]; + unsigned short battery_compensate[3/*volt*/][3/*temp*/]; +} sRAMPDATA; + + + +typedef struct +{ + sRAMPDATA rampData; +}l1cal_rampTable_T; + + + +enum +{ + APP_GET_FUNC_NONE = 0, + + APP_GET_FUNC_MAX +}; + +enum +{ + APP_SET_FUNC_NONE=0, + + APP_SET_FUNC_MAX +}; + + + +typedef struct +{ + u16 type; + u8 len; + u8 data[32]; + PsFuncPtr callback; +}app_set_get_type; + + +/*各类型大小,固定值 + kal_uint8 200 + kal_uint16 100 + kal_uint32 50 + + 由于恢复出厂设置, 会将所有的配置文件删除, 所以需要 + 把设备型号信息放到nvram中 +*/ +typedef struct +{ + kal_uint8 isAgps; + kal_uint8 isServerLock; + kal_uint8 isDoubleSen; + kal_uint8 isBattUpload; + kal_uint8 is90VEnable; + kal_uint8 isRelayEnable; + kal_uint8 isAccEnable; + kal_uint8 isGpsDisable; + kal_uint8 isUart2_9600; + kal_uint8 data_u[191]; + + //目前只有这个字段有用. + kal_uint16 DeviceType; + + kal_uint16 data_u2[99]; + + kal_uint32 data_u4[50]; +} nvram_ef_goome_param_struct, *p_nvram_ef_goome_param_struct; + + + +typedef struct +{ + kal_uint8 band; + kal_uint8 arg1; + kal_uint8 rat_mode; + kal_uint8 preferred_rat; + kal_uint8 umts_prefered_band[2]; + kal_uint8 preference; +} nvram_ef_rac_preference_struct; + +typedef struct +{ + kal_uint8 byte1; + kal_uint8 byte2; + kal_uint8 byte3; + kal_uint8 byte4; + kal_uint16 byte5_byte6; + kal_uint8 byte7; + kal_uint8 byte8; + kal_uint8 byte9; + kal_uint8 byte10; + kal_uint8 byte11; + kal_uint8 byte12; + kal_uint8 byte13; + kal_uint8 byte14; + kal_uint8 byte15; + kal_uint8 byte16; +} nvram_ef_classmark_racap_struct; + + +typedef struct +{ + kal_uint8 raw_data[NVRAM_EF_BAND_INFO_SIZE]; +} nvram_ef_band_info_struct; + + +typedef struct +{ + kal_uint8 raw_data[NVRAM_EF_MM_EQPLMN_LOCIGPRS_SIZE]; +} nvram_ef_mm_eqplmn_locigprs_struct; + + + +extern kal_char* release_verno(void); +extern char* GM_ReleaseVerno(u8* p); +extern char* GM_ReleaseHwVer(void); +extern char* GM_ReleaseBranch(void); +extern char* GM_ReleaseBuild(void); +extern char* GM_BuildDateTime(void); +extern U16 GM_Ucs2ToAsc(char *pOutBuffer, char *pInBuffer); +extern U16 GM_AscToUcs2(char *pOutBuffer, char *pInBuffer); +extern void GM_SysUsdelay(kal_uint32 delay); //uint:us +extern void GM_SysMsdelay(kal_uint32 delay); //uint:ms +extern u32 GM_ImageZiLimit(void); +extern u32 GM_ImageDummyBase(void); +extern s32 GM_IsGprsAutoOn(void); +extern s32 GM_GetTcpStatus(u8* p); +extern s32 GM_GetLibStatus(u8* p); +extern s32 GM_SetUartFunc(u8* p); +extern s32 GM_ReadWriteNvram(U8 is_read, U16 nLID, U16 nRecordId, void *pBuffer, U16 nBufferSize, S32 *result); +extern s32 GM_GetNewAttachStatus(U32 *nw_attach_status); +extern s32 GM_IsWdtPwrOn(char *isWdtPwrOn); +extern s32 GM_DnsParserCallback(PsFuncPtr cb_fun); +extern s32 GM_app_get_func(app_set_get_type* p, u8* out); +extern s32 GM_app_set_func(app_set_get_type* p, u8* out); +extern s32 GM_ReadNvramLid(u16 lib_index); +extern s32 GM_GetChipRID(u8 *pUid); + +#endif // End-of __GM_SYSTEM_H__ + diff --git a/inc/goome_sdk_inc/gm_time.h b/inc/goome_sdk_inc/gm_time.h new file mode 100644 index 0000000..197a08e --- /dev/null +++ b/inc/goome_sdk_inc/gm_time.h @@ -0,0 +1,94 @@ +/***************************************************************************** +* Copyright Statement: +* -------------------- +* www.goome.net +* +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_time.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * Timer related APIs + * + * Author: + * ------- + * ------- + * + *============================================================================ + * HISTORY + *---------------------------------------------------------------------------- + * + ****************************************************************************/ + + + +#ifndef __GM_TIME_H__ +#define __GM_TIME_H__ +#include "gm_type.h" + +typedef struct { + s32 year; + s32 month; + s32 day; + s32 hour; + s32 minute; + s32 second; + s32 dayindex; /* 0=Sunday */ + float timezone; +}ST_Time; + + +/***************************************************************** +* Function: GM_SetLocalTime +* +* Description: +* Set the current local date and time. +* +* Parameters: +* dateTime: +* [in] Point to the ST_Time object +* Return: +* GM_RET_OK indicates this function is executed successesfully. +* GM_RET_ERR_PARAM, indicates the parameter is error. +* +*****************************************************************/ +extern s32 GM_SetLocalTime(ST_Time* dateTime); + +/***************************************************************** +* Function: GM_GetLocalTime +* +* Description: +* Get the current local date and time. +* +* Parameters: +* dateTime: +* [out] Point to the ST_Time object +* Return: +* if succeed,return the current local date and time +* , NULL means get failure. +*****************************************************************/ +extern s32 GM_GetLocalTime(ST_Time* dateTime,float timezone); + +/***************************************************************** +* Function: GM_GetTime +* +* Description: +* Get the UTC time,the time since the Epoch (00:00:00 UTC, January 1, 1970) +* +* Parameters: +* +* +* Return: the UTC time +* +*****************************************************************/ +extern U32 GM_GetTime(void); + +#endif diff --git a/inc/goome_sdk_inc/gm_timer.h b/inc/goome_sdk_inc/gm_timer.h new file mode 100644 index 0000000..b209ed9 --- /dev/null +++ b/inc/goome_sdk_inc/gm_timer.h @@ -0,0 +1,166 @@ +/***************************************************************************** +* Copyright Statement: +* -------------------- +* www.goome.net +* +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_timer.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * Timer related APIs + * + * Author: + * ------- + * ------- + * + *============================================================================ + * HISTORY + *---------------------------------------------------------------------------- + * + ****************************************************************************/ + + +#ifndef __GM_TIMER_H__ +#define __GM_TIMER_H__ + +#include "gm_type.h" + + +typedef enum +{ + GM_TIMER_ID_START = 254, + + GM_TIMER_10MS_MAIN, + + GM_TIMER_1S_MAIN, + + GM_TIMER_DNS_IP_TIM, + + //限定时间收不到数据以不同波特率打开GPS串口定时器ID + GM_TIMER_GPS_CHECK_RECEIVED, + + //限定时间收不到版本号发送查询MTK版本号 + GM_TIMER_GPS_QUERY_MTK_VERSION, + + //限定时间收不到版本号发送查询TD和AT版本号 + GM_TIMER_GPS_QUERY_TD_AT_VERSION, + + //限定时间收不到版本号发送查询TD版本号 + GM_TIMER_GPS_QUERY_TD_VERSION, + + //限定时间收不到版本号发送查询AT版本号 + GM_TIMER_GPS_QUERY_AT_VERSION, + + //限定时间收不到确认发送打开VTG语句 + GM_TIMER_GPS_OPEN_TD_VTG, + + //检查是否定位成功(1分钟不定位,上传LBS) + GM_TIMER_GPS_CHECK_STATE, + + //GSensor主任务定时器(100毫秒) + GM_TIMER_GSENSOR_MAIN_TASK, + + //加速度大于急刹车加速度后检查速度变化 + GM_TIMER_GSENSOR_CHECK_SPEED_AFTER_EMERGENCY_BRAKE, + + //加速度大于急加速加速度后检查速度变化 + GM_TIMER_GSENSOR_CHECK_SPEED_AFTER_RAPID_ACCERATION, + + //加速度大于急转弯加速度后检查角度变化 + GM_TIMER_GSENSOR_CHECK_ANGLE_AFTER_SUDDEN_TURN, + + //加速度大于急转弯加速度后检查角度变化 + GM_TIMER_GSENSOR_CHECK_ACC_AFTER_SHAKE, + + //检查伪基站报警定时器,每20秒一次 + GM_TIMER_GSM_CHECK_FAKE_CELL_ALARM, + + //每秒钟检查一次SIM卡状态 + GM_TIMER_GSM_CHECK_SIMCARD, + + //发现有SIM卡以后等一会去获取SIM卡信息 + GM_TIMER_GSM_GET_SIM_INFO, + + GM_TIMER_SMS_SEND, + + GM_TIMER_CMD_REBOOT, + + GM_TIMER_UPDATE_REBOOT, + + GM_TIMER_HARDWARE_AUTODEFENCE, + + GM_TIMER_HARDWARE_REBOOT, + + GM_TIMER_SELF_CHECK_START, + + GM_TIMER_MAIN_UPLOAD_LOG, + + TIMER_ID_END=GM_TIMER_ID_START + 90 +}GM_TIMER_ID; + + + +#define GM_TICKS_10_MSEC (2) /* 10 msec */ +#define GM_TICKS_50_MSEC (10) /* 50 msec */ +#define GM_TICKS_100_MSEC (21) /* 100 msec */ +#define GM_TICKS_500_MSEC (108) /* 500 msec */ +#define GM_TICKS_1024_MSEC (221) /* 1024 msec */ + +#define GM_TICKS_1_SEC (217) /* 1 sec */ +#define GM_TICKS_2_SEC_2 (433) /* 2 sec */ +#define GM_TICKS_3_SEC (650) /* 3 sec */ +#define GM_TICKS_5_SEC (1083) /* 5 sec */ +#define GM_TICKS_10_SEC (2167) /* 10 sec */ +#define GM_TICKS_30_SEC (6500) /* 30 sec */ +#define GM_TICKS_1_MIN (13000) /* 1 min */ + + + + +#define TIM_GEN_1MS 2 +#define TIM_GEN_10MS 10 // 3 // 10 +#define TIM_GEN_100MS 100 +#define TIM_GEN_1SECOND 1000 +#define TIM_GEN_1_MIN 60000 + + + +typedef struct +{ + kal_uint8 unused; +} *kal_timerid; + + +typedef void (*kal_timer_func_ptr)(void *param_ptr); + +/* +******************************************************* +系统定时器 +要比较小心它的优先级很高,在回调函数运行 +时,其他事件是得不到处理的 +建议只用来做计数用,不做其它用处。 + +系统定器时 216个 tick 为1秒钟 + +封装的函数 +********************************************************* +*/ + +extern s32 ZG_StartKalTimer(U8 timer_id,PsFuncPtr handler_func_ptr,U32 ticks); +extern s32 GM_StopKalTimer(U8 timer_id); +extern s32 GM_StartTimer(U16 timerid, U32 delay, FuncPtr funcPtr); +extern s32 GM_StopTimer(U16 timerid); +extern s32 GM_CreateKalTimer(U8 timer_id); +extern s32 GM_StartKalTimer(U8 timer_id, PsFuncPtr handler_func_ptr, U32 ticks); + +#endif // End-of __GM_TIMER_H__ + diff --git a/inc/goome_sdk_inc/gm_trace.h b/inc/goome_sdk_inc/gm_trace.h new file mode 100644 index 0000000..501ac86 --- /dev/null +++ b/inc/goome_sdk_inc/gm_trace.h @@ -0,0 +1,53 @@ +/***************************************************************************** +* Copyright Statement: +* -------------------- +* www.goome.net +* +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_trace.h + */ + /***************************************************************************** +* Copyright Statement: +* -------------------- +* www.goome.net +* +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_trace.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * Timer related APIs + * + * Author: + * ------- + * ------- + * + *============================================================================ + * HISTORY + *---------------------------------------------------------------------------- + * + ****************************************************************************/ + + +#ifndef __GM_TRACE_H__ +#define __GM_TRACE_H__ + +extern void GM_Trace(const char *fmt, ...); +extern void GM_TRACE(const char *fmt, ...); +extern void GM_SetUartTrace(Enum_SerialPort port,u32 baudrate); +extern void GM_CloseUartTrace(void); + +#endif + diff --git a/inc/goome_sdk_inc/gm_type.h b/inc/goome_sdk_inc/gm_type.h new file mode 100644 index 0000000..ff2281a --- /dev/null +++ b/inc/goome_sdk_inc/gm_type.h @@ -0,0 +1,82 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: common_type_defines.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-02-28 + * Description: 通用数据类型定义 + * Others: + * Function List: + * History: + 1. Date: 2019-02-28 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __COMMON_TYPE_DEFINES_H__ +#define __COMMON_TYPE_DEFINES_H__ + +typedef unsigned char U8,u8; +typedef signed char S8,s8; +typedef unsigned short U16,u16; +typedef signed short S16,s16; +typedef unsigned int U32,u32; +typedef signed int S32,s32; +typedef unsigned long long U64,u64; +typedef long long S64,s64; + +#ifndef NULL +#ifdef __cplusplus +#define NULL (0) +#else +#define NULL ((void *)0) +#endif +#endif +#ifndef null +#define null NULL +#endif + +#ifndef __cplusplus +#ifndef bool +typedef U8 bool; +typedef U8 BOOL; +#define true 1 +#define TRUE 1 +#define false 0 +#define FALSE 0 +#endif +#endif + +typedef unsigned int UINT; +typedef unsigned char kal_uint8; +typedef signed char kal_int8; +typedef char kal_char; +typedef unsigned short kal_wchar; +typedef unsigned short int kal_uint16; +typedef signed short int kal_int16; +typedef unsigned int kal_uint32; +typedef signed int kal_int32; + +typedef U16 module_type; +typedef U16 msg_type; +typedef U16 sap_type; +typedef int MMI_BOOL; + +typedef enum +{ + KAL_FALSE, + KAL_TRUE +} kal_bool; + +typedef void (*FuncPtr) (void); +typedef void (*PsFuncPtr) (void *); + +#define GOOME_APN_MAX_LENGTH 30 +#define GOOME_DNS_MAX_LENTH 50 +#endif + + diff --git a/inc/goome_sdk_inc/gm_uart.h b/inc/goome_sdk_inc/gm_uart.h new file mode 100644 index 0000000..0f052e6 --- /dev/null +++ b/inc/goome_sdk_inc/gm_uart.h @@ -0,0 +1,222 @@ +/***************************************************************************** +* Copyright Statement: +* -------------------- +* This software is protected by Copyright and the information contained +* herein is confidential. The software may not be copied and the information +* contained herein may not be used or disclosed except with the written +* permission of goome Co., Ltd. 2018 +* +*****************************************************************************/ +/***************************************************************************** + * + * Filename: + * --------- + * gm_uart.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * Uart APIs defines. + * + * Author: + * ------- + * ------- + * + *============================================================================ + * HISTORY + *---------------------------------------------------------------------------- + * + ****************************************************************************/ + + +#ifndef __GM_UART_H__ +#define __GM_UART_H__ + + +typedef enum { + UART_PORT1 = 0, // general com + UART_PORT2 = 1, // gps com + UART_PORT3 = 2, // stm8 com + UART_PORT_END = 3 +}Enum_SerialPort; + +typedef enum { + DB_5BIT = 5, + DB_6BIT, + DB_7BIT, + DB_8BIT +} Enum_DataBits; + +typedef enum { + SB_ONE = 1, + SB_TWO, + SB_ONE_DOT_FIVE +} Enum_StopBits; + +typedef enum { + PB_NONE = 0, + PB_ODD, + PB_EVEN, + PB_SPACE, + PB_MARK +} Enum_ParityBits; + +typedef enum { + GM_FC_NONE=1, // None Flow Control + GM_FC_HW, // Hardware Flow Control + GM_SW // Software Flow Control +} Enum_FlowCtrl; + +typedef struct { + u32 baudrate; + Enum_DataBits dataBits; + Enum_StopBits stopBits; + Enum_ParityBits parity; + Enum_FlowCtrl flowCtrl; +}ST_UARTDCB; + + + + +/***************************************************************** +* Function: GM_UartOpen +* +* Description: +* This function opens a specified UART port with the specified +* flow control mode. +* Which task call this function, which task will own the specified UART port. +* +* Parameters: +* [in]port: +* Port name +* [in]baud: +* The baud rate of the UART to be opened +* for the physical the baud rate support 75,150,300,600,1200,2400,4800,7200, +* 9600,14400,19200,28800,38400,57600,115200,230400,460800 +* for the UART_PORT1 support auto-baud rate, when the baud set to 0. +* +* This parameter don't take,effect on the VIRTUAL_PORT1,VIRTUAL_PORT2,just set to 0 +* +* +* Return: +* GM_RET_OK indicates success; otherwise failure. +* +*****************************************************************/ +extern s32 GM_UartOpen(Enum_SerialPort port,u32 baudrate); + + + +/***************************************************************** +* Function: GM_UartWrite +* +* Description: +* This function is used to send data to the specified UART port. +* +* When the number of bytes actually write data is less than that to send, +* Application should stop sending data, and application will receive an event +* EVENT_UART_READY_TO_WRITE later. +* After receiving this Event Application can continue to send data, +* and previously unsent data should be resend. +* +* NOTE: +* The RX/TX buffer size of VIRTUAL_PORT1 and VIRTUAL_PORT2 both are 1024-byte, +* So the number of bytes to write should generally not more than 1024. +* +* Parameters: +* [in] port: +* Port name +* [in]data: +* Pointer to data to be send +* [in]writeLen: +* The length of the data to be written +* +* Return: +* If >= 0, indicates success, and the return value +* is the length of actual write data length +* If < 0, indicates failure to read +* +*****************************************************************/ +extern s32 GM_UartWrite(Enum_SerialPort port, u8* data, u32 writeLen ); + + +/***************************************************************** +* Function: GM_UartRead +* +* Description: +* This function read data from the specified UART port. +* When the UART callback is called, and the message type is +* EVENT_UART_READ_TO_READ, +* user need read all of the data in the data buffer +* which means the real read len is less than the to be read len, +* otherwise later the UART data is coming, there will be no such event to notify user get data. +* +* Parameters: +* [in]port: +* Port name +* [out]data: +* Point to the read data +* [in]readLen: +* then length of data want to read +* +* Return: +* If >= 0, indicates success, and the return value +* is the length of actual read data length +* If < 0, indicates failure to read +* +*****************************************************************/ +extern s32 GM_UartRead(Enum_SerialPort port, u8* data, u32 readLen); + + + +/***************************************************************** +* Function: GM_UartClrRxBuffer +* +* Description: +* This function clears receive-buffer of specified UART port +* +* Parameters: +* [in]port: +* Port name +* +* Return: +* NONE +* +*****************************************************************/ +extern void GM_UartClrRxBuffer(Enum_SerialPort port); + + +/***************************************************************** +* Function: GM_UartClrTxBuffer +* +* Description: +* This function clears send-buffer of specified UART port. +* +* Parameters: +* [in]port: +* Port name +* +* Return: +* NONE +* +*****************************************************************/ +extern void GM_UartClrTxBuffer(Enum_SerialPort port); + + +/***************************************************************** +* Function: GM_UartClose +* +* Description: +* This function close a specified UART port. +* Parameters: +* [in] port: +* Port name +* Return: +* NONE +* +*****************************************************************/ +extern void GM_UartClose(Enum_SerialPort port); + +#endif // End-of __GM_UART_H__ diff --git a/inc/goome_sdk_inc/gm_wdt.h b/inc/goome_sdk_inc/gm_wdt.h new file mode 100644 index 0000000..3b33227 --- /dev/null +++ b/inc/goome_sdk_inc/gm_wdt.h @@ -0,0 +1,36 @@ +/***************************************************************************** + * + * Filename: + * --------- + * gm_wdt.h + * + * Project: + * -------- + * OpenCPU + * + * Description: + * ------------ + * Copyright Statement: + * -------------------- + * www.goome.net + * +*****************************************************************************/ + + +#ifndef __GM_WDT_H__ +#define __GM_WDT_H__ + + +extern void GM_SoftwareWdtCounterEnable(u8 enable); +extern u8 GM_GetSoftwareWdtCounter(void); +extern void GM_SetSoftwareWdtCounter(u8 counter); +extern void GM_SetSwLogicCounterEnable(u8 enable); +extern void GM_SetSwLogicCounter(u32 counter); +extern void GM_SetSwLogicCounterMax(u32 counter); +extern u32 GM_GetSwLogicCounter(void); +extern u32 GM_GetSwLogicCounterMax(void); + +//系统内部默认打开了WDT + +#endif + diff --git a/inc/gprs.h b/inc/gprs.h new file mode 100644 index 0000000..f30fa92 --- /dev/null +++ b/inc/gprs.h @@ -0,0 +1,86 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: gprs.h + * Author: 李耀轩 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. 创建gprs模块 + 2. 销毁gprs模块 + 3. gprs模块定时处理入口 + * History: + 1. Date: 2019-03-01 + Author: 李耀轩 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __GPRS_H__ +#define __GPRS_H__ + +#include "gm_type.h" +#include "error_code.h" + +/** + * Function: 创建gprs模块 + * Description:创建gprs模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE gprs_create(void); + +/** + * Function: 销毁gprs模块 + * Description:销毁gprs模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gprs_destroy(void); + +/** + * Function: gprs模块定时处理入口 + * Description:gprs模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 1秒钟调用1次 + */ +GM_ERRCODE gprs_timer_proc(void); + +/** + * Function: 判断GPRS是否正常 + * Description: + * Input: 无 + * Output: 无 + * Return: true——正常;false——不正常 + * Others: + */ +bool gprs_is_ok(void); + + +/** + * Function: 判断是否需要重启 + * Description: + * Input: 无 + * Output: 无 + * Return: true——重启;false——不重启 + * Others: + */ +bool gprs_check_need_reboot(u32 check_time); + +u32 gprs_get_last_good_time(void); +u32 gprs_get_call_ok_count(void); + +#endif + + + diff --git a/inc/gps.h b/inc/gps.h new file mode 100644 index 0000000..ff2349d --- /dev/null +++ b/inc/gps.h @@ -0,0 +1,319 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: gps.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-01 + * Description: 流程实现参考《GPS流程图.vsd》 + * Others: + * Function List: + 1. 创建gps模块 + 2. 销毁gps模块 + 3. 模块定时处理入口 + 4. 打开GPS模块 + 5. 关闭GPS模块 + 6. 获取最新GPS数据 + * History: + 1. Date: 2019-03-01 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __GPS_H__ +#define __GPS_H__ + +#include +#include "gm_type.h" +#include +#include "error_code.h" + +//GPSState的第0位表示是否差分定位定位,0——非差分定位;1——差分定位 +//GPSState的第1位表示2D/3D定位,0——2D;1——3D +//GPSState的第2位表示是否定位定位,0——未定位;1——已定位 + +typedef enum +{ GM_GPS_OFF = 0xF0, //关闭11110000 + GM_GPS_FIX_NONE = 0, //未定位00000000 + GM_GPS_FIX_2D = 4, //2D定位00000100 + GM_GPS_FIX_2D_DIFF = 5, //2D差分定位00000101 + GM_GPS_FIX_3D = 6, //3D定位00000110 + GM_GPS_FIX_3D_DIFF = 7, //3D差分定位00000111 +}GPSState; + +typedef enum +{ + //型号未知 + GM_GPS_TYPE_UNKNOWN = 0, + + //2503D芯片内置GPS模块 + GM_GPS_TYPE_MTK_EPO = 1, + + //外接泰斗GPS模块 + GM_GPS_TYPE_TD_AGPS = 2, + + //外接中科微GPS模块 + GM_GPS_TYPE_AT_AGPS = 3, +}GPSChipType; + +typedef struct +{ + //卫星编号 + u8 prn; + //信噪比 + u8 snr; +}SNRInfo; + +#define SNR_INFO_NUM 5 + + + +typedef struct +{ + //GPS时间(UTC时间) + time_t gps_time; + + //纬度 + float lat; + + //经度 + float lng; + + //高度(单位米) + float alt; + + //速度(公里/小时) + float speed; + + //航向:表示范围:000—359度,正北为0度,顺时针方向 + float course; + + //信号强度等级[0,100],数值越大信号越强 + U8 signal_intensity_grade; + + //定位精度[0.5,99.9],数值越小精度越高 + float precision; + + //跟踪到的卫星个数 + U8 satellites; +}GPSData; + + +/** + * Function: 创建gps模块 + * Description:创建gps模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE gps_create(void); + +/** + * Function: 销毁gps模块 + * Description:销毁gps模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_destroy(void); + +/** + * Function: gps模块定时处理入口 + * Description:gps模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 1秒钟调用1次 + */ +GM_ERRCODE gps_timer_proc(void); + +/** + * Function: 唤醒 + * Description: + * Input: push_data_enbale:是否推送数据到服务模块 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_power_on(bool push_data_enbale); + +/** + * Function: 写入参考定位和时间 + * Description: + * Input: lng:经度;lat:纬度;utc_time:当前时间;leap_sencond:闰秒,泰斗AGPS直接从AGPS文件中读出,中科微的从AGPS服务器获取 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 状态>=GM_GPS_STATE_INITED时可以写入 + */ +GM_ERRCODE gps_write_agps_info(const float lng,const float lat,const U8 leap_sencond); + +/** + * Function: 写入agps(epo)数据 + * Description: + * Input: seg_index:分片ID;p_data:数据指针;len:数据长度 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 状态>=GM_GPS_STATE_REF_TIME_OK时可以写入 + */ +GM_ERRCODE gps_write_agps_data(const U16 seg_index, const U8* p_data, const U16 len); + +/** + * Function: 收到串口数据 + * Description: + * Input: p_data:数据指针;len数据长度 + * Output: 无 + * Return: 无 + * Others: 内存无须释放 + */ +void gps_on_rcv_uart_data(char* p_data, const U16 len); + +/** + * Function: 休眠 + * Description: + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_power_off(void); + +/** + * Function: 获取GPS模块状态 + * Description: + * Input: 无 + * Output: 无 + * Return: FixState + * Others: + */ +GPSState gps_get_state(void); + +/** + * Function: 是否已定位 + * Description: + * Input: 无 + * Output: 无 + * Return: true——已定位;false——未定位 + * Others: + */ +bool gps_is_fixed(void); + + +/** + * Function: 获取GPS定位时间 + * Description: + * Input: 无 + * Output: 无 + * Return: 定位时间 + * Others: + */ +U16 gps_get_fix_time(void); + +/** + * Function: 获取最大信噪比 + * Description: + * Input: 无 + * Output: 无 + * Return: 最大信噪比 + * Others: + */ +U8 gps_get_max_snr(void); + +/** + * Function: 获取跟踪卫星数 + * Description: + * Input: 无 + * Output: 无 + * Return: 跟踪卫星数 + * Others: + */ +U8 gps_get_satellites_tracked(void); + +/** + * Function: 获取可见卫星数(1秒更新一次) + * Description: + * Input: 无 + * Output: 无 + * Return: 可见卫星数 + * Others: + */ +U8 gps_get_satellites_inview(void); + +/** + * Function: 获取信号好的卫星数(SNR>35) + * Description: + * Input: 无 + * Output: 无 + * Return: 可见卫星数 + * Others: + */ +U8 gps_get_satellites_good(void); + + + /** + * Function: 获取最好的5颗星的信噪比 + * Description: + * Input: 无 + * Output: 无 + * Return: 数组首地址 + * Others: + */ + const SNRInfo* gps_get_snr_array(void); + + +/** + * Function: 获取最新GPS数据 + * Description: + * Input: 无 + * Output: p_data:指向定位数据的指针 + * Return: true——成功;false——失败 + * Others: + */ +bool gps_get_last_data(GPSData* p_data); + +/** + * Function: 获取最近n秒的GPS数据 + * Description: + * Input: seconds:第几秒,从0开始 + * Output: p_data:指向定位数据的指针 + * Return: true——成功;false——失败 + * Others: + */ +bool gps_get_last_n_senconds_data(U8 seconds,GPSData* p_data); + + +/** + * Function: 获取匀速行驶时间 + * Description: + * Input: 无 + * Output: 无 + * Return: 匀速行驶时间(秒) + * Others: + */ +U32 gps_get_constant_speed_time(void); + +/** + * Function: 获取行驶加速度 + * Description: + * Input: 无 + * Output: 无 + * Return: 行驶加速度(g) + * Others: + */ +float gps_get_aclr(void); + +/** + * Function: MTK GPS芯片写命令 + * Description: + * Input: cmd:命令(不包含校验部分) + * Output: 无 + * Return: 无 + * Others: + */ +void gps_write_mtk_cmd(const char* cmd); +#endif + diff --git a/inc/gps_save.h b/inc/gps_save.h new file mode 100644 index 0000000..c69174c --- /dev/null +++ b/inc/gps_save.h @@ -0,0 +1,109 @@ +#ifndef __GPS_SAVE_H__ +#define __GPS_SAVE_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "socket.h" + +typedef struct +{ + u8 *buf; + u8 len; +}LocationSaveData; + +/*它是个双头stack, 两头都可以pop(以保证写入历史文件时顺序写), 一头可以push*/ +typedef struct +{ + LocationSaveData *his; + u16 size; /*总空间*/ + u16 read_idx; /*当前读到哪一条, read==write 表示队列空*/ + u16 write_idx; /*当前写到哪一条, 新消息往write处写*/ +}LocationCurData; + + +#define GOOME_HIS_FILE L"Z:\\goome\\GmHisFile\0" +#define HIS_FILE_OFFSET_CNT 16 //头部几个字节不写 +#define HIS_FILE_HEAD_FLAG 0xABCDDCBA +#define HIS_FILE_FRAME_SIZE 100 //保存的文件时 , 第一字节是长度, 所以数据最长不超过(HIS_FILE_FRAME_SIZE-1) +#define SAVE_HIS_MAX_NUM 720 +#define SAVE_CATCH_MAX_NUM 10 + + +/** + * Function: 数据插入缓存中 + * Description:缓存满失败 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_service_save_to_cache(u8 *data, u8 len); + + +/** + * Function: 根据len决定数据是否从缓存中删除 + * Description: + * Input: ack_place: socket ack. + * Output: *from: which place to onfirm again. + * Return: GM_SUCCESS——删除;其它错误码——未改变 + * Others: + */ +void gps_service_confirm_cache(u32 *from, u32 ack_place); + + +/** + * Function: 数据插入stack缓存中 + * Description:缓存满会自动写文件,并重新插入 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_service_push_to_stack(u8 *data, u8 len); + +/** + * Function: 只看不删除数据,方便发送失败时, 重新发送 + * Description: + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_service_peek_one(LocationSaveData *one, bool from_head); + + +/** + * Function: 与gps_service_peek_one配合, 删除一条已peek过的数据 + * Description: + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_service_commit_peek(bool from_head); + + + +/** + * Function: 删除历史数据文件 + * Description: + * Input: 无 + * Output: 无 + * Return: 无 + * Others: + */ +void gps_service_his_file_delete(void); + + +/** + * Function: 历史数据存入文件,防止丢失 + * Description: + * Input: 无 + * Output: 无 + * Return: 无 + * Others: + */ +void gps_service_save_to_history_file(void); + + +#endif diff --git a/inc/gps_service.h b/inc/gps_service.h new file mode 100644 index 0000000..8f12e34 --- /dev/null +++ b/inc/gps_service.h @@ -0,0 +1,259 @@ +#ifndef __GPS_SERVICE_H__ +#define __GPS_SERVICE_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "socket.h" +#include "gps.h" +#include "gps_save.h" + + +#define GPS_LOGIN_MSG_FAIL_MAX 1 +#define GPS_HEART_MSG_RECEIVE_TIME_OUT 420 + + +/** + * Function: 创建gps_service模块 + * Description:创建gps_service模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE gps_service_create(bool first_create); + +/** + * Function: + * Description: 配置变化,重启gps_service模块 + 在断连服务器, 重建连接时,会使用新信息 + * Input: 无 + * Output: 无 + * Return: 无 + * Others: + */ +GM_ERRCODE gps_service_change_config(void); + + +/** + * Function: 销毁gps_service模块 + * Description:销毁gps_service模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_service_destroy(void); + + +/** + * Function: gps_service模块定时处理入口 + * Description:gps_service模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 1秒钟调用1次 + */ +GM_ERRCODE gps_service_timer_proc(void); + + + + +//状态处理辅助函数 +void gps_service_connection_ok(void); +void gps_service_connection_failed(void); +void gps_service_close_for_reconnect(void); + +/* + 给config_service用于判断 +*/ +u8 gps_service_socket_is_same(void); + +void gps_service_after_register_response(void); +void gps_service_after_login_response(void); +void gps_service_after_receive_heartbeat(void); +void gps_service_after_receive_remote_msg(u8 *pRet, u16 len); +void gps_service_after_server_req(void); +void gps_service_after_param_get(void); +void gps_service_after_server_locate_req(void); + + +//GPS数据点上报类型 +typedef enum +{ + GPS_MODE_NONE = -1, // 不上传 + GPS_MODE_FIX_TIME = 0, // 定时上传 + GPS_MODE_FIX_DISTANCE = 1, // 定距上传(终端未做) + GPS_MODE_TURN_POINT = 2, // 拐点上传 + GPS_MODE_STATUS_CHANGE = 3, // ACC状态改变上传 + GPS_MODE_STATIC_POSITION = 4, // 静止最后位置上传 + GPS_MODE_POWER_UP = 5 // 上电登录成功后直接上传 +}GpsDataModeEnum; + +/** + * Function: after gps module generate gps data. it push to gps_service module + * Description: + * Input: GPSData,如果是NULL则表示定位失败需要上报LBS + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_service_push_gps(GpsDataModeEnum mode, const GPSData *p_gps_data); + +/** + * Function: ACC等状态发生变化后,立即触发一次心跳 + * Description: + * Input: 无 + * Output: 无 + * Return: 无 + * Others: + */ +void gps_service_heart_atonce(void); + + +/** + * Function: 获取心跳成功次数 + * Description: + * Input: 无 + * Output: 无 + * Return: 心跳成功次数 + * Others: + */ +U32 gps_service_get_heart_counts(void); + +/** + * Function: 获取心跳成功次数 + * Description: + * Input: 无 + * Output: 无 + * Return: 心跳成功次数 + * Others: + */ +U32 gps_service_get_location_counts(void); + +/** + * Function: + * Description: jt808使用gps定位包代替心跳 + * Input: mode + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_service_send_one_locate(GpsDataModeEnum mode, bool use_lbs); + + +/** + * Function: 收到指令时, 触发上报基站信息, + 开机超时未定位, 触发上报基站信息, + 未开启gps定位时, 定时上报lbs数据 + * Description: + * Input: force: true表示未开启lbs上报的情况下也要发送 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_service_push_lbs(void); + +typedef enum +{ + ALARM_NONE = 0, + ALARM_POWER_OFF = 0x01, //电源断电报警, + ALARM_BATTERY_LOW = 0x03, //电池低电报警 + ALARM_SHOCK = 0x04, //震动报警 + ALARM_MOVE = 0x05, //车辆移动报警(使用原位移报警位) + ALARM_SPEED = 0x0d, //超速报警 + ALARM_FAKE_CELL = 0x0f, //伪基站报警 + ALARM_POWER_HIGH = 0x11, //电源电压过高报警 + ALARM_COLLISION = 0x12, //碰撞报警 + ALARM_SPEED_UP = 0x13, //急加速报警 + ALARM_SPEED_DOWN = 0x14, //急减速报警 + ALARM_TURN_OVER = 0x15, //翻转报警 + ALARM_SHARP_TURN = 0x16, //急转弯报警 + ALARM_REMOVE = 0x17, //拆动报警 + ALARM_MAX +}AlarmTypeEnum; + +typedef struct +{ + AlarmTypeEnum type; + u16 info; +}AlarmInfo; + + +/** + * Function: 发送报警数据 + * Description: + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_service_push_alarm(AlarmInfo *alarm); + + +/** + * Function: 发送地址请求 + * Description: + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_service_push_position_request(u8 *mobile_num, u8 num_len, u8 *command, u8 cmd_len); + + +/** + * Function: 关闭gprs连接, 如果正在升级就只关闭gps连接 + * Description:升级完毕后仍然会关闭gprs连接 + * Input: 无 + * Output: 无 + * Return: 无 + * Others: + */ +void gps_service_destroy_gprs(void); + +/** + * Function: 查询是否登录成功 + * Description: + * Input: 无 + * Output: 无 + * Return: true——成功;false——没有成功 + * Others: + */ +bool gps_service_is_login_ok(void); + + +/** + * Function: 先放到cache中以防丢失,再发送。 + * Description: + * Input: data:待发数据 len:待发数据长度 + * Output: 无 + * Return: 无 + * Others: + */ +GM_ERRCODE gps_service_cache_send(u8 *data, u8 len); + + +/** + * Function: 根据socket ack决定数据是否从缓存中删除 + * Description: + * Input: 无 + * Output: 无 + * Return: 无 + * Others: + */ +void gps_service_confirm_gps_cache(SocketType *socket); + +/** + * Function: 获取当前正在使用的IP地址 + * Description: + * Input: 无 + * Output: 无 + * Return: IP地址首地址 + * Others: + */ +U8* gps_service_get_current_ip(void); + + +#endif + + diff --git a/inc/gsm.h b/inc/gsm.h new file mode 100644 index 0000000..b5f7498 --- /dev/null +++ b/inc/gsm.h @@ -0,0 +1,138 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: gsm.h + * Author: 李耀轩 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. 创建gsm模块 + 2. 销毁gsm模块 + 3. gsm模块定时处理入口 + * History: + 1. Date: 2019-03-01 + Author: 李耀轩 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __GSM_H__ +#define __GSM_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "gm_network.h" + +#define GM_IMEI_LEN 15 +#define GM_IMSI_LEN 15 +#define GM_IMEI_HEX_LEN 10 +#define GM_ICCID_LEN 20 + + +typedef enum +{ + FAKE_CELL_NORMAL = 0, + FAKE_CELL_VIEW = 1, + FAKE_CELL_ALARM = 2, +}GsmFakeCellState; + + +typedef enum +{ + GSM_CREG_UNREGISTER = 0, //未注册,终端当前并未搜寻新的运营商 + GSM_CREG_REGISTER_LOCAL = 1, //已注册本地网络 + GSM_CREG_REGISTERING = 2, //未注册,终端正在搜寻基站 + GSM_CREG_REGISTER_UNKNOW = 4, //未知代码(SIM卡无效) + GSM_CREG_REGISTER_ROAM = 5, //已注册,处于漫游状态 +}GsmRegState; + +/** + * Function: 创建gsm模块 + * Description:创建gsm模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE gsm_create(void); + +/** + * Function: 销毁gsm模块 + * Description:销毁gsm模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gsm_destroy(void); + +/** + * Function: 获取SIM卡ICCID值 + * Description:获取SIM卡ICCID值 + * Input: 无 + * Output: SIM卡ICCID,以'\0'结束 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gsm_get_iccid(U8* p_iccid); + + +/** + * Function: 获取SIM卡IMSI值 + * Description:获取SIM卡IMSI值 + * Input: 无 + * Output: SIM卡IMSI号,以'\0'结束 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gsm_get_imsi(U8* p_imsi); + +/** + * Function: 获取IMEI号 + * Description:获取IMEI号 + * Input: 无 + * Output: IMEI号,以'\0'结束 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gsm_get_imei(U8* p_imei); + +/** + * Function: 设置IMEI号 + * Description:设置IMEI号 + * Input: 无 + * Output: IMEI号,以'\0'结束 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gsm_set_imei(U8* p_imei); + +/** + * Function: 获取CSQ信号值 + * Description:获取CSQ信号值 + * Input: 无 + * Output: 无 + * Return: 信号强度[0,31] + * Others: + */ +U8 gsm_get_csq(void); + + +/** + * Function: 获取基站信息 + * Description:获取基站信息 + * Input: 无 + * Output: 基站信息 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gsm_get_cell_info(gm_cell_info_struct* p_cell_info); + +#endif + + + diff --git a/inc/hard_ware.h b/inc/hard_ware.h new file mode 100644 index 0000000..1aaf139 --- /dev/null +++ b/inc/hard_ware.h @@ -0,0 +1,289 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: hard_ware.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-01 + * Description: 简单硬件(开关)读写操作封装、电源管理、电池充电管理 + * Others: 需要永久存储的状态,放到system_state模块 + * Function List: + 1. 创建hard_ware模块 + 2. 销毁hard_ware模块 + 3. 定时处理入口 + 4. 获取ACC输入状态 + 5. 设置GPS LED状态 + 6. 设置GSM LED状态 + 7. 设置断油电IO状态 + 8. 设置看门狗电平 + 9. 获取供电电源电压值 + 10.获取外部电池电量百分比 + 11.重启系统 + 12.休眠 + 13.唤醒 + + * History: + 1. Date: 2019-03-01 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __HARD_WARE_H__ +#define __HARD_WARE_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "system_state.h" + +typedef enum +{ + VOLT_NONE = 0, + VOLT_12V = 1, + VOLT_24V = 2, + VOLT_36V = 3, + VOLT_48V = 4, + VOLT_60V = 6, + VOLT_72V = 7, + VOLT_84V = 8, + VOLT_96V = 9, + + VOLT_MAX +}GM_POWER_VOLTAGE_GRADE; + + +/** + * Function: 1.创建hard_ware模块 + * Description:创建hard_ware模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE hard_ware_create(void); + +/** + * Function: 2.销毁hard_ware模块 + * Description:销毁hard_ware模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_destroy(void); + +/** + * Function: 3.hard_ware模块定时处理入口 + * Description:hard_ware模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 1秒调用1次 + */ +GM_ERRCODE hard_ware_timer_proc(void); + +/** + * Function: 4.1 获取ACC输入状态 + * Description: + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_get_acc_level(bool* p_state); + +/** + * Function: 4.2 获取ACC线状态 + * Description:震动报警时使用 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_get_acc_line_level(bool* p_state); + + +/** + * Function: 5. 设置GPS LED状态 + * Description:只提供给led模块使用,其它模块不要直接使用这个接口 + * Input: is_on:true——亮灯;false——灭灯 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_set_gps_led(bool is_on); + +/** + * Function: 6. 设置GSM LED状态 + * Description:只提供给led模块使用,其它模块不要直接使用这个接口 + * Input: is_on:true——亮灯;false——灭灯 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_set_gsm_led(bool is_on); + +/** + * Function: 7. 设置断油电IO状态 + * Description: + * Input: state:true——断油电;false——恢复油电 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_set_relay(bool state); + +/** + * Function: 8. 设置看门狗电平 + * Description: + * Input: state:true——高电平;false——低电平 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_set_watchdog(bool state); + + +/** + * Function: 9. 获取供电电源电压值 + * Description:单位伏特(v) + * Input: 无 + * Output: p_voltage:电压值指针 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_get_power_voltage(float* p_voltage); + +/** + * Function: 获取内部电池电量级别 + * Description: 0:无电(关机) <=3.45V + 1:电量极低(不足以打电话发短信等) 3.45V --- 3.5V + 2:点亮很低(低电报警) <=3.6V + 3:电量低(可正常使用) <=3.8V + 4:电量中 <=3.95V + 5:电量高 <=4.1V + 6:电量极高 >4.1V + * Input: 无 + * Output: p_level:电量级别指针 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_get_internal_battery_voltage(float* p_voltage); + +/** + * Function: 是否在充电 + * Description: + * Input: 无 + * Output: 无 + * Return: true——在充电;false——不在充电 + * Others: + */ +bool hard_ware_battery_is_charging(void); + + +/** + * Function: 是否已充满 + * Description: + * Input: 无 + * Output: 无 + * Return: true——充满;false——未充满 + * Others: + */ +bool hard_ware_battery_is_full(void); + +/** + * Function: 10.获取外部电池电量百分比 + * Description:单位伏特(v) + * Input: 无 + * Output: p_percent:百分比指针 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_get_extern_battery_percent(U8* p_percent); + +/** + * Function: 10.获取内部电池电量百分比 + * Description:单位伏特(v) + * Input: 无 + * Output: p_percent:百分比指针 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_get_internal_battery_percent(U8* p_percent); + +/** + * Function: 获取内部电池电量级别 + * Description: 0:无电(关机) <=3.45V + 1:电量极低(不足以打电话发短信等) 3.45V --- 3.5V + 2:点亮很低(低电报警) <=3.6V + 3:电量低(可正常使用) <=3.8V + 4:电量中 <=3.95V + 5:电量高 <=4.1V + 6:电量极高 >4.1V + * Input: 无 + * Output: p_level:电量级别指针 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_get_internal_battery_level(U8* p_level); + + +/** + * Function: 11.重启 + * Description:重启整个系统软件 + * Input: reason:重启原因;delay_seconds:延迟秒数 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_reboot(const BootReason reason,U16 delay_seconds); + +/** + * Function: 12.休眠 + * Description:使系统休眠 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_sleep(void); + +/** + * Function: 13.关闭GPS + * Description:使系统休眠 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_close_gps(void); + + +/** + * Function: 14.唤醒 + * Description:使系统唤醒 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_awake(void); + +/** + * Function: 15.打开GPS + * Description:使系统休眠 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_open_gps(void); + + + +#endif + + + diff --git a/inc/json.h b/inc/json.h new file mode 100644 index 0000000..c81947c --- /dev/null +++ b/inc/json.h @@ -0,0 +1,110 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: log_service.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-05-21 + * Description: 来自于cJSON,删除了大部分不用的功能和特性,print函数完全重写 + * Others: + * Function List: + 1. 创建对象 + 2. 添加数字 + 3. 添加字符串 + 4. 打印到字符串 + 5. 释放内存 + * History: + 1. Date: 2019-03-01 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + + +#ifndef __JSON_H__ +#define __JSON_H__ + +typedef enum +{ + JSON_OBJECT = 0, + JSON_INT, + JSON_DOUBLE, + JSON_STRING, +}JsonDataType; + +typedef struct +{ + struct JsonObject* next; + struct JsonObject* prev; + struct JsonObject* child; + char* name; + JsonDataType type; + S32 int_value; + char* str_value; + double double_value; +}JsonObject; + +/** + * Function: 创建json对象 + * Description:无 + * Input: 无 + * Output: 无 + * Return: 指向对象的指针 + * Others: + */ +JsonObject* json_create(void); + +/** + * Function: 销毁json对象 + * Description:使用完以后必须销毁,否则内存泄露 + * Input: p_object:指向对象的指针 + * Output: 无 + * Return: 无 + * Others: + */ +void json_destroy(JsonObject* p_object); + +/** + * Function: 在json对象中添加一个整数 + * Description: + * Input: p_object:指向对象的指针;name:名称;value:值 + * Output: 无 + * Return: 无 + * Others: + */ +JsonObject* json_add_int(JsonObject* p_object, const char* name, const int value); + +/** + * Function: 在json对象中添加一个double数值 + * Description:float类型也用这个函数 + * Input: p_object:指向对象的指针;name:名称;value:值 + * Output: 无 + * Return: 无 + * Others: + */ +JsonObject* json_add_double(JsonObject* p_object, const char* name, const double value); + +/** + * Function: 在json对象中添加一个字符串 + * Description:对象内部会申请新的内存存储字符串,在销毁对象时释放 + * Input: p_object:指向对象的指针;name:名称;value:值 + * Output: 无 + * Return: 无 + * Others: + */ +JsonObject* json_add_string(JsonObject* p_object, const char* name, const char* string); + +/** + * Function: 把json对象转成字符串打印到缓存 + * Description: + * Input: p_object:指向对象的指针;buffer:缓存;length:缓存长度 + * Output: 无 + * Return: 无 + * Others: + */ +bool json_print_to_buffer(JsonObject* object, char* buffer, const int length); + +#endif + diff --git a/inc/led.h b/inc/led.h new file mode 100644 index 0000000..f438620 --- /dev/null +++ b/inc/led.h @@ -0,0 +1,93 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: led.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-04-08 + * Description: 封装LED接口 + * Others: 提供GSM、GPS指示灯常亮、灭、闪烁等功能 + * Function List: + 1. 创建led模块 + 2. 销毁led模块 + 3. 定时处理入口 + 4. + + * History: + 1. Date: 2019-04-08 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __LED_H__ +#define __LED_H__ + +#include "gm_type.h" +#include "error_code.h" + + +typedef enum +{ + GM_LED_OFF = 0, //灭 + GM_LED_ON = 1, //亮 + GM_LED_FLASH = 2, //闪烁 +}LedState; + + +/** + * Function: 创建hard_ware模块 + * Description:创建hard_ware模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE led_create(void); + +/** + * Function: 销毁hard_ware模块 + * Description:销毁hard_ware模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE led_destroy(void); + +/** + * Function: hard_ware模块定时处理入口 + * Description:hard_ware模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 100毫秒调用1次 + */ +void led_timer_proc(void); + +/** + * Function: 设置GPS LED状态 + * Description: + * Input: state:状态 + * Output: 无 + * Return: 无 + * Others: + */ +void led_set_gps_state(LedState state); + +/** + * Function: 设置GSM LED状态 + * Description: + * Input: state:状态 + * Output: 无 + * Return: 无 + * Others: + */ +void led_set_gsm_state(LedState state); + +#endif + + + diff --git a/inc/log_service.h b/inc/log_service.h new file mode 100644 index 0000000..05fff01 --- /dev/null +++ b/inc/log_service.h @@ -0,0 +1,163 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: log_service.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. 创建log_service模块 + 2. 销毁log_service模块 + 3. log_service模块定时处理入口 + 4. 打印日志到串口 + 5. 上传日志到日志后台 + * History: + 1. Date: 2019-03-01 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __LOG_SERVICE_H__ +#define __LOG_SERVICE_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "json.h" +#include "socket.h" +#include "stdio.h" + +#define LOG_BUFFER_NUM 100 + +typedef enum +{ + DEBUG = 0, + INFO = 1, + WARN = 2, + ERROR = 3, + FATAL= 4 +}LogLevel; + +#define LOG log_service_print +#define LOG_HEX log_service_print_hex +#define LOG_TEST log_service_print_test + + +#define TRACE log_service_print(DEBUG, "%s(%d):%s()", __FILE__, __LINE__,__FUNCTION__); + +/** + * Function: 创建log_service模块 + * Description:创建log_service模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE log_service_create(void); + +/** + * Function: 销毁log_service模块 + * Description:销毁log_service模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE log_service_destroy(void); + +/** + * Function: log_service模块定时处理入口 + * Description:log_service模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE log_service_timer_proc(void); + +/** + * Function: 设置日志级别 + * Description: + * Input: log_level:日志级别 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void log_service_set_level(LogLevel log_level, LogLevel upload_level); + +/** + * Function: 获取日志级别 + * Description: + * Input: 无 + * Output: 无 + * Return: log_level:日志级别 + * Others: 无 + */ +void log_service_get_level(LogLevel *log_level, LogLevel *upload_level); + +/** + * Function: 设置日志开关 + * Description: + * Input: enable:true——打开;false——关闭 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void log_service_enable_print(bool enable); + + + +/*由socket层回调*/ +void log_service_connection_failed(void); +void log_service_connection_ok(void); +void log_service_close_for_reconnect(void); + + +/** + * Function: 打印日志到串口 + * Description: + * Input: level:日志界别;format:格式化字符串;...:可变参数 + * Output: 无 + * Return: 无 + * Others: 1秒钟处理一次 + */ +void log_service_print(LogLevel level,const char *format, ...); + +/** + * Function: 打印自动化测试日志到串口 + * Description: + * Input: level:日志界别;format:格式化字符串;...:可变参数 + * Output: 无 + * Return: 无 + * Others: 1秒钟处理一次 + */ +void log_service_print_test(const char *format, ...); + + +/** + * Function: 打印16进制数据到串口 + * Description: + * Input: p_data:数据指针;len:数据长度 + * Output: 无 + * Return: 无 + * Others: 1秒钟处理一次 + */ +void log_service_print_hex(const char* p_data, const U16 len); + + +/** + * Function: 上传日志到日志后台 + * Description:异步操作,先内存缓存,然后定时写文件和上传日志后台,函数内部会添加公共的头 + * Input: level:日志界别;p_root——指向json对象的指针 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: p_root由被调函数(本函数)释放 + */ +void log_service_upload(LogLevel level,JsonObject* p_root); + +#endif + diff --git a/inc/main.h b/inc/main.h new file mode 100644 index 0000000..7760ad1 --- /dev/null +++ b/inc/main.h @@ -0,0 +1,67 @@ +/** + * Copyright ? Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: main.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-02-28 + * Description: APP主函数头 + * Others: + * Function List: + 1. APP主入口 + * History: + 1. Date: 2019-02-28 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __GOOME_MAIN_H__ +#define __GOOME_MAIN_H__ + + +/** + * Function: 主函数入口 + * Description:唯一的主函数入口 + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 无 + */ +extern void app_main_entry(void); + +/** + * Function: 普通10ms定时器 + * Description:工作状态时有效,由gsensor唤醒时开启 + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void timer_10ms_proc(void); + +/** + * Function: 普通1秒定时器 + * Description:工作状态时有效,由gsensor唤醒时开启 + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void timer_1s_proc(void); + +/** + * Function: 内核1秒定时器 + * Description:休眠时有效 + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void kal_timer_1s_proc(void* p_arg); + + +#endif + diff --git a/inc/nmea_protocol.h b/inc/nmea_protocol.h new file mode 100644 index 0000000..f3d6997 --- /dev/null +++ b/inc/nmea_protocol.h @@ -0,0 +1,521 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: nmea.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-19 + * Description: GPS标准协议NMEA-0183以及MTK、泰斗、中科微自定义协议实现《The NMEA 0183 Protocol.pdf》 + * Others: + * Function List: + 1. + + * History: + 1. Date: 2019-03-19 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + + +#ifndef __NMEA_H__ +#define __NMEA_H__ + +#include +#include +#include "gm_type.h" + +#define SENTENCE_MAX_LENGTH 80 + +//小端模式:高位代表高地址,内存中是buf[0]=0x23,buf[1]=0x3E,下面的也一样 +#define TD_SENTENCE_HEAD 0x3E23 +#define TD_SENTENCE_TAIL 0x0A +#define TD_AID_TIME_CMD 0x0204 +#define TD_AID_POS_CMD 0x0104 +#define TD_AID_BDSEPH_CMD 0x1104 +#define TD_AID_BDSALM_CMD 0x1204 +#define TD_AID_GPSEPH_CMD 0x2104 +#define TD_AID_GPSALM_CMD 0x2204 +#define TD_AID_ACK_CMD 0x0101 +#define TD_AID_NACK_CMD 0x0201 +#define TD_AID_VER_CMD 0x0105 +#define TD_OPEN_FUNC_CMD 0x5103 + + +#define AT_SENTENCE_HEAD 0xCEBA +#define AT_AID_TIMEPOS_CMD 0x010B +#define AT_AID_BDSEPH_CMD 0x0208 +#define AT_AID_GPSEPH_CMD 0x0708 +#define AT_AID_GLNEPH_CMD 0x0808 +#define AT_AID_ACK_CMD 0x0105 +#define AT_AID_NACK_CMD 0x0005 +#define AT_AID_VER_CMD 0x040A + + +typedef enum +{ + NMEA_INVALID = -1, + NMEA_UNKNOWN = 0, + NMEA_SENTENCE_TXT = 1, // AT 文本 + NMEA_SENTENCE_INF = 2, // TD 文本 + NMEA_SENTENCE_MTK_START = 3, // MTK GPS work OK,可以发送EPO + NMEA_SENTENCE_MTK_ACK = 4, // MTK AGPS ACK,确认包 + NMEA_SENTENCE_MTK_VER = 5, // MTK GPS version,版本号 + NMEA_SENTENCE_TD_ACK = 6, // 泰斗 AGPS ACK,确认包 + NMEA_SENTENCE_TD_VER = 7, // 泰斗 GPS version,版本号 + NMEA_SENTENCE_AT_ACK = 8, // 中科微 AGPS ACK,确认包 + NMEA_SENTENCE_AT_NACK = 9, // 中科微 AGPS ACK,确认包 + NMEA_SENTENCE_AT_VER = 10, // 中科微 GPS version,版本号 + NMEA_SENTENCE_RMC = 11, // 标准NMEA-0183协议RMC语句 + NMEA_SENTENCE_GGA = 12, // 标准NMEA-0183协议GGA语句 + NMEA_SENTENCE_GSA = 13, // 标准NMEA-0183协议GSA语句 + NMEA_SENTENCE_GLL = 14, // 标准NMEA-0183协议GLL语句 + NMEA_SENTENCE_GST = 15, // 标准NMEA-0183协议GST语句 + NMEA_SENTENCE_GSV = 16, // 标准NMEA-0183协议GSV语句 + NMEA_SENTENCE_VTG = 17, // 标准NMEA-0183协议VTG语句 + NMEA_SENTENCE_ZDA = 18, // 标准NMEA-0183协议ZDA语句 + NMEA_SENTENCE_ACCURACY = 19, // MTK精度语句 +}NMEASentenceID; + +typedef struct +{ + S32 value; + S32 scale; +}NMEAFloat; + +typedef struct +{ + S32 day; + S32 month; + S32 year; +}NMEADate; + +typedef struct +{ + S32 hours; + S32 minutes; + S32 seconds; + S32 microseconds; +}NMEATime; + +typedef struct +{ + char ver[64]; +}NMEASentenceVER; + +//$GNRMC,081347.00,A,2232.51905,N,11357.10992,E,2.353,,190319,,,A,V*12 +typedef struct +{ + NMEATime time; + + bool valid; + + NMEAFloat latitude; + + NMEAFloat longitude; + + //速度(单位knots(节)) + NMEAFloat speed; + + //方位角(单位度°) + NMEAFloat course; + + //日期 + NMEADate date; + + NMEAFloat variation; +}NMEASentenceRMC; + +//Global Positioning System Fix Data. +//$GNGGA,081347.00,2232.51905,N,11357.10992,E,1,08,1.13,-121.3,M,-2.4,M,,*7C +typedef struct +{ + NMEATime time; + + NMEAFloat latitude; + + NMEAFloat longitude; + + //0——未定位;1——已定位;2——差分定位 + S32 fix_quality; + + //可见卫星数0-12 + S32 satellites_tracked; + + //水平分量精度因子:为纬度和经度等误差平方和的开根号值([0.5--99.9]数值越小精度越高) + //直接反映GPS卫星的分布情况,当值较大时,表明空中的4颗GPS卫星几何分布不是太理想,他们构成的图形周长太短,定位精度就低,反之亦然。 + NMEAFloat hdop; + + //天线高度(相对于平均海平面) + NMEAFloat altitude; + + //天线高度单位,‘M’为M + char altitude_units; + + //Geoidal separation, the difference between the WGS-84 earth ellipsoid and mean-sea-level (geoid), "-" means mean-sea-level below ellipsoid + NMEAFloat height; + + char height_units; + + //Age of differential GPS data, time in seconds since last SC104 type 1 or 9 update, null field when DGPS is not used + NMEAFloat dgps_age; +}NMEASentenceGGA; + +typedef enum +{ + NMEA_GLL_STATUS_DATA_VALID = 'A', + NMEA_GLL_STATUS_DATA_NOT_VALID = 'V', +}NMEAGLLStatus; + +// FAA mode added to some fields in NMEA 2.3. +typedef enum +{ + NMEA_FAA_MODE_AUTONOMOUS = 'A', + NMEA_FAA_MODE_DIFFERENTIAL = 'D', + NMEA_FAA_MODE_ESTIMATED = 'E', + NMEA_FAA_MODE_MANUAL = 'M', + NMEA_FAA_MODE_SIMULATED = 'S', + NMEA_FAA_MODE_NOT_VALID = 'N', + NMEA_FAA_MODE_PRECISE = 'P', +}NMEAFAAMode; + +//Geographic Position – Latitude/Longitude +typedef struct +{ + NMEAFloat latitude; + NMEAFloat longitude; + NMEATime time; + char status; + char mode; +}NMEASentenceGLL; + +//GPS Pseudorange Noise Statistics +typedef struct +{ + NMEATime time; + NMEAFloat rms_deviation; + NMEAFloat semi_major_deviation; + NMEAFloat semi_minor_deviation; + NMEAFloat semi_major_orientation; + NMEAFloat latitude_error_deviation; + NMEAFloat longitude_error_deviation; + NMEAFloat altitude_error_deviation; +}NMEASentenceGST; + +typedef enum +{ + NMEA_GPGSA_MODE_AUTO = 'A', + NMEA_GPGSA_MODE_FORCED = 'M', +}NMEAGSAMode; + +typedef enum +{ + NMEA_GPGSA_FIX_NONE = 1, + NMEA_GPGSA_FIX_2D = 2, + NMEA_GPGSA_FIX_3D = 3, +}NMEAGSAFixType; + +//GPS DOP and active satellites +typedef struct +{ + char mode; + S32 fix_type; + S32 satellites[12]; + NMEAFloat pdop; + NMEAFloat hdop; + NMEAFloat vdop; +}NMEASentenceGSA; + +typedef struct +{ + S32 nr; + //海拔 + S32 elevation; + + //地平经度,方位角(用以找出恒星、行星等的方位); + S32 azimuth; + + //SNR in dB + S32 snr; +}NMEASatelliteInfo; + +//Satellites in view +typedef struct +{ + S32 total_msgs; + S32 msg_number; + S32 total_satellites; + NMEASatelliteInfo satellites[4]; +}NMEASentenceGSV; + +//Track Made Good and Ground Speed +typedef struct +{ + NMEAFloat true_track_degrees; + NMEAFloat magnetic_track_degrees; + NMEAFloat speed_knots; + NMEAFloat speed_kph; + NMEAFAAMode faa_mode; +}NMEASentenceVTG; + +//Time & Date – UTC, Day, Month, Year and Local Time Zone +typedef struct +{ + NMEATime time; + NMEADate date; + S32 hour_offset; + S32 minute_offset; +}NMEASentenceZDA; + +typedef enum +{ + MTK_TIME_ACK = 740, + MTK_POS_ACK = 713, + MTK_DATA_ACK = 721, + MTK_TTFF_ACK = 257, +}MTKAckType; + +typedef struct +{ + MTKAckType ack_type; +}NMEASentenceMTKACK; + + + + +/** + * Function: 确定语句 + * Description: + * Input: p_sentence:语句;strict——是否严格模式 + * Output: 语句类型 + * Return: true——有效;false——无效 + * Others: + */ +NMEASentenceID nmea_sentence_id(const char* p_sentence, const U16 len, bool strict); + +/** + * Function: 解析特定类型的语句 + * Description: + * Input: p_sentence:二进制形式的语句 + * Output: p_frame:结构体形式的语句内容 + * Return: true——成功;false——失败 + * Others: + */ + +bool nmea_parse_txt(NMEASentenceVER* p_frame, const char* p_sentence); +bool nmea_parse_inf(NMEASentenceVER* p_frame, const char* p_sentence); +bool nmea_parse_rmc(NMEASentenceRMC* p_frame, const char* p_sentence); +bool nmea_parse_gga(NMEASentenceGGA* p_frame, const char* p_sentence); +bool nmea_parse_gsa(NMEASentenceGSA* p_frame, const char* p_sentence); +bool nmea_parse_gll(NMEASentenceGLL* p_frame, const char* p_sentence); +bool nmea_parse_gst(NMEASentenceGST* p_frame, const char* p_sentence); +bool nmea_parse_gsv(NMEASentenceGSV* p_frame, const char* p_sentence); +bool nmea_parse_vtg(NMEASentenceVTG* p_frame, const char* p_sentence); +bool nmea_parse_zda(NMEASentenceZDA* p_frame, const char* p_sentence); +bool nmea_parse_mtk_ack(NMEASentenceMTKACK* p_frame, const char* p_sentence); +bool nmea_parse_mtk_ver(NMEASentenceVER* p_frame, const char* p_sentence); +bool nmea_parse_td_ack(U16* p_cmd, const char* p_sentence, const U16 len); +bool nmea_parse_td_ver(NMEASentenceVER* p_frame, const char* p_sentence, const U16 len); +bool nmea_parse_at_ack(U16* p_cmd, const char* p_sentence, const U16 len); +bool nmea_parse_at_ver(NMEASentenceVER* p_frame, const char* p_sentence, const U16 len); + + +/** + * Function: 创建内置(MTK)一般语句 + * Description: + * Input: cmd:命令;p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +void nmea_create_common_mtk_sentence(const char* cmd,U8* p_sentence); + +/** + * Function: 创建内置(MTK)查询版本号语句 + * Description: + * Input: p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_mtk_qeury_version_sentence(U8* p_sentence, U8* p_len); + +/** + * Function: 创建内置(MTK)辅助时间语句 + * Description: + * Input: st_time:UTC时间(注意不是本地时间);p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: 无 + * Others: + */ +bool nmea_creat_mtk_aid_time_sentence(const ST_Time st_time, U8* p_sentence, U8* p_len); + +/** + * Function: 创建内置(MTK)辅助位置语句 + * Description: + * Input: ref_lat:辅助位置纬度;ref_lng:辅助位置经度;p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_mtk_aid_pos_sentence(const float ref_lat, const float ref_lng, U8* p_sentence, U8* p_len); + +/** + * Function: 创建内置(MTK)完全冷启动语句 + * Description: + * Input: p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_mtk_full_cold_start_sentence(U8* p_sentence, U8* p_len); +bool nmea_creat_mtk_cold_start_sentence(U8* p_sentence, U8* p_len); + +/** + * Function: 创建内置(MTK)高精度模式语句 + * Description: + * Input: enable:是否高精度模式;p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_high_accuracy_sentence(bool enable,U8* p_sentence, U8* p_len); + +/** + * Function: 创建内置(MTK)打开/关闭主动干扰消除语句 + * Description: + * Input: enable:是否开启;p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_active_interference_cancellation(bool enable,U8* p_sentence, U8* p_len); + +/** + * Function: 创建内置(MTK)设置最小SNR语句 + * Description: + * Input: min_snr:最小信噪比,p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_set_min_snr_sentence(const U8 min_snr, U8* p_sentence, U8* p_len); + +/** + * Function: 创建内置(MTK)EPO数据语句 + * Description: + * Input: seg_index:分片ID;p_data:数据分片指针;data_len:数据长度;p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_mtk_epo_sentence(const U16 seg_index, const U8* p_data, const U16 data_len, U8* p_sentence, U16* p_len); + +/** + * Function: 创建泰斗(TD)查询版本号语句 + * Description: + * Input: p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_td_qeury_version_sentence(U8* p_sentence, U8* p_len); + +/** + * Function: 创建泰斗(TD)辅助时间语句 + * Description: + * Input: st_time:UTC时间(注意不是本地时间);leap_sencond——闰秒值;p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_td_aid_time_sentence(const ST_Time st_time, const U8 leap_sencond, U8* p_sentence, U8* p_len); + +/** + * Function: 创建泰斗(TD)辅助位置语句 + * Description: + * Input: ref_lat:辅助位置纬度;ref_lng:辅助位置经度;p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_td_aid_pos_sentence(const float ref_lat, const float ref_lng, U8* p_sentence, U8* p_len); + +/** + * Function: 创建泰斗(TD)打开VTG语句 + * Description: + * Input: p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_td_open_vtg_sentence( U8* p_sentence, U8* p_len); + + +/** + * Function: 创建中科微(AT)查询版本号语句 + * Description: + * Input: p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_at_qeury_version_sentence(U8* p_sentence, U8* p_len); + + +/** + * Function: 创建中科微(AT)辅助信息语句 + * Description:把辅助位置和辅助时间打包成专用的二进制数据格式 + * Input: st_time:UTC时间(注意不是本地时间);leap_sencond——闰秒值;ref_lat:辅助位置纬度;ref_lng:辅助位置经度;p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_at_aid_info_sentence(const ST_Time st_time,const U8 leap_sencond, const float ref_lat, const float ref_lng, U8* p_sentence, U8* p_len); + +/** + * Function: 把GPS日期+时间转换为UNIX时间戳 + * Description: + * Input: p_date:GPS日期;p_time:GPS时间 + * Output: 无 + * Return: UNIX时间戳 + * Others: + */ +time_t nmea_get_utc_time(const NMEADate* p_date, const NMEATime* p_time); + +/** + * Function: 改变分母 + * Description: + * Input: p_value:分数;new_scale:新的分母 + * Output: 无 + * Return: 新的分子 + * Others: + */ +S32 nmea_rescale(const NMEAFloat* p_fraction, S32 new_scale); + +/** + * Function: 分数转换成浮点数 + * Description: + * Input: p_fraction:分数 + * Output: 无 + * Return: 转换后的浮点数 + * Others: + */ +float nmea_tofloat(const NMEAFloat* p_fraction); + +/** + * Function: 将原生经纬度转换成浮点经纬度:XX.YYY——XX度YYY分 + * Description: + * Input: p_fraction:分数 + * Output: 无 + * Return: 浮点左标 + * Others: + */ +float nmea_tocoord(const NMEAFloat *p_fraction); + + + +#endif + diff --git a/inc/protocol.h b/inc/protocol.h new file mode 100644 index 0000000..d68cb50 --- /dev/null +++ b/inc/protocol.h @@ -0,0 +1,46 @@ +#ifndef __GPS_PROTOCOL__ +#define __GPS_PROTOCOL__ + +#include "gm_type.h" +#include "error_code.h" +#include "socket.h" + +#define PROTOCOL_HEADER_GOOME 0x67 +#define PROTOCOL_HEADER_CONCOX 0x78 //len 1字节 +#define PROTOCOL_HEADER_CONCOX_NEW 0x79 //len 2字节 +#define PROTOCOL_HEADER_JT808 0x7e +#define PROTOCOL_HEADER_ESCAPE 0x7d +#define MAX_GPS_MSGS_PER_SEND 5 +#define MAX_JT808_MSG_LEN 1024 + +/* msg flow: + login -> THEN login_ack<- THEN iccid-> + heart <-> + gps or lbs or alarm -> THEN ack<- + remote_msg <- THEN ack-> + + (中文地址请求) 设备接收到123短信,上发到服务器, 收到时间经纬度和短信内容后, 通过短信发给源发送方 + + only goome: + alarm_ask <- THEN ack-> + + only jt808: + 改imei号前,要logout +*/ +void protocol_msg_receive(SocketType *socket); + +GM_ERRCODE protocol_send_login_msg(SocketType *socket); +GM_ERRCODE protocol_send_device_msg(SocketType *socket); + +GM_ERRCODE protocol_send_logout_msg(SocketType *socket); +GM_ERRCODE protocol_send_heartbeat_msg(SocketType *socket); +U32 protocol_send_gps_msg(SocketType *socket); + +GM_ERRCODE protocol_send_remote_ack(SocketType *socket, u8 *pRet, u16 retlen); +GM_ERRCODE protocol_send_general_ack(SocketType *socket); +GM_ERRCODE protocol_send_param_get_ack(SocketType *socket); + +#endif + + + diff --git a/inc/protocol_concox.h b/inc/protocol_concox.h new file mode 100644 index 0000000..c2d25b5 --- /dev/null +++ b/inc/protocol_concox.h @@ -0,0 +1,51 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: protocol_concox.h + * Author: 梁震 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. 创建protocol_concox模块 + 2. 销毁protocol_concox模块 + 3. protocol_concox模块定时处理入口 + * History: + 1. Date: 2019-03-01 + Author: 梁震 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __PROTOCOL_CONCOX_H__ +#define __PROTOCOL_CONCOX_H__ + +#include "gm_type.h" +#include "error_code.h" + +#include "gps_service.h" + +/*plen 是输入输出参数*/ +void protocol_concox_pack_login_msg(u8 *pdata, u16 *idx, u16 len); +void protocol_concox_pack_device_status_msg(u8 *pdata, u16 *idx, u16 len); +void protocol_concox_pack_heartbeat_msg(u8 *pdata, u16 *idx, u16 len); +void protocol_concox_pack_remote_ack(u8 *pdata, u16 *idx, u16 len, u8 *pRet, u16 retlen); + + +struct GPSData; +void protocol_concox_pack_gps_msg(GpsDataModeEnum mode, const GPSData *gps, u8 *pdata, u16 *idx, u16 len); +void protocol_concox_pack_lbs_msg(u8 *pdata, u16 *idx, u16 len); +void protocol_concox_pack_alarm_msg(AlarmInfo *alarm,u8 *pdata, u16 *idx, u16 len); +void protocol_concox_pack_position_request_msg(u8 *mobile_num, u8 num_len, u8 *command, u8 cmd_len,u8 *pdata, u16 *idx, u16 len); + +void protocol_concox_parse_msg(u8 *pdata, u16 len); + + + +#endif + + + diff --git a/inc/protocol_goome.h b/inc/protocol_goome.h new file mode 100644 index 0000000..0d979ac --- /dev/null +++ b/inc/protocol_goome.h @@ -0,0 +1,58 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: protocol_goome.h + * Author: 梁震 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. 创建protocol_goome模块 + 2. 销毁protocol_goome模块 + 3. protocol_goome模块定时处理入口 + * History: + 1. Date: 2019-03-01 + Author: 梁震 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __PROTOCOL_GOOME_H__ +#define __PROTOCOL_GOOME_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "socket.h" + +#include "gps.h" +#include "gps_service.h" + + +/*idx 是输入输出参数*/ +void protocol_goome_pack_login_msg(u8 *pdata, u16 *idx, u16 len); +void protocol_goome_pack_iccid_msg(u8 *pdata, u16 *idx, u16 len); +void protocol_goome_pack_heartbeat_msg(u8 *pdata, u16 *idx, u16 len); +void protocol_goome_pack_remote_ack(u8 *pdata, u16 *idx, u16 len, u8 *pRet, u16 retlen); + +struct GPSData; +void protocol_goome_pack_gps_msg(GpsDataModeEnum mode, const GPSData *gps, u8 *pdata, u16 *idx, u16 len); +void protocol_goome_pack_lbs_msg(u8 *pdata, u16 *idx, u16 len); +void protocol_goome_pack_alarm_msg(AlarmInfo *alarm,u8 *pdata, u16 *idx, u16 len); +void protocol_goome_pack_position_request_msg(u8 *mobile_num, u8 num_len, u8 *command, u8 cmd_len,u8 *pdata, u16 *idx, u16 len); + + + +void protocol_goome_parse_msg( u8 *pdata, u16 len); + +void protocol_goome_alarm_ask(u8 *pdata, u16 len); +void protocol_goome_sms_ask(u8 *pdata, u16 len); + + +#endif + + + + diff --git a/inc/protocol_jt808.h b/inc/protocol_jt808.h new file mode 100644 index 0000000..cd9ed26 --- /dev/null +++ b/inc/protocol_jt808.h @@ -0,0 +1,57 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: protocol_jt808.h + * Author: 梁震 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. 创建protocol_jt808模块 + 2. 销毁protocol_jt808模块 + 3. protocol_jt808模块定时处理入口 + * History: + 1. Date: 2019-03-01 + Author: 梁震 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __PROTOCOL_JT808_H__ +#define __PROTOCOL_JT808_H__ + +#include "gm_type.h" +#include "error_code.h" + +#include "gps_service.h" + +/*plen 是输入输出参数*/ +void protocol_jt_pack_regist_msg(u8 *pdata, u16 *idx, u16 len); +void protocol_jt_pack_auth_msg(u8 *pdata, u16 *idx, u16 len); +void protocol_jt_pack_iccid_msg(u8 *pdata, u16 *idx, u16 len); + + +void protocol_jt_pack_logout_msg(u8 *pdata, u16 *idx, u16 len); +void protocol_jt_pack_heartbeat_msg(u8 *pdata, u16 *idx, u16 len); + +struct GPSData; +void protocol_jt_pack_gps_msg(GpsDataModeEnum mode, const GPSData *gps, u8 *pdata, u16 *idx, u16 len); +void protocol_jt_pack_lbs_msg(u8 *pdata, u16 *idx, u16 len); +void protocol_jt_pack_gps_msg2(u8 *pdata, u16 *idx, u16 len); +void protocol_jt_pack_remote_ack(u8 *pdata, u16 *idx, u16 len, u8 *pRet, u16 retlen); +void protocol_jt_pack_general_ack(u8 *pdata, u16 *idx, u16 len); +void protocol_jt_pack_param_ack(u8 *pdata, u16 *idx, u16 len); + + + +void protocol_jt_parse_msg(u8 *pdata, u16 len); + + +#endif + + + + diff --git a/inc/relay.h b/inc/relay.h new file mode 100644 index 0000000..d3e9122 --- /dev/null +++ b/inc/relay.h @@ -0,0 +1,82 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: relay.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. 创建relay模块 + 2. 销毁relay模块 + 3. relay模块定时处理入口 + 4. 断油电 + 5. 恢复油电 + * History: + 1. Date: 2019-03-01 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __RELAY_H__ +#define __RELAY_H__ + +#include "gm_type.h" +#include "error_code.h" + +/** + * Function: 创建relay模块 + * Description:创建relay模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE relay_create(void); + +/** + * Function: 销毁relay模块 + * Description:销毁relay模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE relay_destroy(void); + +/** + * Function: relay模块定时处理入口 + * Description:不满足断油电条件的,定时检查条件,条件满足时执行 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 1秒钟调用1次 + */ +GM_ERRCODE relay_timer_proc(void); + +/** + * Function: 断油电 + * Description:接常闭继电器,打开继电器=断油电,不满足执行条件时会在条件满足时执行最后一条指令 + * Input: check_speed:是否检查速度 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE relay_on (bool check_speed); + +/** + * Function: 恢复油电 + * Description:接常闭继电器,关闭继电器=恢复油电,不满足执行条件时会在条件满足时执行最后一条指令 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE relay_off (void); + +#endif + diff --git a/inc/sms.h b/inc/sms.h new file mode 100644 index 0000000..8c65936 --- /dev/null +++ b/inc/sms.h @@ -0,0 +1,65 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: sms.h + * Author: 李耀轩 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. 创建sms模块 + 2. 销毁sms模块 + 3. sms模块定时处理入口 + * History: + 1. Date: 2019-03-01 + Author: 李耀轩 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __SMS_H__ +#define __SMS_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "gm_sms.h" + +/** + * Function: 创建sms模块 + * Description:创建sms模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE sms_create(void); + +/** + * Function: 销毁sms模块 + * Description:销毁sms模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE sms_destroy(void); + +/** + * Function: 发送短信 + * Description: + * Input: pdata:发送短信内容 + * dist_number:发送短信号码 + * contentDcs:发送短信格式 + * Output: 无 + * Return: GM_SUCCESS——成功接收,存放发送短信缓存;其它错误码——失败 + * Others: + */ +GM_ERRCODE sms_send(const char* p_data, u16 data_len, char* number, ENUM_SMSAL_DCS doc_type); + +#endif + + + diff --git a/inc/socket.h b/inc/socket.h new file mode 100644 index 0000000..41d08a8 --- /dev/null +++ b/inc/socket.h @@ -0,0 +1,185 @@ +#ifndef __GM_SOCKET_H__ +#define __GM_SOCKET_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "fifo.h" + +#define MAX_SOCKET_RECV_MSG_LEN 750 +#define MAX_SOCKET_SEND_MSG_LEN 1600 +#define MAX_SOCKET_ONE_SEND_LEN 500 + +#define MAX_SOCKET_SUPPORTED 10 +#define SIZE_OF_SOCK_FIFO 2000 + +#define MAX_GET_HOST_REPEAT 3 +#define MAX_CONNECT_REPEAT 3 +#define MAX_MESSAGE_REPEAT 3 + +#define CONNECT_TIME_OUT 10 +#define GET_HOST_TIME_OUT 10 +#define MESSAGE_TIME_OUT 10 + +/* Socket Type */ +typedef enum +{ + STREAM_TYPE_STREAM = 0, /* stream socket, TCP */ + STREAM_TYPE_DGRAM = 1, /* datagram socket, UDP */ + STREAM_TYPE_SMS = 2, /* SMS bearer */ + STREAM_TYPE_RAW = 3, /* raw socket */ +} StreamType; + + +/* +标明Socket的通道,在SDK中会根据access_id来记录Socket相关参数(sockaddr_struct?? +对应到GM_SocketConnect 的access_id参数 +*/ +typedef enum +{ + SOCKET_INDEX_MAIN = 0, + SOCKET_INDEX_EPO = 1, + SOCKET_INDEX_AGPS = SOCKET_INDEX_EPO, + SOCKET_INDEX_LOG = 2, + SOCKET_INDEX_UPDATE = 3, + SOCKET_INDEX_CONFIG = 4, + SOCKET_INDEX_UPDATE_FILE = 5, + SOCKET_INDEX_MAX = MAX_SOCKET_SUPPORTED + 1, +}SocketIndexEnum; + + +typedef struct +{ + int id; /* socket id */ + char addr[GOOME_DNS_MAX_LENTH]; /*dns name*/ + u8 status; /* current status */ + u8 status_fail_count; /* fail count of current status */ + u8 ip[4]; + u16 port; + StreamType type; + SocketIndexEnum access_id; /* used by sdk. */ + FifoType fifo; + u8 excuted_get_host; /* if excuted get host, can not connect then fail.*/ + u32 send_time; /* record time of recent get host, connect, send msg etc*/ + + //because gps data have no ack msg. it depends on ack_seq to confirm msg is received. + u32 last_ack_seq; //ack_seq before send +}SocketType; + + + + + +typedef enum +{ + SOCKET_STATUS_INIT = 0, + SOCKET_STATUS_GET_HOST = 1, + SOCKET_STATUS_CONNECTING = 2, + SOCKET_STATUS_LOGIN = 3, //一些socket不用登录 + SOCKET_STATUS_WORK = 4, + SOCKET_STATUS_DATA_FINISH = 5, //配置socket数据ok后才对其它socket初始化 + SOCKET_STATUS_ERROR = 6, //配置socket数据不ok 也要对其它socket初始化 + SOCKET_STATUS_MAX = 7, +}SocketStatus; + +typedef enum +{ + CURRENT_GET_HOST_INIT = 0, + CURRENT_GET_HOST_CONTINUE = 1, + CURRENT_GET_HOST_SUCCESS = 2, + CURRENT_GET_HOST_FAILED = 3, +}CurrentGetHostByNameStatus; + + +/* +get_host_by_name 独立运行, 更新system_state ip_cache + +socket 与gprs模块交互过程: + 系统 初始态 + gprs_create + 系统 work: + gprs_timer_proc 中据状态操作 + init态 + reg态 + cgreg态 + 注册成功 + gm_socket_global_init() + 若是开机重启(配置socket处于init态 + 配置socket_create + 调gm_socket_init gm_socket_set_ip_port/gm_socket_set_addr + 切换到工作态 + 工作态 + 调配置socket_timer_proc() + 配置socket_timer_proc据状态操作 + init态 + ip有效,直接用ip, + 无效等待ip有效 + 连接态 + 超时重建连接, 三次进入error态 + 工作态 + 收发数据,数据完毕更改配置 进数据ok态 + 数据ok态 error态 + 各socket_create + 各socket _timer_proc据状态操作 + 初始态 + ip有效,直接用ip建连接 + gethost态 + 超时Gprs重新初始化 + 三次进入error态 + 拿到ip建连接 + 连接态 + 超时重建连接, 三次进入error态 + 区分主连接与非主连接 + 连接态 + 需login就login + 工作态 + 收发数据 + 断连态 + 清理数据, 等待重连 + 断连态 + 调gm_socket_global_destroy()函数, + +*/ + +/* 在系统初始化时调用, 初始化account_id*/ +GM_ERRCODE gm_socket_global_init(void); + +/* 在gprs重建连接时调用 清理所有socket */ +void gm_socket_global_destroy(void); + +SocketType * get_socket_by_id(int id); +SocketType * get_socket_by_accessid(int access_id); + + + +/* 在socket 初始化时调用, 初始化socket对应的id, status, fifo等*/ +GM_ERRCODE gm_socket_init(SocketType *socket); +GM_ERRCODE gm_socket_connect(SocketType *socket); +void gm_socket_get_host_by_name_trigger(SocketType *socket); +void gm_socket_get_host_timer_proc(void); + + +/*在GM_SocketRegisterCallBack 注册的回调函数 gprs_socket_notify 中调用 */ +void gm_socket_connect_ok(SocketType *socket); +void gm_socket_close_for_reconnect(SocketType *socket); +void gm_socket_destroy(SocketType * socket); + + +/* 在socket 连接建立前调用 重建连接不用调用 */ +GM_ERRCODE gm_socket_set_ip_port(SocketType *socket, u8 ip[4], u16 port, StreamType type); +GM_ERRCODE gm_socket_set_addr(SocketType *socket, u8 *addr, u8 addr_len, u16 port, StreamType type); +void gm_socket_set_account_id(int account_id); +GM_ERRCODE gm_is_valid_ip(const u8*data); +GM_ERRCODE gm_socket_send(SocketType *socket, u8 *data, u16 len); +GM_ERRCODE gm_socket_recv(SocketType *socket); +const char * gm_socket_status_string(SocketStatus statu); +GM_ERRCODE gm_socket_get_ackseq(SocketType *socket, u32 *ack_seq); + + +void current_get_host_init(void); +void socket_get_host_by_name_callback(void *msg); + + +#endif + + + diff --git a/inc/system_state.h b/inc/system_state.h new file mode 100644 index 0000000..7f3bd04 --- /dev/null +++ b/inc/system_state.h @@ -0,0 +1,415 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: system_state.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-12 + * Description: 全局系统状态管理 + * Others: + * Function List: + 1. + + * History: + 1. Date: 2019-03-12 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __SYSTEM_STATE_H__ +#define __SYSTEM_STATE_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "g_sensor.h" +#include +#include "gps.h" + + +typedef enum +{ + GM_RREBOOT_UNKNOWN = -1, + GM_REBOOT_CMD = 0, + GM_REBOOT_UPDATE = 1, + GM_REBOOT_POWER_ON = 2, + GM_REBOOT_GPRS = 3, + GM_REBOOT_GPS = 4, + GM_REBOOT_CHECKPARA = 5, +}BootReason; + + +typedef enum +{ + GM_SYSTEM_STATE_WORK = 0, + GM_SYSTEM_STATE_SLEEP = 1 +}SystemWorkState; + +typedef enum +{ + VEHICLE_STATE_RUN = 0, + VEHICLE_STATE_STATIC = 1 +} VehicleState; + + +void system_state_set_last_gps(const GPSData *p_gps); +void system_state_get_last_gps(GPSData *p_gps); + + +/** + * Function: 创建system_state模块 + * Description:创建system_state模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE system_state_create(void); + +/** + * Function: 销毁system_state模块 + * Description:销毁system_state模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE system_state_destroy(void); + +/** + * Function: 重置system_state数据 + * Description: + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE system_state_reset(void); + +/** + * Function: 清除重启次数 + * Description: + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE system_state_clear_reboot_count(void); + +/** + * Function: system_state模块定时处理入口 + * Description:system_state模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 1秒调用1次 + */ +GM_ERRCODE system_state_timer_proc(void); + + + +typedef enum +{ + SYSBIT_START_TYPE = 1L, //启动类型:0-重启,1——上电 + SYSBIT_UPLOADED_LOCATE = 1L<<1, //上电后是否已上传过定位 + SYSBIT_UPLOADED_STATIC = 1L<<2, //是否已发送静止点 + SYSBIT_UPLOADED_GPS = 1L<<3, //修改IP后是否已上传GPS数据 + SYSBIT_CHARGE_OPEN = 1L<<4, //充电是否开启(软件控制) + SYSBIT_ACC_CHECK_MODE = 1L<<5, //ACC检测模式:0——震动检测; 1——ACC线检测 + SYSBIT_RELAY_STATE = 1L<<6, //设备relay端口状态: 0——低电平(恢复油电); 1——高电平(断油电) + SYSBIT_RELAY_STATE_USER = 1L<<7, //用户设置relay端口状态:0——低电平(恢复油电); 1——高电平(断油电) + + SYSBIT_ALARM_NO_POWER = 1L<<16, //断电报警 + SYSBIT_ALARM_BAT_LOW = 1L<<17, //电池低电报警 + SYSBIT_ALARM_LOW_POWER = 1L<<18, //电源电压过低报警 + SYSBIT_ALARM_HIGH_POWER = 1L<<19, //电源电压过高报警 + SYSBIT_ALARM_SHOCK = 1L<<20, //震动报警 + SYSBIT_ALARM_SPEED = 1L<<21, //超速报警 + SYSBIT_ALARM_FAKE_BASE = 1L<<22, //伪基站报警 + SYSBIT_ALARM_COLLIDE = 1L<<23, //碰撞报警 + SYSBIT_ALARM_SPEED_UP = 1L<<24, //急加速报警 + SYSBIT_ALARM_SPEED_DOWN = 1L<<25, //急减速报警 + SYSBIT_ALARM_TURN_OVER = 1L<<26, //翻车报警 + SYSBIT_ALARM_SHARP_TURN = 1L<<27, //急转弯报警 + SYSBIT_ALARM_PULL_DOWN = 1L<<28, //拆动报警 + SYSBIT_ALARM_MOVE = 1L<<29, //车辆移动报警(使用原位移报警位) +}StateBitEnum; + + +/** + * Function: 获取状态位 + * Description: bit0 ——启动类型:0-重启,1——上电 + bit1 ——上电后是否已上传过定位 + bit2 ——是否已发送静止点 + bit3 ——修改IP后是否已上传GPS数据 + bit4 ——充电是否开启(软件控制) + bit5 ——ACC检测模式:0——震动检测; 1——ACC线检测 + bit6 ——设备relay端口状态: 0——低电平(恢复油电); 1——高电平(断油电) + bit7 ——用户设置relay端口状态:0——低电平(恢复油电); 1——高电平(断油电) + bit8 ——备用 + bit9 ——备用 + bit10——备用 + bit11——备用 + bit12——备用 + bit13——备用 + bit14——备用 + bit15——备用 + + bit16——断电报警, + bit17——电池低电报警 + bit18——电源电压过低报警 + bit19——电源电压过高报警 + bit20——震动报警 + bit21——超速报警 + bit22——伪基站报警 + bit23——碰撞报警 + bit24——急加速报警 + bit25——急减速报警 + bit26——翻车报警 + bit27——急转弯报警 + bit28——拆动报警 + bit29——车辆移动报警 + bit30——备用 + bit31——备用 + * Input: 无 + * Output: 无 + * Return: 状态位 + * Others: + */ +U32 system_state_get_status_bits(void); + +/** + * Function: 获取启动时间 + * Description: + * Input: 无 + * Output: 无 + * Return: 启动时间(秒) + * Others: + */ +U32 system_state_get_start_time(void); + +/** + * Function: 获取启动原因 + * Description: + * Input: add_counts:是否增加统计次数 + * Output: 无 + * Return: 启动原因 + * Others: + */ +BootReason system_state_get_boot_reason(bool add_counts); + +/** + * Function: 获取启动原因字符串 + * Description: + * Input: reason:启动原因 + * Output: 无 + * Return: 启动原因字符串 + * Others: + */ +const char* system_state_get_boot_reason_str(BootReason reason); + + +/** + * Function: 设置启动原因 + * Description: + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE system_state_set_boot_reason(const BootReason boot_reason); + +/** + * Function: 获取重启次数 + * Description: + * Input: boot_reason:重启原因 + * Output: 无 + * Return: 指定重启原因的重启次数 + * Others: + */ +U32 system_state_get_reboot_counts(const BootReason boot_reason); + +/** + * Function: 获取工作状态 + * Description: + * Input: 无 + * Output: 无 + * Return: 工作状态 + * Others: + */ +SystemWorkState system_state_get_work_state(void); + +/** + * Function: 设置车辆状态 + * Description: + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE system_state_set_work_state(const SystemWorkState work_state); + +/** + * Function: 设置工作状态 + * Description: + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE system_state_set_vehicle_state(const VehicleState work_state); + +/** + * Function: 获取车辆状态 + * Description: + * Input: 无 + * Output: 无 + * Return: 车辆状态 + * Others: + */ +VehicleState system_state_get_vehicle_state(void); + +bool system_state_has_reported_gps_since_boot(void); + +GM_ERRCODE system_state_set_has_reported_gps_since_boot(bool state); + +bool system_state_has_reported_lbs_since_boot(void); + +GM_ERRCODE system_state_set_has_reported_lbs_since_boot(bool state); + +bool system_state_has_reported_static_gps(void); + +GM_ERRCODE system_state_set_has_reported_static_gps(bool state); + +bool system_state_has_reported_gps_since_modify_ip(void); + +GM_ERRCODE system_state_set_reported_gps_since_modify_ip(bool state); + +bool system_state_get_defence(void); + +GM_ERRCODE system_state_set_defence(bool state); + +bool system_state_get_high_voltage_alarm(void); + +GM_ERRCODE system_state_set_high_voltage_alarm(bool state); +/*bit16——断电报警------------------- + bit17——电池低电报警------------------- + bit18——电源电压过低报警 + bit19——震动报警 + bit20——超速报警 + bit21——伪基站报警 + bit22——电源电压过高报警 + bit23——碰撞报警 + bit24——急加速报警 + bit25——急减速报警 + bit26——翻车报警 + bit27——急转弯报警 + bit28——拆动报警 + bit29——车辆移动报警 +*/ +bool system_state_get_power_off_alarm(void); + +GM_ERRCODE system_state_set_power_off_alarm(bool state); + +bool system_state_get_battery_low_voltage_alarm(void); + +GM_ERRCODE system_state_set_battery_low_voltage_alarm(bool state); + +bool system_state_get_shake_alarm(void); + +GM_ERRCODE system_state_set_shake_alarm(bool state); + +bool system_state_get_overspeed_alarm(void); + +GM_ERRCODE system_state_set_overspeed_alarm(bool state); + +bool system_state_get_fakecell_alarm(void); + +GM_ERRCODE system_state_set_fakecell_alarm(bool state); + +bool system_state_get_highvoltage_alarm(void); + +GM_ERRCODE system_state_set_highvoltage_alarm(bool state); + +bool system_state_get_collision_alarm(void); + +GM_ERRCODE system_state_set_collision_alarm(bool state); + +bool system_state_get_speed_up_alarm(void); + +GM_ERRCODE system_state_set_speed_up_alarm(bool state); + +bool system_state_get_speed_down_alarm(void); + +GM_ERRCODE system_state_set_speed_down_alarm(bool state); + +bool system_state_get_turn_over_alarm(void); + +GM_ERRCODE system_state_set_turn_over_alarm(bool state); + +bool system_state_get_sharp_turn_alarm(void); + +GM_ERRCODE system_state_set_sharp_turn_alarm(bool state); + +bool system_state_get_remove_alarm(void); + +GM_ERRCODE system_state_set_remove_alarm(bool state); + +bool system_state_get_move_alarm(void); + +GM_ERRCODE system_state_set_move_alarm(bool state); + +bool system_state_get_move_alarm(void); + +GM_ERRCODE system_state_set_move_alarm(bool state); + +bool system_state_get_has_started_charge(void); + +GM_ERRCODE system_state_set_has_started_charge(bool state); + +bool system_state_get_acc_is_line_mode(void); + +GM_ERRCODE system_state_set_acc_is_line_mode(bool state); + +bool system_state_get_device_relay_state(void); + +GM_ERRCODE system_state_set_device_relay_state(bool state); + +bool system_state_get_user_relay_state(void); + +bool system_state_is_cold_boot(void); + +GM_ERRCODE system_state_set_cold_boot(bool state); + +GM_ERRCODE system_state_set_user_relay_state(bool state); + +U8 system_state_get_extern_battery_voltage_grade(void); + +GM_ERRCODE system_state_set_extern_battery_voltage_grade(U8 voltage_grade); + +void system_state_set_mileage(U32 mileage); + +U32 system_state_get_mileage(void); + +void system_state_set_bin_checksum(U32 check_sum); + +U32 system_state_get_bin_checksum(void); + +void system_state_set_gsensor_type(GSensorType gsensor_type); + +GSensorType system_state_get_gsensor_type(void); + +u32 system_state_get_last_good_time(void); +u32 system_state_get_call_ok_count(void); + +void system_state_set_gpss_reboot_reason(const char *reason); +const char *system_state_get_gpss_reboot_reason(void); + +void system_state_set_ip_cache(U8 index,const U8* ip); +void system_state_get_ip_cache(U8 index,U8* ip); + + +#endif + diff --git a/inc/uart.h b/inc/uart.h new file mode 100644 index 0000000..129160b --- /dev/null +++ b/inc/uart.h @@ -0,0 +1,113 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: uart.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-06 + * Description: 串口配置管理、数据读写 + * Others: 1、使用顺序:创建->注册回调函数->打开串口 + 2、GM_UART_DEBUG端口接收到的数据发给commandgps模块 + 3、GM_UART_GPS端口接受到的数据发送给gps模块 + * Function List: + 1. 创建uart模块 + 2. 销毁uart模块 + 3. 定时处理入口 + 4. 注册回调函数 + 5. 打开串口 + 6. 关闭串口 + 7. 向串口写数据 + + * History: + 1. Date: 2019-03-06 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __UART_H__ +#define __UART_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "gm_uart.h" + +typedef enum +{ + GM_UART_DEBUG = UART_PORT1, + GM_UART_GPS = UART_PORT2, + GM_UART_BMS = UART_PORT3, + GM_UART_MAX = 3 +}UARTPort; + +#define BAUD_RATE_HIGH 115200 +#define BAUD_RATE_LOW 9600 + +/** + * Function: 创建uart模块 + * Description:创建uart模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE uart_create(void); + +/** + * Function: 销毁uart模块 + * Description:销毁uart模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE uart_destroy(void); + +/** + * Function: uart模块定时处理入口 + * Description:uart模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE uart_timer_proc(void); + + +/** + * Function: 打开串口 + * Description:波特率只有特定的几个值(9600、115200等) + * Input: port:哪个串口;baud_rate:波特率;no_data_to_reopen_time:超过时间收不到数据重新打开串口,如果为0则检查 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE uart_open_port(const UARTPort port, const U32 baud_rate, const U16 no_data_to_reopen_time); + +/** + * Function: 关闭串口 + * Description:波特率只有特定的几个值(9600、115200等) + * Input: port:哪个串口 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE uart_close_port(const UARTPort port); + + +/** + * Function: 向串口写数据 + * Description:同步操作 + * Input: port:哪个串口;p_data:数据指针;len——数据长度 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE uart_write(const UARTPort port, const U8* p_data, const U16 len); + +#endif + + + diff --git a/inc/update_file.h b/inc/update_file.h new file mode 100644 index 0000000..84c5999 --- /dev/null +++ b/inc/update_file.h @@ -0,0 +1,141 @@ +#ifndef __UPDATE_FILE_H__ +#define __UPDATE_FILE_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "socket.h" + +#define UPDATE_PING_TIME 43200 +#define UPDATE_RETRY_TIME 180 +#define UPDATE_UPGRADE_FILE L"Z:\\goome\\GmUpGrade\0" +#define UPDATE_TARGET_IMAGE L"Z:\\goome\\GmAppMain.ex\0" +#define UPDATE_MINOR_IMAGE L"Z:\\goome\\GmAppMinor.ex\0" + +#define UPDATE_MAX_PACK 600 +#define UPD_RESERVER_LEN 128 +#define UPDATE_PAKET_MAX_LEN 500 //不能小于等于 UPD_RESERVER_LEN +#define UPDATAE_FILE_MAX_SIZE (UPDATE_MAX_PACK * UPDATE_PAKET_MAX_LEN) +#define UPDATE_MAX_PACK_ONE_SEND 10 //每次发送包数 //不可超过30 + +/* +2字节 1字节 2字节 8字节 N字节 1字节 1字节 +包头 命令字 报文长度 终端ID 数据内容 校验 结束符 +0x68 0x68 CMD LEN ID DATA CHK 0x0D +*/ +#define PROTOCOL_HEADER_UPDATE 0x68 +#define PROTOCOL_TAIL_UPDATE 0x0D +typedef enum +{ + PROTOCCOL_UPDATE_REQUEST = 0x11, //终端向服务器查询是否有升级 + PROTOCCOL_UPDATE_REQUEST_FILE = 0x12, //终端向服务器请求文件数据 + PROTOCCOL_UPDATE_REPORT = 0x13, //终端向服务器上报升级结果 + PROTOCCOL_UPDATE_RESPONSE = 0x91, //服务器向终端返回是否有升级 + PROTOCCOL_UPDATE_FILE_DATA = 0x92, //服务器向终端下发文件数据 +}ProtocolUpdateCmdEnum; + +typedef enum +{ + UPDATE_NONE = 0x00, + UPDATE_QUE = 0x01, + UPDATE_READY = 0x02, +}ProtocolUpdateResultEnum; + + +typedef enum +{ + REPORT_RESULT_FINISH = 0x00, //已接收完成,尚未更新 + REPORT_RESULT_UPDATED = 0x01, //已接收完成,并更新 + REPORT_RESULT_FAILED = 0x02 //更新失败 +}ReportResultEnum; + + +/* +记录服务器发来的升级响应 + +以及发给服务器的请求包状态 +*/ +typedef struct +{ + bool use_new_socket; //是否新建连接 + + u32 check_sum; //升级文件的校验码 + u32 total_len; //升级文件的总长度 + u8 custom_code[7]; //客户代码 + u8 model[6]; //终端型号编码 + u8 file_id[9]; //升级文件的ID + u8 task_id[9]; //升级任务的ID + + //发给服务器的请求包状态 + u16 total_blocks; //包数 + u16 block_size; //每包数据大小 + u16 block_current; //当前包序号 + u32 block_status; // 从低到高, 每一位代表从当前包开始,往后的回收情况,收到回包为1,未收到为0 + + int handle; // file handle + ReportResultEnum result; // 升级结果 + u8 result_info[50]; + u32 state_sum; // state file的check sum +}UpdateFileExtend; + +/* +只给update_service使用 +由于 s_file_socket是s_update_socket的伴生socket, +所以 update_file中能访问的, update_service一般也要能访问 +*/ +UpdateFileExtend *get_file_extend(void); +void init_file_extend(bool boot_init); + +/** + * Function: 创建update_file模块 + * Description:创建update_file模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE update_filemod_create(void); + +/** + * Function: 销毁update_file模块 + * Description:销毁update_file模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE update_filemod_destroy(void); + +/** + * Function: update_file模块定时处理入口 + * Description:update_file模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE update_filemod_timer_proc(void); + + +void update_filemod_connection_failed(void); +void update_filemod_connection_ok(void); +void update_filemod_close_for_reconnect(void); +u32 update_filemod_get_checksum(const u16 *FileName); + + + +/*以下函数与update_service模块共用*/ +void update_msg_receive(SocketType *socket); +void update_msg_parse(u8 *pdata, u16 len); +void update_msg_parse_response(u8 *pdata, u16 len); + +void update_msg_pack_head(u8 *pdata, u16 *idx, u16 len); +void update_msg_pack_id_len(u8 *pdata, u8 id, u16 len); +void update_msg_pack_request(u8 *pdata, u16 *idx, u16 len); + + +void update_msg_start_data_block_request(SocketType *socket); +GM_ERRCODE update_msg_send_data_block_request(SocketType *socket); +GM_ERRCODE update_msg_send_result_to_server(SocketType *socket); + +#endif + diff --git a/inc/update_service.h b/inc/update_service.h new file mode 100644 index 0000000..eb69734 --- /dev/null +++ b/inc/update_service.h @@ -0,0 +1,91 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: update_service.h + * Author: 梁震 + * Version: 1.0 + * Date: 2019-02-28 + * Description: 模块升级服务 + * Others: + * Function List: + 1. 创建 + 2. 销毁 + 3. + * History: + 1. Date: 2019-03-01 + Author: 梁震 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __UPDATE_SERVICE_H__ +#define __UPDATE_SERVICE_H__ + +#include "gm_type.h" +#include "error_code.h" +#include "socket.h" + +/** + * Function: 创建update_service模块 + * Description:创建update_service模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE update_service_create(bool first_create); + +/** + * Function: 销毁update_service模块 + * Description:销毁update_service模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE update_service_destroy(void); + +/** + * Function: update_service模块定时处理入口 + * Description:update_service模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE update_service_timer_proc(void); + + +/** + * Function: 获取update_service模块状态 + * Description: + * Input: 无 + * Output: 无 + * Return: SocketStatus + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +SocketStatus update_service_get_status(void); + + +void update_service_connection_failed(void); +void update_service_connection_ok(void); +void update_service_finish(u32 wait); +void update_service_result_to_server(void); + +void update_service_after_response(bool newsocket, u32 total_len); +void update_service_after_blocks_finish(void); + +/** + * Function: 确定升级模块是否处于等待重启, 需要配合update_service_get_status使用 + * Description: 用于无线模块发现升级了,不进入休眠,立即重启,以得到升级后的执行效果(否则要等下次唤醒,可能是一周甚至一月以后) + * Input: 无 + * Output: 无 + * Return: true:升级完成 false:不需要升级,或升级失败 + * Others: 只有update_service_get_status 得到SOCKET_STATUS_DATA_FINISH时,才可以用此函数判断 + */ +bool update_service_is_waiting_reboot(void); + +#endif + diff --git a/inc/utility.h b/inc/utility.h new file mode 100644 index 0000000..a43f168 --- /dev/null +++ b/inc/utility.h @@ -0,0 +1,560 @@ +#ifndef __UTILITY_H__ +#define __UTILITY_H__ + +#include +#include "gm_type.h" +#include "error_code.h" +#include "gm_time.h" +#include "time.h" + +#define BIT0 0x0001 +#define BIT1 0x0002 +#define BIT2 0x0004 +#define BIT3 0x0008 +#define BIT4 0x0010 +#define BIT5 0x0020 +#define BIT6 0x0040 +#define BIT7 0x0080 +#define BIT8 0x0100 +#define BIT9 0x0200 +#define BIT10 0x0400 +#define BIT11 0x0800 +#define BIT12 0x1000 +#define BIT13 0x2000 +#define BIT14 0x4000 +#define BIT15 0x8000 + +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + + + +#define GET_BIT0(val) (((val) & BIT0)?1:0) +#define GET_BIT1(val) (((val) & BIT1)?1:0) +#define GET_BIT2(val) (((val) & BIT2)?1:0) +#define GET_BIT3(val) (((val) & BIT3)?1:0) +#define GET_BIT4(val) (((val) & BIT4)?1:0) +#define GET_BIT5(val) (((val) & BIT5)?1:0) +#define GET_BIT6(val) (((val) & BIT6)?1:0) +#define GET_BIT7(val) (((val) & BIT7)?1:0) +#define GET_BIT8(val) (((val) & BIT8)?1:0) +#define GET_BIT9(val) (((val) & BIT9)?1:0) +#define GET_BIT10(val) (((val) & BIT10)?1:0) +#define GET_BIT11(val) (((val) & BIT11)?1:0) +#define GET_BIT12(val) (((val) & BIT12)?1:0) +#define GET_BIT13(val) (((val) & BIT13)?1:0) +#define GET_BIT14(val) (((val) & BIT14)?1:0) +#define GET_BIT15(val) (((val) & BIT15)?1:0) + +#define GET_BIT16(val) (((val) & BIT16)?1:0) +#define GET_BIT17(val) (((val) & BIT17)?1:0) +#define GET_BIT18(val) (((val) & BIT18)?1:0) +#define GET_BIT19(val) (((val) & BIT19)?1:0) +#define GET_BIT20(val) (((val) & BIT20)?1:0) +#define GET_BIT21(val) (((val) & BIT21)?1:0) +#define GET_BIT22(val) (((val) & BIT22)?1:0) +#define GET_BIT23(val) (((val) & BIT23)?1:0) +#define GET_BIT24(val) (((val) & BIT24)?1:0) +#define GET_BIT25(val) (((val) & BIT25)?1:0) +#define GET_BIT26(val) (((val) & BIT26)?1:0) +#define GET_BIT27(val) (((val) & BIT27)?1:0) +#define GET_BIT28(val) (((val) & BIT28)?1:0) +#define GET_BIT29(val) (((val) & BIT29)?1:0) +#define GET_BIT30(val) (((val) & BIT30)?1:0) +#define GET_BIT31(val) (((val) & BIT31)?1:0) + + +#define SET_BIT0(val) val = val|BIT0 +#define SET_BIT1(val) val = val|BIT1 +#define SET_BIT2(val) val = val|BIT2 +#define SET_BIT3(val) val = val|BIT3 +#define SET_BIT4(val) val = val|BIT4 +#define SET_BIT5(val) val = val|BIT5 +#define SET_BIT6(val) val = val|BIT6 +#define SET_BIT7(val) val = val|BIT7 +#define SET_BIT8(val) val = val|BIT8 +#define SET_BIT9(val) val = val|BIT9 +#define SET_BIT10(val) val = val|BIT10 +#define SET_BIT11(val) val = val|BIT11 +#define SET_BIT12(val) val = val|BIT12 +#define SET_BIT13(val) val = val|BIT13 +#define SET_BIT14(val) val = val|BIT14 +#define SET_BIT15(val) val = val|BIT15 + +#define SET_BIT16(val) val = val|BIT16 +#define SET_BIT17(val) val = val|BIT17 +#define SET_BIT18(val) val = val|BIT18 +#define SET_BIT19(val) val = val|BIT19 +#define SET_BIT20(val) val = val|BIT20 +#define SET_BIT21(val) val = val|BIT21 +#define SET_BIT22(val) val = val|BIT22 +#define SET_BIT23(val) val = val|BIT23 +#define SET_BIT24(val) val = val|BIT24 +#define SET_BIT25(val) val = val|BIT25 +#define SET_BIT26(val) val = val|BIT26 +#define SET_BIT27(val) val = val|BIT27 +#define SET_BIT28(val) val = val|BIT28 +#define SET_BIT29(val) val = val|BIT29 +#define SET_BIT30(val) val = val|BIT30 +#define SET_BIT31(val) val = val|BIT31 + + + +#define CLR_BIT0(val) val = val&(~BIT0) +#define CLR_BIT1(val) val = val&(~BIT1) +#define CLR_BIT2(val) val = val&(~BIT2) +#define CLR_BIT3(val) val = val&(~BIT3) +#define CLR_BIT4(val) val = val&(~BIT4) +#define CLR_BIT5(val) val = val&(~BIT5) +#define CLR_BIT6(val) val = val&(~BIT6) +#define CLR_BIT7(val) val = val&(~BIT7) +#define CLR_BIT8(val) val = val&(~BIT8) +#define CLR_BIT9(val) val = val&(~BIT9) +#define CLR_BIT10(val) val = val&(~BIT10) +#define CLR_BIT11(val) val = val&(~BIT11) +#define CLR_BIT12(val) val = val&(~BIT12) +#define CLR_BIT13(val) val = val&(~BIT13) +#define CLR_BIT14(val) val = val&(~BIT14) +#define CLR_BIT15(val) val = val&(~BIT15) + +#define CLR_BIT16(val) val = val&(~BIT16) +#define CLR_BIT17(val) val = val&(~BIT17) +#define CLR_BIT18(val) val = val&(~BIT18) +#define CLR_BIT19(val) val = val&(~BIT19) +#define CLR_BIT20(val) val = val&(~BIT20) +#define CLR_BIT21(val) val = val&(~BIT21) +#define CLR_BIT22(val) val = val&(~BIT22) +#define CLR_BIT23(val) val = val&(~BIT23) +#define CLR_BIT24(val) val = val&(~BIT24) +#define CLR_BIT25(val) val = val&(~BIT25) +#define CLR_BIT26(val) val = val&(~BIT26) +#define CLR_BIT27(val) val = val&(~BIT27) +#define CLR_BIT28(val) val = val&(~BIT28) +#define CLR_BIT29(val) val = val&(~BIT29) +#define CLR_BIT30(val) val = val&(~BIT30) +#define CLR_BIT31(val) val = val&(~BIT31) + +#define BHIGH_BYTE(arg) (*((u8 *)(&arg) + 1)) +#define BLOW_BYTE(arg) (*(u8 *)(&arg)) +#define WHIGH_WORD(arg) (*((u16 *)(&arg) + 1)) +#define WLOW_WORD(arg) (*(u16 *)(&arg)) +#define MERGEBCD(a, b) (((a)<<4)+((b)&0x0f)) +#define UPPER_BYTE(n) (((n) >> 8 ) & 0xff) +#define LOWER_BYTE(n) (((n) & 0xff)) +#define MKWORD(B1, B0) ((((u16)B1)<<8) + ((u16)B0)) +#define MKDWORD(B3, B2, B1, B0) ((((u32)B3)<<24) + (((u32)B2)<<16) + (((u32)B1)<<8) + ((u32)B0)) +#define BCD2HEX(n) ((((n)>>4)*10) + ((n)&0x0f)) // 0x13 = 10+3 +#define HEX2BCD(n) (((((n)/10)%10)<<4) + ((n)%10)) +#define BCD_HIGH(A) (((A) >> 4 ) & 0x0f) +#define BCD_LOW(A) ((A) & 0x0f) +#define IS_DNS_CHAR(c) (((c)!=' ') && ((c)!='!') && ((c)!='$') && ((c)!='&') && ((c)!='?')) +#define BASE_YEAR_2000 2000 + + +typedef enum +{ + GM_CHANGE_FALSE = -1, + GM_NO_CHANGE = 0, + GM_CHANGE_TRUE = 1 +}GM_CHANGE_ENUM; + +typedef struct +{ + bool state; + //报警状态保持时间(秒) + U32 true_state_hold_seconds; + + //正常状态保持时间(秒) + U32 false_state_hold_seconds; + +}StateRecord,*PStateRecord; + + +//GPS的时间起点是1980.1.6 从1970年到1980.1.6的秒数 +#define SECONDS_FROM_UTC_TO_GPS_START (315936000+8*3600) + +/** + * Function: 创建util模块 + * Description:创建util模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE util_create(void); + +/** + * Function: 销毁util模块 + * Description:销毁util模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE util_destroy(void); + + +/** + * Function: util模块定时处理入口 + * Description:uart模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE util_timer_proc(void); + + +/** + * Function: + * Description:change character hex number to real number + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 无 + */ +u8 util_chr(u8 x); + + +/** + * Function: + * Description: change number to character hex number. + * Input: 无 + * Output: 无 + * Return: 无 + * Others: if x is not number, it will be changed as unrecognize_char, normally is 'x' or '0' + */ +u8 util_asc(u8 x, u8 unrecognize_char); + + +/** + * Function: + * Description: remove a char from pdata + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 无 + */ +u16 util_remove_char(u8 *pdata, u16 len,char c); + +char util_to_upper(char c); + +char util_to_lower(char c); + +/** + * Function: + * Description:change pdata string to upper case + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void util_string_upper(u8 *pdata, u16 len); + + +/** + * Function: + * Description: change pdata string to lower case + * Input: 无 + * Output: 无 + * Return: 无 + * Others: 无 + */ +void util_string_lower(u8 *pdata, u16 len); + + +/** + * Function: + * Description:check whether pdns is valid dns + * Input: pdns len + * Output: 无 + * Return: vaild dns return 1, else retun 0 + * Others: 无 + */ +u8 util_is_valid_dns(const u8 *pdns, u16 len); + +/** + * Function: + * Description:check whether ip is valid ip + * Input: ip len + * Output: 无 + * Return: vaild dns return 1, else retun 0 + * Others: 无 + */ +u8 util_is_valid_ip(const u8 *ip, u16 len); + + +/** + * Function: + * Description: get current time to pdata(bcd format) and time(ST_Time format) based on zone. + * Input: 无 + * Output: 无 + * Return: success. + * Others: 无 + */ +GM_ERRCODE util_get_current_local_time(u8* pdata, ST_Time* time, u8 zone); + + +/** + * Function: + * Description: change seconds to bcd time. + * Input: sec_time UTC format + * Output: 无 + * Return: 无 + * Others: 无 + */ +void util_utc_sec_to_bcdtime_base2000(time_t sec_time, u8 *bcd, u8 zone); + +/** + * Function: 判断是否是闰年 + * Description: + * Input: year:年 + * Output: + * Return: true——是闰年;false——不是闰年 + * Others: + */ +bool util_is_leap_year(U16 year); + +/** + * Function: 时间戳转换成数据结构 + * Description:替换time系统函数 + * Input: p_time:指向时间戳的指针 + * Output: 无 + * Return: 时间数据结构 + * Others: + */ +struct tm util_gmtime(time_t t); + +/** + * Function: 时间数据结构转换成时间戳 + * Description:替换time系统函数 + * Input: t:指向时间数据结构的指针 + * Output: 无 + * Return: 时间戳 + * Others: + */ +time_t util_mktime(struct tm* t); + +/** + * Function: 时间戳 转换成 时间数据结构 + * Description:替换time系统函数 + * Input: srctime:指向时间戳的指针 + * Output: 无 + * Return: 时间数据结构 + * Others: + */ +struct tm * util_localtime(const time_t *srctime); + +/** + * Function: 把MTK时间转换为GPS时间 + * Description: + * Input: st_time:MTK时间;leap_sencond——闰秒值 + * Output: p_tow:周内时间(秒);p_wn:周数(从1980年1月1日开始) + * Return: 无 + * Others: GPS时间格式,用周数和周内时表示,GPS的时间起点是1980.1.6 + GPS时间没有闰秒修正,是连续的时间,而常规时间是经过闰秒修正的 + 2016年的闰秒修正值是17秒 + */ +void util_mtktime_to_gpstime(const ST_Time st_time, const U8 leap_sencond, double* p_tow, U16* p_wn); + + +/** + * Function: mtktime 转换为 tm + * Description: + * Input: 无 + * Output: 无 + * Return: Linux时间结构体 + * Others: + */ +void util_mtktime_to_tm(const ST_Time *mtk_t, struct tm *tm_t); + +/** + * Function: tm 转换为 mtktime + * Description: + * Input: 无 + * Output: 无 + * Return: Linux时间结构体 + * Others: + */ +void util_tm_to_mtktime(const struct tm *tm_t, ST_Time *mtk_t); + +/** + * Function: 获取UTC时间 + * Description: + * Input: 无 + * Output: + * Return: Linux时间结构体 + * Others: + */ +time_t util_get_utc_time(void); + + +/** + * Function: 获取开机以来的秒数 + * Description: + * Input: 无 + * Output: + * Return: 开机以来的秒数 + * Others: 每隔229天1小时54分36秒会翻转至0 + */ +u32 util_clock(void); + + +/************************************************************************ + * Function : + * Description : + * Unicode符号范围 UTF-8编码方式 + * 十六进制 二进制 + * 0000 0000-0000 007F | 0xxxxxxx + * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + * 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + + * utf8Str -- UTF8 source string + * utf8StrLen -- max utf8 length + * unStr --- Unicode Str dest + * unMaxLen --- Unicode max length + * return : ---- 实际转化的长度 + + * 把UTF-8转成双字节的UNICODE + * E6 96 AD(汉字"断"的UTF-8编码) ---> 0x65AD (即汉字"断"的UNICODE) + + * Parameter : + * Return : + * Author: + * Date: +************************************************************************/ +u16 util_utf8_to_unicode(const u8 *msg, u16 msg_len, u16 *ucs2_msg, u16 max_len); + + +/************************************************************************ + * Function : + * Description : + * 把双字节的UNICODE转成单字节的UNICODE + * 0x1234 ---> 0x12 , 0x34 + + * Parameter : + * Return : + * Author: + * Date: +************************************************************************/ +u16 util_ucs2_u16_to_u8(const u16 *input, u16 len, u8 *output); + + +/************************************************************************ + * Function : + * Description : + * 把双字节的UNICODE 字节反过来 + * 0x1234 ---> 0x3412 + + * Parameter : + * Return : + * Author: + * Date: +************************************************************************/ +u16 util_ucs2_byte_revert(u8 *pdata, u16 len); + + +/************************************************************************ + * Function : + * Description : + * long转成ascii字符串 + * withZero=1 0x0123456->"0123456" 包括0 + * withZero=0 0x0123456->"123456" 不包括0 + * Parameter : + * Return : + * Author: + * Date: +************************************************************************/ +u8 util_long_to_asc(u32 value, u8 *buffer, u8 with_zero); + + +/************************************************************************ + Function : + Description : delete a file + Parameter : + Return : + Author: + Date: +************************************************************************/ +s32 util_delete_file(const u16 *file); + + +/************************************************************************ + Function : + Description : + change ucs2 to ascii + Parameter : + Return : + Author: + Date: +************************************************************************/ +u16 util_ucs2_to_ascii(const u8 *w_in, u8 *a_out, u16 len); + +/************************************************************************ + * Function: 将海里转换为公里 + * Description: + * Input: 无 + * Output: + * Return: Linux时间结构体 + * Others: + ************************************************************************/ +float util_mile_to_km(const float miles); + +/************************************************************************ + * Function: 判断字符是否为数字 + * Description: + * Input: c:字符 + * Output: + * Return: true——是;false——否 + * Others: + ************************************************************************/ +bool util_isdigit(const char c); + + +/************************************************************************ + * Function: 判断字符是否为可打印字符 + * Description: + * Input: c:字符 + * Output: + * Return: true——是;false——否 + * Others: + ************************************************************************/ +bool util_isprint(const char c); + +/************************************************************************ + * Function: 将10进制数字符串转换成长整型 + * Description:https://baike.baidu.com/item/strtol/6134558 + * Input: cp:字符串; + * Output: endptr:是一个传出参数,函数返回时指向后面未被识别的第一个字符 + * Return: true——是;false——否 + * Others: + ************************************************************************/ +S32 util_strtol(const char* cp,char** endp); + +/** + * Function: 检查状态发生了什么变化 + * Description:当前状态与历史状态不同,并且保持时间足够认为状态发生了变化并记录为新的历史状态 + * Input: current_state:当前状态;p_record:历史状态记录;true_hold_time_threshold:true状态保持时间阈值;false_hold_time_threshold:false状态保持时间阈值 + * Output: p_record:历史状态记录 + * Return: GM_CHANGE_TRUE——变为true状态;GM_NO_CHANGE——不变;GM_CHANGE_FALSE——变为false状态 + * Others: + */ +GM_CHANGE_ENUM util_check_state_change(bool current_state, PStateRecord p_record, U16 true_hold_time_threshold, U16 false_hold_time_threshold); + +#endif + diff --git a/inc/watch_dog.h b/inc/watch_dog.h new file mode 100644 index 0000000..4d5ce40 --- /dev/null +++ b/inc/watch_dog.h @@ -0,0 +1,73 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: watch_dog.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-02-28 + * Description: 实现软件看门狗功能 + * Others: + * Function List: + 1. 创建 + 2. 销毁 + 3. 定时处理入口 + 4. 开启/关闭软件看门狗 + * History: + 1. Date: 2019-02-28 + Author: 王志华 + Modification 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#ifndef __WATCH_DOG_H__ +#define __WATCH_DOG_H__ + +#include "gm_type.h" +#include "error_code.h" + + +/** + * Function: 创建watch_dog模块 + * Description:创建watch_dog模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE watch_dog_create(void); + +/** + * Function: 销毁watch_dog模块 + * Description:销毁watch_dog模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE watch_dog_destroy(void); + +/** + * Function: watch_dog模块定时处理入口 + * Description:watch_dog模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE watch_dog_timer_proc(void); + +/** + * Function: 开启/关闭软件看门狗 + * Description:默认开启 + * Input: enable:true——开启;false——关闭 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE watch_dog_enable(bool enable); + +#endif + + diff --git a/lib/app_start.s b/lib/app_start.s new file mode 100644 index 0000000..b5b967c --- /dev/null +++ b/lib/app_start.s @@ -0,0 +1,322 @@ +;/*************************************************************************************** +; ** DATE: 05/22/2019 * +; ** Copyright: Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved.* +; ** Description: ServiceHeader define * +; *************************************************************************************** + + + PRESERVE8 + AREA ServiceHeader, CODE, READONLY + + IMPORT Service_Entry + IMPORT |Image$$ER_RO$$Length| + IMPORT |Image$$ER_RW$$Length| + IMPORT |Image$$ER_ZI$$ZI$$Length| + + EXPORT service_feature + + + + +;****************************************************************************** +service_version + DCD 0x00000002 +service_feature + DCD 0x00000001 + +service_entry_offset + DCD Service_Entry - {PC} + +ro_size + DCD |Image$$ER_RO$$Length| +rw_size + DCD |Image$$ER_RW$$Length| +zi_size + DCD |Image$$ER_ZI$$ZI$$Length| + + + +;****************************************************************************** +;The Kernel Export function pointer table + + MACRO + Subfun $name + LCLS appfun + LCLS libfun +appfun SETS "$name" +libfun SETS "|$$Super$$$$" :CC: appfun :CC: "|" +appfun SETS "|$$Sub$$$$" :CC: appfun :CC: "|" + EXPORT $appfun + IMPORT $libfun + + CODE32 +$appfun LDR pc, =$libfun + LTORG + + MEND + +; /*Add other export api according to the format of above*/ + + + + Subfun GM_Trace + Subfun GM_ReleaseBuild + Subfun GM_ReleaseBranch + Subfun GM_ReleaseHwVer + Subfun GM_ReleaseVerno + Subfun GM_BuildDateTime + Subfun GM_atoi + Subfun GM_atof + Subfun GM_memset + Subfun GM_memcpy + Subfun GM_memcmp + Subfun GM_memmove + Subfun GM_strcpy + Subfun GM_strncpy + Subfun GM_strcat + Subfun GM_strncat + Subfun GM_strcmp + Subfun GM_strncmp + Subfun GM_strchr + Subfun GM_strlen + Subfun GM_strstr + Subfun GM_sprintf + Subfun GM_snprintf + Subfun GM_vsprintf + Subfun GM_sscanf + Subfun GM_GpioInit + Subfun GM_GetGpioMode + Subfun GM_GpioSetLevel + Subfun GM_GpioGetLevel + Subfun GM_GpioSetDirection + Subfun GM_GpioGetDirection + Subfun GM_GpioSetPullSelection + Subfun GM_RegisterCallBack + Subfun GM_UartOpen + Subfun GM_UartClose + Subfun GM_UartWrite + Subfun GM_UartRead + Subfun GM_UartClrRxBuffer + Subfun GM_UartClrTxBuffer + Subfun GM_CheckSimValid + Subfun GM_GetImei + Subfun GM_GetPlmn + Subfun GM_GetServiceAvailability + Subfun GM_SetLocalTime + Subfun GM_GetLocalTime + Subfun GM_SetUartTrace + Subfun GM_CloseUartTrace + Subfun GM_MemoryAlloc + Subfun GM_MemoryFree + Subfun GM_Ucs2ToAsc + Subfun GM_AscToUcs2 + Subfun GM_SendSMS + Subfun GM_CallAnswer + Subfun GM_CallHangUp + Subfun GM_MakeCall + Subfun GM_SystemReboot + Subfun GM_SystemPowerOff + Subfun GM_FS_Open + Subfun GM_FS_Close + Subfun GM_FS_Read + Subfun GM_FS_Write + Subfun GM_FS_Seek + Subfun GM_FS_Commit + Subfun GM_FS_GetFileSize + Subfun GM_FS_GetFilePosition + Subfun GM_GetDiskFreeSpace + Subfun GM_FS_Delete + Subfun GM_FS_CheckFile + Subfun GM_FS_GetCurrentDir + Subfun GM_FS_SetCurrentDir + Subfun GM_FS_CreateDir + Subfun GM_FS_RemoveDir + Subfun GM_FS_Rename + Subfun GM_FS_XDelete + Subfun GM_IsinkBacklightCtrl + Subfun GM_SocketCreate + Subfun GM_SocketConnect + Subfun GM_SocketRecv + Subfun GM_SocketClose + Subfun GM_SocketSend + Subfun GM_SocketRegisterCallBack + Subfun GM_GetLocalIP + Subfun ZG_SleepEnable + Subfun ZG_SleepDisable + Subfun GM_KpledLevelCtrl + Subfun GM_CreateKalTimer + Subfun GM_StartKalTimer + Subfun GM_StopKalTimer + Subfun GM_StartTimer + Subfun GM_StopTimer + Subfun GM_GetSignalValue + Subfun GM_GetLbsInfo + Subfun GM_I2cInit + Subfun GM_I2cConfig + Subfun GM_I2cWriteByte + Subfun GM_I2cReadBytes + Subfun GM_I2cGetMode + Subfun GM_I2cSetMode + Subfun GM_AdcRead + Subfun GM_EintRegister + Subfun GM_EintPinInit + Subfun GM_EintSetPolarity + Subfun GM_SysUsdelay + Subfun GM_SysMsdelay + Subfun GM_GetImsi + Subfun GM_GetIccid + Subfun GM_GetPdpStatus + Subfun GM_GetGsmStatus + Subfun GM_ImageZiLimit + Subfun GM_ImageDummyBase + Subfun GM_GetBarcode + Subfun GM_IsGprsAutoOn + Subfun GM_GetTcpStatus + Subfun GM_GetLibStatus + Subfun GM_SetUartFunc + Subfun GM_GetHostByName + Subfun GM_GetCregStatus + Subfun GM_GetBearerStatus + Subfun GM_AccountIdClose + Subfun GM_GetFakeCellFeature + Subfun GM_ApnConfig + Subfun GM_ReadWriteNvram + Subfun GM_GetNewAttachStatus + Subfun GM_IsWdtPwrOn + Subfun GM_DnsParserCallback + Subfun GM_GetSetFlightMode + Subfun GM_CloseBearerAppId + Subfun GM_GetApnMatch + Subfun GM_DeleteApn + Subfun GM_SoftwareWdtCounterEnable + Subfun GM_SetSoftwareWdtCounter + Subfun GM_GetSoftwareWdtCounter + Subfun GM_SetSwLogicCounterEnable + Subfun GM_SetSwLogicCounter + Subfun GM_SetSwLogicCounterMax + Subfun GM_GetSwLogicCounter + Subfun GM_GetSwLogicCounterMax + Subfun GM_SpiReadData + Subfun GM_SpiWriteData + Subfun GM_SpiFlashReadID + Subfun GM_SpiPinInit + Subfun GM_StopRecord + Subfun GM_StartRecord + Subfun GM_RecordRegister + Subfun GM_GetChrStatus + Subfun GM_PowerKeyRegister + Subfun GM_ConvertIpAddr + Subfun GM_ReadNvramLid + Subfun GM_ChrCurrentConfig + Subfun GM_ChrCurrentGet + Subfun GM_AutoApnCheck + Subfun GM_Set_Mic_Volume + Subfun GM_log10 + Subfun GM_log + Subfun GM_sqrt + Subfun GM_fabs + Subfun wlan_init + Subfun wlan_deinit + Subfun wlan_scan + Subfun GM_MemoryRealloc + Subfun GM_GetTime + Subfun GM_GetChipRID + Subfun GM_Func19 + Subfun GM_Func20 + Subfun GM_Func21 + Subfun GM_Func22 + Subfun GM_Func23 + Subfun GM_Func24 + Subfun GM_Func25 + Subfun GM_Func26 + Subfun GM_Func27 + Subfun GM_Func28 + Subfun GM_Func29 + Subfun GM_Func30 + Subfun GM_Func31 + Subfun GM_Func32 + Subfun GM_Func33 + Subfun GM_Func34 + Subfun GM_Func35 + Subfun GM_Func36 + Subfun GM_Func37 + Subfun GM_Func38 + Subfun GM_Func39 + Subfun GM_Func40 + Subfun GM_Func41 + Subfun GM_Func42 + Subfun GM_Func43 + Subfun GM_Func44 + Subfun GM_Func45 + Subfun GM_Func46 + Subfun GM_Func47 + Subfun GM_Func48 + Subfun GM_Func49 + Subfun GM_Func50 + Subfun GM_CallbackFunc1 + Subfun GM_CallbackFunc2 + Subfun GM_CallbackFunc3 + Subfun GM_CallbackFunc4 + Subfun GM_CallbackFunc5 + Subfun GM_CallbackFunc6 + Subfun GM_CallbackFunc7 + Subfun GM_CallbackFunc8 + Subfun GM_CallbackFunc9 + Subfun GM_CallbackFunc10 + Subfun GM_CallbackFunc11 + Subfun GM_CallbackFunc12 + Subfun GM_CallbackFunc13 + Subfun GM_CallbackFunc14 + Subfun GM_CallbackFunc15 + Subfun GM_CallbackFunc16 + Subfun GM_CallbackFunc17 + Subfun GM_CallbackFunc18 + Subfun GM_CallbackFunc19 + Subfun GM_CallbackFunc20 + Subfun GM_CallbackFunc21 + Subfun GM_CallbackFunc22 + Subfun GM_CallbackFunc23 + Subfun GM_CallbackFunc24 + Subfun GM_CallbackFunc25 + Subfun GM_CallbackFunc26 + Subfun GM_CallbackFunc27 + Subfun GM_CallbackFunc28 + Subfun GM_CallbackFunc29 + Subfun GM_CallbackFunc30 + Subfun GM_CallbackFunc31 + Subfun GM_CallbackFunc32 + Subfun GM_CallbackFunc33 + Subfun GM_CallbackFunc34 + Subfun GM_CallbackFunc35 + Subfun GM_CallbackFunc36 + Subfun GM_CallbackFunc37 + Subfun GM_CallbackFunc38 + Subfun GM_CallbackFunc39 + Subfun GM_CallbackFunc40 + Subfun GM_CallbackFunc41 + Subfun GM_CallbackFunc42 + Subfun GM_CallbackFunc43 + Subfun GM_CallbackFunc44 + Subfun GM_CallbackFunc45 + Subfun GM_CallbackFunc46 + Subfun GM_CallbackFunc47 + Subfun GM_CallbackFunc48 + Subfun GM_CallbackFunc49 + Subfun GM_CallbackFunc50 + +;--------------------------------------------------------- +; adding new api under this line +; for ex: Subfun xxxxxxx + +;--------------------------------------------------------- + + EXPORT TK_dll_set_sb + + +TK_dll_set_sb + STMDB SP!, {R1, LR} + MOV R1, SB + MOV SB, R0 + MOV R0, R1 + LDMIA SP!, {R1, PC} + END diff --git a/lib/app_start.sym b/lib/app_start.sym new file mode 100644 index 0000000..3eb7c33 --- /dev/null +++ b/lib/app_start.sym @@ -0,0 +1,246 @@ +## ARM Linker, ADS1.2 [Build 842]: Last Updated: Wed Oct 29 16:18:30 2014 +0x00000000 A GM_Trace +0x00000001 A GM_ReleaseBuild +0x00000002 A GM_ReleaseBranch +0x00000003 A GM_ReleaseHwVer +0x00000004 A GM_ReleaseVerno +0x00000005 A GM_BuildDateTime +0x00000006 A GM_atoi +0x00000007 A GM_atof +0x00000008 A GM_memset +0x00000009 A GM_memcpy +0x0000000A A GM_memcmp +0x0000000B A GM_memmove +0x0000000C A GM_strcpy +0x0000000D A GM_strncpy +0x0000000E A GM_strcat +0x0000000F A GM_strncat +0x00000010 A GM_strcmp +0x00000011 A GM_strncmp +0x00000012 A GM_strchr +0x00000013 A GM_strlen +0x00000014 A GM_strstr +0x00000015 A GM_sprintf +0x00000016 A GM_snprintf +0x00000017 A GM_vsprintf +0x00000018 A GM_sscanf +0x00000019 A GM_GpioInit +0x0000001A A GM_GetGpioMode +0x0000001B A GM_GpioSetLevel +0x0000001C A GM_GpioGetLevel +0x0000001D A GM_GpioSetDirection +0x0000001E A GM_GpioGetDirection +0x0000001F A GM_GpioSetPullSelection +0x00000020 A GM_RegisterCallBack +0x00000021 A GM_UartOpen +0x00000022 A GM_UartClose +0x00000023 A GM_UartWrite +0x00000024 A GM_UartRead +0x00000025 A GM_UartClrRxBuffer +0x00000026 A GM_UartClrTxBuffer +0x00000027 A GM_CheckSimValid +0x00000028 A GM_GetImei +0x00000029 A GM_GetPlmn +0x0000002A A GM_GetServiceAvailability +0x0000002B A GM_SetLocalTime +0x0000002C A GM_GetLocalTime +0x0000002D A GM_SetUartTrace +0x0000002E A GM_CloseUartTrace +0x0000002F A GM_MemoryAlloc +0x00000030 A GM_MemoryFree +0x00000031 A GM_Ucs2ToAsc +0x00000032 A GM_AscToUcs2 +0x00000033 A GM_SendSMS +0x00000034 A GM_CallAnswer +0x00000035 A GM_CallHangUp +0x00000036 A GM_MakeCall +0x00000037 A GM_SystemReboot +0x00000038 A GM_SystemPowerOff +0x00000039 A GM_FS_Open +0x0000003A A GM_FS_Close +0x0000003B A GM_FS_Read +0x0000003C A GM_FS_Write +0x0000003D A GM_FS_Seek +0x0000003E A GM_FS_Commit +0x0000003F A GM_FS_GetFileSize +0x00000040 A GM_FS_GetFilePosition +0x00000041 A GM_GetDiskFreeSpace +0x00000042 A GM_FS_Delete +0x00000043 A GM_FS_CheckFile +0x00000044 A GM_FS_GetCurrentDir +0x00000045 A GM_FS_SetCurrentDir +0x00000046 A GM_FS_CreateDir +0x00000047 A GM_FS_RemoveDir +0x00000048 A GM_FS_Rename +0x00000049 A GM_FS_XDelete +0x0000004A A GM_IsinkBacklightCtrl +0x0000004B A GM_SocketCreate +0x0000004C A GM_SocketConnect +0x0000004D A GM_SocketRecv +0x0000004E A GM_SocketClose +0x0000004F A GM_SocketSend +0x00000050 A GM_SocketRegisterCallBack +0x00000051 A GM_GetLocalIP +0x00000052 A ZG_SleepEnable +0x00000053 A ZG_SleepDisable +0x00000054 A GM_KpledLevelCtrl +0x00000055 A GM_CreateKalTimer +0x00000056 A GM_StartKalTimer +0x00000057 A GM_StopKalTimer +0x00000058 A GM_StartTimer +0x00000059 A GM_StopTimer +0x0000005A A GM_GetSignalValue +0x0000005B A GM_GetLbsInfo +0x0000005C A GM_I2cInit +0x0000005D A GM_I2cConfig +0x0000005E A GM_I2cWriteByte +0x0000005F A GM_I2cReadBytes +0x00000060 A GM_I2cGetMode +0x00000061 A GM_I2cSetMode +0x00000062 A GM_AdcRead +0x00000063 A GM_EintRegister +0x00000064 A GM_EintPinInit +0x00000065 A GM_EintSetPolarity +0x00000066 A GM_SysUsdelay +0x00000067 A GM_SysMsdelay +0x00000068 A GM_GetImsi +0x00000069 A GM_GetIccid +0x0000006A A GM_GetPdpStatus +0x0000006B A GM_GetGsmStatus +0x0000006C A GM_ImageZiLimit +0x0000006D A GM_ImageDummyBase +0x0000006E A GM_GetBarcode +0x0000006F A GM_IsGprsAutoOn +0x00000070 A GM_GetTcpStatus +0x00000071 A GM_GetLibStatus +0x00000072 A GM_SetUartFunc +0x00000073 A GM_GetHostByName +0x00000074 A GM_GetCregStatus +0x00000075 A GM_GetBearerStatus +0x00000076 A GM_AccountIdClose +0x00000077 A GM_GetFakeCellFeature +0x00000078 A GM_ApnConfig +0x00000079 A GM_ReadWriteNvram +0x0000007A A GM_GetNewAttachStatus +0x0000007B A GM_IsWdtPwrOn +0x0000007C A GM_DnsParserCallback +0x0000007D A GM_GetSetFlightMode +0x0000007E A GM_CloseBearerAppId +0x0000007F A GM_GetApnMatch +0x00000080 A GM_DeleteApn +0x00000081 A GM_SoftwareWdtCounterEnable +0x00000082 A GM_SetSoftwareWdtCounter +0x00000083 A GM_GetSoftwareWdtCounter +0x00000084 A GM_SetSwLogicCounterEnable +0x00000085 A GM_SetSwLogicCounter +0x00000086 A GM_SetSwLogicCounterMax +0x00000087 A GM_GetSwLogicCounter +0x00000088 A GM_GetSwLogicCounterMax +0x00000089 A GM_SpiReadData +0x0000008A A GM_SpiWriteData +0x0000008B A GM_SpiFlashReadID +0x0000008C A GM_SpiPinInit +0x0000008D A GM_StopRecord +0x0000008E A GM_StartRecord +0x0000008F A GM_RecordRegister +0x00000090 A GM_GetChrStatus +0x00000091 A GM_PowerKeyRegister +0x00000092 A GM_ConvertIpAddr +0x00000093 A GM_ReadNvramLid +0x00000094 A GM_ChrCurrentConfig +0x00000095 A GM_ChrCurrentGet +0x00000096 A GM_AutoApnCheck +0x00000097 A GM_Set_Mic_Volume +0x00000098 A GM_log10 +0x00000099 A GM_log +0x0000009A A GM_sqrt +0x0000009B A GM_fabs +0x0000009C A wlan_init +0x0000009D A wlan_deinit +0x0000009E A wlan_scan +0x0000009F A GM_MemoryRealloc +0x000000A0 A GM_GetTime +0x000000A1 A GM_GetChipRID +0x000000A2 A GM_Func19 +0x000000A3 A GM_Func20 +0x000000A4 A GM_Func21 +0x000000A5 A GM_Func22 +0x000000A6 A GM_Func23 +0x000000A7 A GM_Func24 +0x000000A8 A GM_Func25 +0x000000A9 A GM_Func26 +0x000000AA A GM_Func27 +0x000000AB A GM_Func28 +0x000000AC A GM_Func29 +0x000000AD A GM_Func30 +0x000000AE A GM_Func31 +0x000000AF A GM_Func32 +0x000000B0 A GM_Func33 +0x000000B1 A GM_Func34 +0x000000B2 A GM_Func35 +0x000000B3 A GM_Func36 +0x000000B4 A GM_Func37 +0x000000B5 A GM_Func38 +0x000000B6 A GM_Func39 +0x000000B7 A GM_Func40 +0x000000B8 A GM_Func41 +0x000000B9 A GM_Func42 +0x000000BA A GM_Func43 +0x000000BB A GM_Func44 +0x000000BC A GM_Func45 +0x000000BD A GM_Func46 +0x000000BE A GM_Func47 +0x000000BF A GM_Func48 +0x000000C0 A GM_Func49 +0x000000C1 A GM_Func50 +0x000000C2 A GM_CallbackFunc1 +0x000000C3 A GM_CallbackFunc2 +0x000000C4 A GM_CallbackFunc3 +0x000000C5 A GM_CallbackFunc4 +0x000000C6 A GM_CallbackFunc5 +0x000000C7 A GM_CallbackFunc6 +0x000000C8 A GM_CallbackFunc7 +0x000000C9 A GM_CallbackFunc8 +0x000000CA A GM_CallbackFunc9 +0x000000CB A GM_CallbackFunc10 +0x000000CC A GM_CallbackFunc11 +0x000000CD A GM_CallbackFunc12 +0x000000CE A GM_CallbackFunc13 +0x000000CF A GM_CallbackFunc14 +0x000000D0 A GM_CallbackFunc15 +0x000000D1 A GM_CallbackFunc16 +0x000000D2 A GM_CallbackFunc17 +0x000000D3 A GM_CallbackFunc18 +0x000000D4 A GM_CallbackFunc19 +0x000000D5 A GM_CallbackFunc20 +0x000000D6 A GM_CallbackFunc21 +0x000000D7 A GM_CallbackFunc22 +0x000000D8 A GM_CallbackFunc23 +0x000000D9 A GM_CallbackFunc24 +0x000000DA A GM_CallbackFunc25 +0x000000DB A GM_CallbackFunc26 +0x000000DC A GM_CallbackFunc27 +0x000000DD A GM_CallbackFunc28 +0x000000DE A GM_CallbackFunc29 +0x000000DF A GM_CallbackFunc30 +0x000000E0 A GM_CallbackFunc31 +0x000000E1 A GM_CallbackFunc32 +0x000000E2 A GM_CallbackFunc33 +0x000000E3 A GM_CallbackFunc34 +0x000000E4 A GM_CallbackFunc35 +0x000000E5 A GM_CallbackFunc36 +0x000000E6 A GM_CallbackFunc37 +0x000000E7 A GM_CallbackFunc38 +0x000000E8 A GM_CallbackFunc39 +0x000000E9 A GM_CallbackFunc40 +0x000000EA A GM_CallbackFunc41 +0x000000EB A GM_CallbackFunc42 +0x000000EC A GM_CallbackFunc43 +0x000000ED A GM_CallbackFunc44 +0x000000EE A GM_CallbackFunc45 +0x000000EF A GM_CallbackFunc46 +0x000000F0 A GM_CallbackFunc47 +0x000000F1 A GM_CallbackFunc48 +0x000000F2 A GM_CallbackFunc49 +0x000000F3 A GM_CallbackFunc50 + diff --git a/make.exe b/make.exe new file mode 100644 index 0000000..230491d Binary files /dev/null and b/make.exe differ diff --git a/make_debug.bat b/make_debug.bat new file mode 100644 index 0000000..cd5327d --- /dev/null +++ b/make_debug.bat @@ -0,0 +1,16 @@ +@echo off + + +echo *********************************************************************** +echo ************************* start to build ****************************** +echo *********************************************************************** + +make.exe clean + +make.exe -f makefile DEBUG_SYMBOLS=1 APP_BUILD_TIME="%date:~,10% %time:~,8%" + +rd /s /q output + +copy build\GmAppMain.bin build\GmAppMain.ex + +perl filecreat.pl diff --git a/make_release.bat b/make_release.bat new file mode 100644 index 0000000..9e11126 --- /dev/null +++ b/make_release.bat @@ -0,0 +1,15 @@ +@echo off + +echo *********************************************************************** +echo ************************* start to build ****************************** +echo *********************************************************************** + +make.exe clean + +make.exe -f makefile DEBUG_SYMBOLS=0 APP_BUILD_TIME="%date:~,10% %time:~,8%" + +rd /s /q output + +copy build\GmAppMain.bin build\GmAppMain.ex + +perl filecreat.pl diff --git a/makefile b/makefile new file mode 100644 index 0000000..ef2e7a4 --- /dev/null +++ b/makefile @@ -0,0 +1,143 @@ +#****************************************************************************** +# Filename : Makefile +# Project : +# Language : +# Description : +# Edit History : +#****************************************************************************** + +#***************************************************************************** +# Target name +#***************************************************************************** +TARGET = build\GmAppMain + +#***************************************************************************** +# Link File Definitions +#***************************************************************************** +LINK_FILES = + +DEBUG_SYMBOLS = 1 +export DEBUG_SYMBOLS +#***************************************************************************** +# Source File Definitions +#***************************************************************************** +LIB_SRCS_ASM = app_start.s +include makefile_src.inc +include makefile.inc + +ifeq ($(DEBUG_SYMBOLS), 1) + GM_DEF += -D__GOOME_TRACE_DEBUG_ENABLE__=1 +else + GM_DEF += -D__GOOME_TRACE_DEBUG_ENABLE__=0 +endif + +export APP_BUILD_TIME + +GM_DEF += -DSW_APP_BUILD_DATE_TIME="\"$(APP_BUILD_TIME)"\" + +#***************************************************************************** +# Inclue platfrom information +#***************************************************************************** +include makefile_plat.inc + +PLATFORM_SYMBOL_FILE = app_start.sym +PLATFORM_HEADER_FILE = app_start.o + + +#***************************************************************************** +# Directory Definition +#***************************************************************************** +ALL_DIRS = $(SUB_DIRS) LIB + +#***************************************************************************** +# Depedency Library Definition +#***************************************************************************** +ALL_LIBS = + +#***************************************************************************** +# Depedency Library full path +#***************************************************************************** +ALL_LIB_FILES = $(addsuffix .lib, $(addprefix $(LIB_DIR)/,$(ALL_LIBS))) +ALL_LINK_LIB_FILES = $(ALL_LIB_FILES) + + + + +#***************************************************************************** +# Object creation +#***************************************************************************** + +default: prepare $(ALL_DIRS) $(ALL_LIBS) $(TARGET).axf + +$(TARGET).axf: $(ALL_OBJS) $(ALL_LIB_FILES) + @copy $(LIB_DIR)\app_start.sym $(OBJ_DIR)\app_start.sym + + + $(LINK) -o $@ $(LINK_FLAGS) $(TARGET).map -entry Service_Entry -first $(PLATFORM_HEADER_FILE)\(ServiceHeader\)\ + $(OBJ_DIR)/$(PLATFORM_SYMBOL_FILE) $(OBJ_DIR)/$(PLATFORM_HEADER_FILE) $(ALL_OBJS)\ + $(ALL_LINK_LIB_FILES) $(LIB_DIR)\app_main.lib + + $(BIN_TOOL) $(TARGET).axf -bin -o $(TARGET).bin + +prepare: + @if exist $(strip $(OBJ_DIR))\*.log \ + @del /f $(strip $(OBJ_DIR))\*.log + @echo ;Building Log > .\$(BUILDLOG) + +$(ALL_DIRS): + @$(MKDIR) $@ + + +$(ALL_LIBS): + @$(MAKE) -C prj/$@ + +all_tools: + @$(MAKE) -C $(TOOLS_DIR) + + +#***************************************************************************** +# Clean Rule @del build\* +#***************************************************************************** +.PHONY: clean +clean: + @del build\*.o + @del build\*.sym + @del build\*.ex + @del build\*.axf + @del build\*.bin + @del build\*.htm + @del build\*.map + @del build\*.log + @del output\*.bin + @del output\*.ex + +.PHONY: clean_sub +clean_sub: + for D in $(ALL_LIBS); do cd prj/$$D ; $(MAKE) clean;cd ../..;done + +.PHONY: clean_all +clean_all: + $(MAKE) clean + $(MAKE) clean_sub +# $(MAKE) -C $(COMMON_DIR) clean + + +# +# make / clean dependency list +# + +MAKEFILENAME = makefile +CFLAGSDEPEND = -MM $(C_FLAGS) # for make depend +DEPENDENT_START = \# DO NOT EDIT AFTER THIS LINE -- make depend will generate it. + +depend: + $(MAKE) -f $(MAKEFILENAME) clean_depend + $(ECHO) "$(DEPENDENT_START)" >> $(MAKEFILENAME) + $(CC) $(CFLAGSDEPEND) $(ALL_SRCS_C) | sed -e 's/^\(.*\)\.o/OBJ\/\1.o/g' >> $(MAKEFILENAME) + +clean_depend: + chmod u+w $(MAKEFILENAME) + (awk 'BEGIN{f=1}\ + /^$(DEPENDENT_START)/{f=0} \ + {if (f) print $0}'\ + < $(MAKEFILENAME) > .depend && mv .depend $(MAKEFILENAME)) || exit 1; diff --git a/makefile.inc b/makefile.inc new file mode 100644 index 0000000..8eb1cf4 --- /dev/null +++ b/makefile.inc @@ -0,0 +1,88 @@ +#****************************************************************************** +# Filename : Makefile + +#****************************************************************************** + + +#***************************************************************************** +# List of suffixes +#***************************************************************************** + +.SUFFIXES: +.SUFFIXES: .asm .c .o .lib .a + + +#***************************************************************************** +# Local Source File Directories +#***************************************************************************** + +INC_DIR = inc +SRC_DIR = src +OBJ_DIR = build +LIB_DIR = lib +SUB_DIRS = $(OBJ_DIR) +BUILDLOG = $(strip $(OBJ_DIR))\build.log +BIN_DIR = . + +#***************************************************************************** +# Include path define +#***************************************************************************** +C_INC = -I. -I$(INC_DIR) -I./$(INC_DIR)/goome_sdk_inc -I./$(INC_DIR)/C_H + +GM_DEF += -D__MTK__ + + +#***************************************************************************** +# C Compile option +#***************************************************************************** +PREPROC_FLAGS = -m -n -i +#C_FLAGS = -c -O2 -D__MTK__ --apcs /ropi/rwpi/interwork $(C_INC) -D_MAP_BROWSE_SUPPORT_ +C_FLAGS = -c -O2 ${GM_DEF} --apcs /ropi/rwpi/interwork $(C_INC) -D_MAP_BROWSE_SUPPORT_ + +#***************************************************************************** +# ASM Compile option +#***************************************************************************** +ASM_FLAGS = --32 -g --apcs /ropi/rwpi/interwork $(ASM_INC) + + +#***************************************************************************** +# LIB Compile option +#***************************************************************************** +LIB_FLAGS = -a + +#***************************************************************************** +# LINK Compile option +#***************************************************************************** +LINK_FLAGS = -xref -remove -ropi -ro-base 0x8000 -rwpi -rw-base 0x1000000 -map -callgraph -symbols -info sizes,totals,unused -list + + +MAKEFILE = makefile + + + +#***************************************************************************** +# Source File Definitions +#***************************************************************************** +LIB_OBJS_ASM = $(LIB_SRCS_ASM:.s=.o) +LIB_OBJS_C = $(LIB_SRCS_C:.c=.o) +Frame_OBJS_C := $(Frame_SRCS_DIR %.c,%.o,$(wildcard *.c)) +#***************************************************************************** +# Generate objects files full path +#***************************************************************************** +LIB_OBJS = $(addprefix $(OBJ_DIR)/,$(LIB_OBJS_ASM)) $(addprefix $(OBJ_DIR)/,$(LIB_OBJS_C)) +ALL_OBJS = $(addprefix $(OBJ_DIR)/,$(LIB_OBJS_ASM)) $(addprefix $(OBJ_DIR)/,$(LIB_OBJS_C)) +#***************************************************************************** +# Generate source files full path +#***************************************************************************** +ALL_SRCS_C = $(addprefix $(SRC_DIR)/,$(LIB_SRCS_C)) + +#***************************************************************************** +# Object creation +#***************************************************************************** + +$(OBJ_DIR)/%.o: $(LIB_DIR)/%.s + $(ASM) $(ASM_FLAGS) $< $(OBJ_DIR)/$*.o 2>>.\$(BUILDLOG) + +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c + $(CC) $(C_FLAGS) $< -o $(OBJ_DIR)/$*.o 2>>.\$(BUILDLOG) + diff --git a/makefile_plat.inc b/makefile_plat.inc new file mode 100644 index 0000000..0fd7535 --- /dev/null +++ b/makefile_plat.inc @@ -0,0 +1,29 @@ +#****************************************************************************** +# Filename : Makefile +# Project : General Project +# Language : GUN makefile +# Description : Created to define make platform +# Edit History : Created by goome at 2018-07-25 +#****************************************************************************** + +#****************************************************************************** +#PLATFORM +#****************************************************************************** +ARMTOOL_PATH=C:\Progra~1\ARM\RVCT +#***************************************************************************** +# Make file MACRO definitions +#***************************************************************************** + +DIR_ARM=$(strip $(ARMTOOL_PATH)) + +DIR_TOOL = $(DIR_ARM)\Programs\3.1\569\win_32-pentium +DIR_ARMLIB = $(DIR_ARM)\Data\3.1\569\lib +DIR_ARMINC = $(DIR_ARM)\Data\3.1\569\include\windows +DIR_TOOL := $(strip $(DIR_TOOL)) +CC32 = $(DIR_TOOL)\armcc.exe --arm +CC = $(DIR_TOOL)\armcc.exe --thumb +LINK = $(DIR_TOOL)\armlink.exe # Linker +ASM = $(DIR_TOOL)\armasm.exe # ARM assembler +AR = $(DIR_TOOL)\armar.exe # Library tool +BIN_TOOL = $(DIR_TOOL)\fromelf.exe # Binary tool +MAKE = make.exe diff --git a/makefile_src.inc b/makefile_src.inc new file mode 100644 index 0000000..0c19793 --- /dev/null +++ b/makefile_src.inc @@ -0,0 +1,35 @@ +LIB_SRCS_C = main.c \ + utility.c \ + led.c \ + system_state.c \ + json.c \ + applied_math.c \ + fifo.c \ + circular_queue.c \ + hard_ware.c \ + relay.c \ + watch_dog.c \ + gprs.c \ + socket.c \ + gsm.c \ + sms.c \ + uart.c \ + g_sensor.c \ + nmea_protocol.c \ + gps.c \ + log_service.c \ + gps_service.c \ + gps_save.c \ + agps_service.c \ + config_save.c \ + config_service.c \ + update_file.c \ + update_service.c \ + protocol.c \ + protocol_concox.c \ + protocol_goome.c \ + protocol_jt808.c \ + command.c \ + auto_test.c\ + bms.c \ + diff --git a/output/README.txt b/output/README.txt new file mode 100644 index 0000000..e69de29 diff --git a/release/README.txt b/release/README.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/agps_service.c b/src/agps_service.c new file mode 100644 index 0000000..6a6454b --- /dev/null +++ b/src/agps_service.c @@ -0,0 +1,1743 @@ +#include "agps_service.h" +#include "config_service.h" +#include "log_service.h" +#include "gm_stdlib.h" +#include "gm_gprs.h" +#include "utility.h" +#include "gsm.h" +#include "gm_memory.h" +#include "applied_math.h" +#include "gm_fs.h" +#include "gm_timer.h" +#include "gps_service.h" +#include "system_state.h" + +#define PROTOCOL_HEADER_AGPS 0x29 +#define PROTOCOL_TAIL_AGPS 0x0D +#define AGPS_MSG_REQ_LENTH 500 //由于udp受MTU限制,500比较安全 + +#define AGPS_MSG_PACKAGE_LENTH 21 +#define TWO_HOUR_SECONDS (3600*2) +#define SIX_HOUR_SECONDS (3600*6) +#define EPO_GPS_DATA_6HOURS_LENTH 2304 +#define AGPS_FILE_PATH L"Z:\\goome\\GmAgpsFile\0" +#define EPO_FILE_PATH L"Z:\\goome\\GmEpoFile.DAT\0" + +static SocketType s_agps_socket = {-1,"",SOCKET_STATUS_ERROR,}; +static u8 s_at6558_flag[] = {0x41,0x47,0x4E,0x53,0x53,0x20,0x64,0x61,0x74,0x61,0x20,0x66,0x72,0x6F,0x6D,0x20,0x43,0x41,0x53,0x49,0x43}; +static u8 s_techtotop_flag[] = {0x54, 0x65, 0x63, 0x68, 0x74, 0x6F, 0x74, 0x6F, 0x70, 0x20, 0x41, 0x2D, 0x47, 0x4E, 0x53, 0x53, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x0A}; + +typedef struct +{ + u8 required_agps; //是否gps模块申请了gps + u8 timing; //是否正在请求校时 + + // epo/agps 文件信息 + u32 data_len; // 消息包总大小 + u32 data_start; // 请求文件时,数据起始位置 +}SocketTypeAgpsExtend; +static SocketTypeAgpsExtend s_agps_socket_extend = {0,0,0,0}; + + +typedef struct +{ + u16 crc; // applied_math_calc_common_crc16 + u8 gps_dev_type; //GPSChipType + u8 leap_seconds; // 润秒数 + u32 file_flag; // 文件flag + u32 len; // pdata长度 + u32 start_time; //utc 开始时间 + float lng; //经度 + float lat; //纬度 + u32 last; // 此文件能管多久,一般是2小时, 服务器每半小时拿一次数据,如果数据中不带时间的话, 则取1.5小时 + u8 data[AGPS_MSG_REQ_LENTH*8]; //content. +}AgpsFileExtend; + +static AgpsFileExtend s_agps_file_extend = {0,0,0,0,0,0,0.0,0.0,0, }; +static AgpsFileExtend s_agps_file_inuse = {0,0,0,0,0,0,0.0,0.0,0, }; + +#define AGPS_FILE_EXTEND_HEAD_SIZE (sizeof(AgpsFileExtend) - (AGPS_MSG_REQ_LENTH*8)) + +static GM_ERRCODE agps_service_transfer_status(u8 new_status); +static void agps_service_init_proc(void); +static void agps_service_connecting_proc(void); +static void agps_service_work_proc(void); +static void agps_service_data_finish_proc(void); +static void agps_service_close(void); + +static void agps_msg_send_timing(void); +static void agps_msg_send_get_file(u16 data_len); +static void agps_msg_receive(SocketType *socket); + +static void agps_msg_pack_head(u8 *pdata, u16 *idx, u16 len); +static void agps_msg_pack_timing(u8 *pdata, u16 *idx, u16 len); +static void agps_msg_pack_id_len(u8 *pdata, u8 id, u16 len); +static void agps_msg_pack_get_file(u8 *pdata, u16 *idx, u16 len,u16 data_len); + + +static void agps_msg_parse(u8 *pdata, u16 len); +static void agps_msg_parse_timing_ack(u8 *pdata, u16 len); +static void agps_msg_parse_epo_ack(u8 *pdata, u16 len); +static void agps_msg_parse_taidou_ack(u8 *pdata, u16 len); +static void agps_msg_parse_zkw_ack(u8 *pdata, u16 len); + + +static u8 agps_data_check_item_num(u8 *pdata, u16 len); +static u8 goome_agps_at6558_check_item_num(u8 *pdata, u16 len); +static void agps_write_data_file(const U16 * file_name) ; +static void agps_read_data_file(const U16 * file_name) ; +static void agps_service_check_and_read_file(void); +static bool agps_service_write_to_gps(void); +static void agps_service_reset(void); + +static GM_ERRCODE agps_service_transfer_status(u8 new_status) +{ + u8 old_status = (u8)s_agps_socket.status; + GM_ERRCODE ret = GM_PARAM_ERROR; + switch(s_agps_socket.status) + { + case SOCKET_STATUS_INIT: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_GET_HOST: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + break; + case SOCKET_STATUS_CONNECTING: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_CONNECTING: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_WORK: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_DATA_FINISH: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_ERROR: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + default: + break; + } + + + if(GM_SUCCESS == ret) + { + s_agps_socket.status = new_status; + s_agps_socket.status_fail_count = 0; + LOG(INFO,"clock(%d) agps_service_transfer_status from %s to %s success", util_clock(), + gm_socket_status_string((SocketStatus)old_status), gm_socket_status_string((SocketStatus)new_status)); + } + else + { + LOG(INFO,"clock(%d) agps_service_transfer_status from %s to %s failed", util_clock(), + gm_socket_status_string((SocketStatus)old_status), gm_socket_status_string((SocketStatus)new_status)); + } + + return ret; + +} + + +GM_ERRCODE agps_service_create(bool first_create) +{ + u8 addr[2*GOOME_DNS_MAX_LENTH+1]; + u8 IP[4]; + u32 port = 0; + u8 idx = 0; + + if(!first_create) + { + if(s_agps_socket.fifo.base_addr) + { + return GM_SUCCESS; + } + } + + s_agps_socket.access_id = SOCKET_INDEX_AGPS; + gm_socket_init(&s_agps_socket); + + GM_memset(addr, 0x00, sizeof(addr)); + idx = GM_sscanf((const char *)config_service_get_pointer(CFG_AGPSSERVERADDR), "%[^:]:%d", addr, &port); + if (idx != 2) + { + LOG(WARN,"clock(%d) agps_service_create assert(idx(%d) ==2) failed.", util_clock(),idx); + return GM_PARAM_ERROR; + } + + if(GM_SUCCESS != GM_ConvertIpAddr(addr, IP)) + { + if(util_is_valid_dns(addr, GM_strlen((const char *)addr))) + { + gm_socket_set_addr(&s_agps_socket, addr, GM_strlen((const char *)addr), port, STREAM_TYPE_DGRAM); + system_state_get_ip_cache(SOCKET_INDEX_AGPS, IP); + gm_socket_set_ip_port(&s_agps_socket, IP, port, STREAM_TYPE_DGRAM); + } + else + { + LOG(WARN,"clock(%d) agps_service_create assert(dns(%s)) failed.", util_clock(), addr); + return GM_PARAM_ERROR; + } + } + else + { + gm_socket_set_ip_port(&s_agps_socket, IP, port, STREAM_TYPE_DGRAM); + } + + + LOG(INFO,"clock(%d) agps_service_create access_id(%d) fifo(%p).", util_clock(), s_agps_socket.access_id, &s_agps_socket.fifo); + + GM_memset(&s_agps_file_extend, 0, sizeof(s_agps_file_extend)); + GM_memset(&s_agps_file_inuse, 0, sizeof(s_agps_file_inuse)); + return GM_SUCCESS; +} + +GM_ERRCODE agps_service_destroy(void) +{ + if(SOCKET_STATUS_ERROR == s_agps_socket.status) + { + return GM_SUCCESS; + } + + agps_service_close(); + + //agps socket only reconnect, not recreated. + //fifo_delete(&s_agps_socket.fifo); + + agps_service_transfer_status(SOCKET_STATUS_ERROR); + return GM_SUCCESS; +} + +static void agps_service_close(void) +{ + if(s_agps_socket.id >=0) + { + GM_SocketClose(s_agps_socket.id); + s_agps_socket.id=-1; + } +} + +GM_ERRCODE agps_service_timer_proc(void) +{ + if(!s_agps_socket.fifo.base_addr) + { + return GM_SUCCESS; + } + + switch(s_agps_socket.status) + { + case SOCKET_STATUS_INIT: + agps_service_init_proc(); + break; + case SOCKET_STATUS_CONNECTING: + agps_service_connecting_proc(); + break; + case SOCKET_STATUS_WORK: + agps_service_work_proc(); + break; + case SOCKET_STATUS_DATA_FINISH: + agps_service_data_finish_proc(); + break; + case SOCKET_STATUS_ERROR: + agps_service_data_finish_proc(); + break; + default: + LOG(WARN,"clock(%d) agps_service_timer_proc assert(s_agps_socket.status(%d)) unknown.", util_clock(),s_agps_socket.status); + return GM_ERROR_STATUS; + } + + return GM_SUCCESS; +} + + +static bool agps_service_write_to_gps(void) +{ + agps_service_check_and_read_file(); + + //由于agps文件是多管半小时的, 所以提前拿文件没必要, 多加180是防止本地时间不太准 + if((s_agps_file_inuse.start_time <= (util_get_utc_time()+180)) && + (s_agps_file_inuse.start_time+s_agps_file_inuse.last ) > util_get_utc_time() ) + { + //数据有效 + LOG(INFO,"clock(%d) agps_service_write_to_gps ok, start(%d) last(%d) until(%d).", + util_clock(),s_agps_file_inuse.start_time,s_agps_file_inuse.last, util_get_utc_time()); + if(s_agps_socket_extend.required_agps && (!gps_is_fixed())) + { + agps_service_require_to_gps(AGPS_TO_GPS_LNGLAT_TIME,false); + } + return true; + } + LOG(DEBUG,"clock(%d) agps_service_write_to_gps file failed, start(%d) last(%d) until(%d).", + util_clock(),s_agps_file_inuse.start_time,s_agps_file_inuse.last,util_get_utc_time()); + + return false; +} + +static void agps_service_init_proc(void) +{ + GM_ERRCODE ret; + gm_cell_info_struct lbs; + bool write_agps_succ = false; + u8 IP[4]; + + if(gps_is_fixed()) + { + write_agps_succ = agps_service_write_to_gps(); //here will read file + { + //report logs + JsonObject* p_json_log = json_create(); + json_add_string(p_json_log,"event","read_agps1"); + json_add_int(p_json_log,"start",s_agps_file_inuse.start_time); + json_add_int(p_json_log,"last",s_agps_file_inuse.last); + json_add_int(p_json_log,"ret",write_agps_succ?1:0); + log_service_upload(INFO, p_json_log); + } + + //由于agps文件是多管半小时的, 所以提前拿文件没必要, 多加180是防止本地时间不太准 + if((s_agps_file_inuse.start_time <= (util_get_utc_time()+180)) && + (s_agps_file_inuse.start_time+s_agps_file_inuse.last ) > util_get_utc_time() ) + { + LOG(INFO,"clock(%d) agps_service_init_proc fix and agps data is ok.", util_clock()); + // 数据有效,则等下次再获取 + agps_service_close_for_reconnect(); + return; + } + } + else + { + //得到lbs信息后启动校时 + ret = gsm_get_cell_info(&lbs); + if (GM_SUCCESS!=ret || lbs.nbr_cell_num ==0) + { + return; + } + } + + + gm_socket_get_host_by_name_trigger(&s_agps_socket); + system_state_get_ip_cache(SOCKET_INDEX_AGPS, IP); + if(GM_SUCCESS == gm_is_valid_ip(IP)) + { + GM_memcpy( s_agps_socket.ip , IP, sizeof(IP)); + agps_service_transfer_status(SOCKET_STATUS_CONNECTING); + if(GM_SUCCESS == gm_socket_connect(&s_agps_socket)) + { + } + // else do nothing . connecting_proc will deal. + } + else if((!s_agps_socket.excuted_get_host) && (GM_SUCCESS == gm_is_valid_ip(s_agps_socket.ip))) + { + agps_service_transfer_status(SOCKET_STATUS_CONNECTING); + if(GM_SUCCESS == gm_socket_connect(&s_agps_socket)) + { + } + // else do nothing . connecting_proc will deal. + } +} + +void agps_service_connection_failed(void) +{ + agps_service_close(); + + if(s_agps_socket.status_fail_count >= MAX_CONNECT_REPEAT) + { + // if excuted get_host transfer to error statu, else get_host. + if(s_agps_socket.excuted_get_host || (s_agps_socket.addr[0] == 0)) + { + agps_service_transfer_status(SOCKET_STATUS_DATA_FINISH); + } + else + { + agps_service_transfer_status(SOCKET_STATUS_INIT); + } + } + // else do nothing . wait connecting proc to deal. +} + + + +static void agps_service_connecting_proc(void) +{ + u32 current_time = util_clock(); + + if((current_time - s_agps_socket.send_time) > CONNECT_TIME_OUT) + { + s_agps_socket.status_fail_count ++; + agps_service_connection_failed(); + + if(s_agps_socket.status == SOCKET_STATUS_CONNECTING && + s_agps_socket.status_fail_count < MAX_CONNECT_REPEAT) + { + if(GM_SUCCESS == gm_socket_connect(&s_agps_socket)) + { + //do nothing. wait callback + } + } + + } +} + + + +void agps_service_connection_ok(void) +{ + agps_service_transfer_status(SOCKET_STATUS_WORK); + agps_msg_send_timing(); +} + +void agps_service_close_for_reconnect(void) +{ + agps_service_close(); + agps_service_transfer_status(SOCKET_STATUS_DATA_FINISH); +} + +static void agps_service_work_proc(void) +{ + u32 current_time = util_clock(); + if((current_time - s_agps_socket.send_time) >= MESSAGE_TIME_OUT) + { + if(s_agps_socket_extend.timing) + { + //发送请求阶段 + s_agps_socket.status_fail_count ++; + if(s_agps_socket.status_fail_count >= MAX_MESSAGE_REPEAT) + { + LOG(INFO,"clock(%d) agps_service_work_proc failed:%d", util_clock(), s_agps_socket.status_fail_count); + agps_service_close_for_reconnect(); + } + else + { + agps_msg_send_timing(); + } + } + else + { + //发送请求frame阶段 + s_agps_socket.status_fail_count ++; + if(s_agps_socket.status_fail_count >= MAX_MESSAGE_REPEAT) + { + LOG(INFO,"clock(%d) agps_service_work_proc failed:%d", util_clock(), s_agps_socket.status_fail_count); + agps_service_close_for_reconnect(); + } + else + { + agps_msg_send_get_file(AGPS_MSG_REQ_LENTH); + } + } + } + + agps_msg_receive(&s_agps_socket); + + return; +} + + +static void agps_service_data_finish_proc(void) +{ + u32 current_time = util_clock(); + static u32 last_execute_time = 0; + + //在已定位/或休眠状态下没必要去获取agps数据,等gps模块请求了再获取 + if((GM_GPS_OFF == gps_get_state()) || (GM_GPS_FIX_3D <= gps_get_state())) + { + s_agps_socket_extend.required_agps = 0; + } + + if(!s_agps_socket_extend.required_agps) + { + return; + } + + //由于agps文件是多管半小时的, 所以提前拿文件没必要, 多加180是防止本地时间不太准 + if((s_agps_file_inuse.start_time > (util_get_utc_time()+180)) || + (s_agps_file_inuse.start_time+s_agps_file_inuse.last ) < util_get_utc_time() ) + { + int gap = 3; + + // 距离上次取agps最少3 sec,以免不停循环取 + if((current_time - last_execute_time) >= gap) + { + last_execute_time = current_time; + LOG(DEBUG,"clock(%d) agps_service_data_finish_proc start(%d) + last(%d) < now gap(%d).", + util_clock(), s_agps_file_inuse.start_time, s_agps_file_inuse.last, gap); + s_agps_file_extend.file_flag = 0; + s_agps_socket_extend.data_len = 0; + s_agps_socket_extend.data_start = 1; + s_agps_socket_extend.timing = 0; + agps_service_transfer_status(SOCKET_STATUS_INIT); + } + } +} + + +static void agps_msg_send_timing(void) +{ + u8 buff[100]; + u16 len = sizeof(buff); + u16 idx = 0; //current place + + agps_msg_pack_head(buff, &idx, len); //9 bytes + agps_msg_pack_timing(buff, &idx, len); //72 bytes + if((idx + 2) > len) + { + LOG(WARN,"clock(%d) agps_msg_send_timing assert(len(%d)) failed.", util_clock(), len); + return; + } + agps_msg_pack_id_len(buff, AGPS_REQ_TIMING, idx); //2 bytes + len=idx+2; // 1byte checksum , 1byte 0xD + + if(GM_SUCCESS == gm_socket_send(&s_agps_socket, buff, len)) + { + s_agps_socket.send_time = util_clock(); + s_agps_socket_extend.timing = 1; + LOG(DEBUG,"clock(%d) agps_msg_send_timing msglen(%d)", util_clock(), len); + return; + } + else + { + agps_service_close_for_reconnect(); + } + return; +} + +static void agps_msg_pack_head(u8 *pdata, u16 *idx, u16 len) +{ + u8 imei[GM_IMEI_LEN + 1] = {0}; + GM_ERRCODE ret = GM_SUCCESS; + + if((*idx) + 9 > len) + { + LOG(WARN,"clock(%d) agps_msg_pack_head assert(len(%d)) failed.", util_clock(), len); + return; + } + + pdata[(*idx)++] = PROTOCOL_HEADER_AGPS; + pdata[(*idx)++] = PROTOCOL_HEADER_AGPS; + (*idx) = (*idx) + 3; // id 1 , len 2 + + if(GM_SUCCESS != (ret = gsm_get_imei(imei))) + { + LOG(INFO,"clock(%d) agps_msg_pack_head can not get imei, ret:%d.", util_clock(), ret); + } + + if (0 == GM_strlen((const char *)imei)) + { + GM_memset(imei, 0, sizeof(imei)); + } + + pdata[(*idx)++] = MERGEBCD(util_chr(imei[7]), util_chr(imei[8])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[9]), util_chr(imei[10])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[11]), util_chr(imei[12])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[13]), util_chr(imei[14])); + +} + + +static void agps_msg_pack_timing(u8 *pdata, u16 *idx, u16 len) +{ + u8 bcd_tim[6]; + ST_Time current_time; + u8 zone; + gm_cell_info_struct lbs; + u16 k = 0; + u16 cell_num=0; + u16 lbsidx=0; + GM_ERRCODE ret; + + GM_memset(&lbs,0, sizeof(lbs)); + + if(((*idx) + 34 + 38) > len) + { + LOG(WARN,"clock(%d) agps_msg_pack_timing assert(len(%d)) failed.", util_clock(), len); + return; + } + + + zone = config_service_get_zone(); + util_get_current_local_time(bcd_tim, ¤t_time, zone); + + // 占用6个字节 YMDHMS:年月日时分秒 + GM_memcpy(&pdata[(*idx)], bcd_tim, sizeof(bcd_tim)); + (*idx) += 6; + + // 纬度 由于每台车位置不同, 所以下面的位置数据没有意义 + pdata[(*idx)++] = 0x02; + pdata[(*idx)++] = 0x23; + pdata[(*idx)++] = 0x24; + pdata[(*idx)++] = 0x78; + + // 经度 + pdata[(*idx)++] = 0x11; + pdata[(*idx)++] = 0x35; + pdata[(*idx)++] = 0x70; + pdata[(*idx)++] = 0x84; + + // 速度 + pdata[(*idx)++] = 0x00; + pdata[(*idx)++] = 0x00; + + // 角度 + pdata[(*idx)++] = 0x01; + pdata[(*idx)++] = 0x80; + + GM_memset(&pdata[(*idx)], 0xFF, 16); + (*idx) += 16; + + //基站数据 + pdata[(*idx)++] = 0x00; + pdata[(*idx)++] = 0x24; + + pdata[(*idx)++] = 0x00; + pdata[(*idx)++] = 0xA9; + + + ret = gsm_get_cell_info(&lbs); + LOG(DEBUG,"clock(%d) agps_msg_pack_timing ret(%d) lbs(%d).", util_clock(), ret, lbs.nbr_cell_num); + if (lbs.nbr_cell_num > 5) + { + cell_num = 5; + } + else + { + cell_num = lbs.nbr_cell_num; + } + + // MCC(2B) + MNC(1B) + 基站数(1B) + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.mcc); // MCC + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.mcc); + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.mnc); // MNC + pdata[(*idx)++] = cell_num+1; // 基站数 + + + // 主服务基站信息 LAC(2B)+CI(3B)+RSSI(1B) + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.lac); // LAC + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.lac); + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.ci); // CELL ID + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.ci); + pdata[(*idx)++] = lbs.serv_info.rxlev;// 信号强度 RSSI + + + // 剩余4个基站 LAC(2B)+CI(3B)+RSSI(1B) + lbsidx = (*idx); + for (k=0; k len) + { + LOG(WARN,"clock(%d) update_msg_pack_id_len assert(len(%d)) failed.", util_clock(), len); + return; + } + + //len now is pointing checksum byte + total = 2 + len; + len_send = total - 5; + + pdata[2] = id; //id 1byte + pdata[3] = BHIGH_BYTE(len_send); //length 2bytes + pdata[4] = BLOW_BYTE(len_send); + + //from head to end_of_data + for(idx = 0; idx < len; ++ idx) + { + checksum ^= pdata[idx]; + } + + pdata[len] = checksum; // xor value. 1byte + + pdata[total - 1] = PROTOCOL_TAIL_AGPS; //end +} + + +static void agps_msg_receive(SocketType *socket) +{ + u8 head[7]; + u32 len = sizeof(head); + u16 msg_len; + u8 *pdata; + static u32 packet_error_start = 0; + + /* + update协议 最短7 + 信息头(0x68 0x68) 2 协议号1 包长度2(下一字节至data_end) check2 0xD + */ + + if(GM_SUCCESS != fifo_peek(&socket->fifo, head, len)) + { + // no msg + return; + } + + msg_len = MKWORD(head[3], head[4]); + msg_len = msg_len + 5; + + if(msg_len > MAX_GPRS_MESSAGE_LEN) + { + LOG(WARN,"clock(%d) agps_msg_receive assert(msg_len(%d)) failed.",util_clock(), msg_len); + //clear fifo and restart socket. + fifo_reset(&socket->fifo); + gm_socket_close_for_reconnect(socket); + return; + } + + pdata = GM_MemoryAlloc(msg_len); + if(pdata == NULL) + { + LOG(WARN,"clock(%d) agps_msg_receive alloc buf failed. len:%d", util_clock(), msg_len); + + //clear fifo and restart socket. + fifo_reset(&socket->fifo); + gm_socket_close_for_reconnect(socket); + return; + } + + if(GM_SUCCESS != fifo_peek(&socket->fifo, pdata, msg_len)) + { + // GM_EMPTY_BUF + GM_MemoryFree(pdata); + + if(packet_error_start == 0) + { + LOG(DEBUG,"clock(%d) agps_msg_receive get msg failed. len:%d", util_clock(), msg_len); + log_service_print_hex((const char*)head, sizeof(head)); + packet_error_start = util_clock(); + } + else + { + if((util_clock() - packet_error_start) > MAX_GPRS_PART_MESSAGE_TIMEOUT) + { + LOG(WARN,"clock(%d) agps_msg_receive MAX_GPRS_PART_MESSAGE_TIMEOUT.",util_clock()); + //clear fifo and restart socket. + fifo_reset(&socket->fifo); + gm_socket_close_for_reconnect(socket); + packet_error_start = 0; + } + } + return; + } + fifo_pop_len(&socket->fifo, msg_len); + + LOG(DEBUG,"clock(%d) agps_msg_receive msg len(%d)", util_clock(), msg_len); + + + agps_msg_parse(pdata, msg_len); + GM_MemoryFree(pdata); +} + + + +static void agps_msg_parse(u8 *pdata, u16 len) +{ + u8 checksum = 0; + u16 idx = 0; + + if(PROTOCOL_HEADER_AGPS != pdata[0] || PROTOCOL_HEADER_AGPS != pdata[1]) + { + LOG(WARN,"clock(%d) agps_msg_parse assert(header(%02x %02x)) failed.", util_clock(), pdata[0],pdata[1]); + return; + } + if(PROTOCOL_TAIL_AGPS != pdata[len-1] ) + { + LOG(WARN,"clock(%d) update_msg_parse assert(tail(%d)) failed.", util_clock(), pdata[len-1] ); + return; + } + + for(idx = 0; idx < (len-2); ++idx) + { + checksum ^= pdata[idx]; + } + + if(checksum != pdata[len-2]) + { + LOG(WARN,"clock(%d) update_msg_parse assert(xor(%d != %d)) failed.", util_clock(), checksum, pdata[len-2]); + return; + } + + //协议号 + switch(pdata[2]) + { + case AGPS_ACK_TIMING: + agps_msg_parse_timing_ack(pdata,len); + break; + case AGPS_EPO_ACK: + agps_msg_parse_epo_ack(pdata,len); + break; + case AGPS_TAIDOU_ACK: + agps_msg_parse_taidou_ack(pdata,len); + break; + case AGPS_ZKW_ACK: + agps_msg_parse_zkw_ack(pdata,len); + break; + default: + LOG(WARN,"clock(%d) agps_msg_parse assert(msgid(%d)) failed.", util_clock(), pdata[2]); + break; + } + return; +} + + +static void agps_msg_parse_timing_ack(u8 *pdata, u16 len) +{ + ST_Time mt; + struct tm tm_t; + time_t t; + bool write_agps_succ = false; + + if(! s_agps_socket_extend.timing) + { + LOG(WARN,"clock(%d) agps_msg_parse_timing_ack assert(timing) failed.", util_clock()); + return; + } + + if (len < 24) + { + LOG(WARN,"clock(%d) agps_msg_parse_timing_ack assert(len(%d)) failed.", util_clock(), len); + return; + } + + //服务器时间为东八区时间 + mt.year = 2000 + BCD2HEX(pdata[9]); + mt.month = BCD2HEX(pdata[10]); + mt.day = BCD2HEX(pdata[11]); + + mt.hour = BCD2HEX(pdata[12]); + mt.minute = BCD2HEX(pdata[13]); + mt.second= BCD2HEX(pdata[14]); + mt.timezone = 0; + LOG(DEBUG,"clock(%d) agps_msg_parse_timing_ack GM_SetLocalTime(%d-%02d-%02d %02d:%02d:%02d)).", + util_clock(), mt.year,mt.month,mt.day,mt.hour,mt.minute,mt.second); + + util_mtktime_to_tm(&mt, &tm_t); + t = util_mktime(&tm_t); + if(t == (time_t)-1) + { + LOG(INFO,"clock(%d) agps_msg_parse_timing_ack GM_SetLocalTime(%d-%02d-%02d %02d:%02d:%02d)) failed.", + util_clock(), mt.year,mt.month,mt.day,mt.hour,mt.minute,mt.second); + return; + } + + t -= 28800; //服务器是东八区 8*60*60 + tm_t = *util_localtime(&t); + util_tm_to_mtktime(&tm_t, &mt); + + + //如果agps文件中带有润秒数,则会覆盖这里的赋值 + s_agps_file_extend.leap_seconds = pdata[15]; + + //有线设备只有休眠(静止超过5分钟才关gps) + if (!gps_is_fixed()) + { + LOG(INFO,"clock(%d) agps_msg_parse_timing_ack leap(%d) time(%d-%02d-%02d %02d:%02d:%02d)).", + util_clock(), s_agps_file_extend.leap_seconds,mt.year,mt.month,mt.day,mt.hour,mt.minute,mt.second); + GM_SetLocalTime(&mt); + } + else + { + LOG(INFO,"clock(%d) agps_msg_parse_timing_ack leap(%d) ignore(%d-%02d-%02d %02d:%02d:%02d)).", + util_clock(), s_agps_file_extend.leap_seconds,mt.year,mt.month,mt.day,mt.hour,mt.minute,mt.second); + } + + + //经纬度用于1分钟后不能定位时上报基站数据 + s_agps_file_extend.lat = (BCD_LOW(pdata[16])*1000000 +BCD_HIGH(pdata[17])*100000 + (BCD_LOW(pdata[17])*10000 + + BCD_HIGH(pdata[18])*1000 + BCD_LOW(pdata[18])*100 + BCD_HIGH(pdata[19])*10 + BCD_LOW(pdata[19]))*100.0f/60.0f); + s_agps_file_extend.lat /= 100000.0f; + s_agps_file_extend.lat =(pdata[16] & 0x80) ? (-s_agps_file_extend.lat) : (s_agps_file_extend.lat); + s_agps_file_extend.lng = (BCD_HIGH(pdata[20] & 0x7F)*10000000 + BCD_LOW(pdata[20])*1000000 + + BCD_HIGH(pdata[21])*100000 + (BCD_LOW(pdata[21])*10000 + BCD_HIGH(pdata[22])*1000 + + BCD_LOW(pdata[22])*100 + BCD_HIGH(pdata[23])*10 + BCD_LOW(pdata[23]))*100.0f/60.0f); + s_agps_file_extend.lng /= 100000.0f; + s_agps_file_extend.lng = (pdata[20] & 0x80) ? (-s_agps_file_extend.lng) : (s_agps_file_extend.lng); + + + s_agps_socket_extend.timing = 0; + s_agps_file_extend.file_flag = 0; + s_agps_socket_extend.data_len = 0; + s_agps_socket_extend.data_start = 1; + + //校时完,本地有文件的话,先用本地文件 + write_agps_succ = agps_service_write_to_gps(); + { + //report logs + JsonObject* p_json_log = json_create(); + json_add_string(p_json_log,"event","write_agps2"); + json_add_int(p_json_log,"start",s_agps_file_inuse.start_time); + json_add_int(p_json_log,"last",s_agps_file_inuse.last); + json_add_double(p_json_log,"lng",s_agps_file_inuse.lng); + json_add_double(p_json_log,"lat",s_agps_file_inuse.lat); + json_add_int(p_json_log,"ret",write_agps_succ?1:0); + log_service_upload(INFO, p_json_log); + } + + + //由于agps文件是多管半小时的, 所以提前拿文件没必要, 多加180是防止本地时间不太准 + if((s_agps_file_inuse.start_time <= (util_get_utc_time()+180)) && + (s_agps_file_inuse.start_time+s_agps_file_inuse.last ) > util_get_utc_time() ) + { + // 数据有效,则等下次再获取 + agps_service_close_for_reconnect(); + } + else + { + agps_msg_send_get_file(AGPS_MSG_REQ_LENTH); + } +} + + +static void agps_msg_send_get_file(u16 data_len) +{ + u8 buff[100]; + u16 len = sizeof(buff); + u16 idx = 0; //current place + u8 cmd = 0; + + switch(config_service_get_gps_type()) + { + case GM_GPS_TYPE_MTK_EPO: + cmd = AGPS_REQ_EPO; + break; + case GM_GPS_TYPE_TD_AGPS: + cmd = AGPS_REQ_TAIDOU; + break; + case GM_GPS_TYPE_AT_AGPS: + cmd = AGPS_REQ_ZKW; + break; + default: + LOG(WARN,"clock(%d) agps_msg_send_get_file assert(config_service_get_gps_type(%d) failed.",util_clock(),config_service_get_gps_type()); + return; + } + + agps_msg_pack_head(buff, &idx, len); //9 bytes + agps_msg_pack_get_file(buff, &idx, len,data_len); //6 + if((idx + 2) > len) + { + LOG(WARN,"clock(%d) agps_msg_send_get_file assert(len(%d)) failed.", util_clock(), len); + return; + } + agps_msg_pack_id_len(buff, cmd, idx); //2bytes + len=idx+2; // 1byte checksum , 1byte 0xD + + if(GM_SUCCESS == gm_socket_send(&s_agps_socket, buff, len)) + { + s_agps_socket.send_time = util_clock(); + LOG(DEBUG,"clock(%d) agps_msg_send_get_file cmd(%d) msglen(%d) start(%d) total(%d),get_len(%d)", + util_clock(), cmd, len, s_agps_socket_extend.data_start, s_agps_socket_extend.data_len, data_len); + return; + } + else + { + agps_service_close_for_reconnect(); + } + return; +} + +static void agps_msg_pack_get_file(u8 *pdata, u16 *idx, u16 len,u16 data_len) +{ + u32 data_start = 0; + + data_start = s_agps_socket_extend.data_start; + + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(data_start)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(data_start)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(data_start)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(data_start)); + + pdata[(*idx)++] = BHIGH_BYTE(data_len); + pdata[(*idx)++] = BLOW_BYTE(data_len); +} + + +static void agps_msg_parse_epo_ack(u8 *pdata, u16 len) +{ + u32 cur_epo_hour = 0; + u32 cur_rtc_hour = 0; + u32 file_flag; + u16 data_len = 0; + file_flag = MKDWORD(pdata[9], pdata[10], pdata[11], pdata[12]); + + if(s_agps_file_extend.file_flag == 0) + { + //首包 + cur_epo_hour = MKDWORD(0,pdata[21],pdata[20],pdata[19]); + + cur_rtc_hour = (util_get_utc_time() - SECONDS_FROM_UTC_TO_GPS_START)/3600; + LOG(DEBUG,"clock(%d) agps_msg_parse_epo_ack cur_rtc_hour(%d) cur_epo_hour(%d).", util_clock(), cur_rtc_hour, cur_epo_hour); + if(cur_rtc_hour < cur_epo_hour) + { + cur_rtc_hour = cur_epo_hour; //本地时间落后时直接取文件 + } + s_agps_socket_extend.data_start = ((cur_rtc_hour - cur_epo_hour) / 6 ) * EPO_GPS_DATA_6HOURS_LENTH + 1; + s_agps_file_extend.file_flag = file_flag; + s_agps_socket_extend.data_len = EPO_GPS_DATA_6HOURS_LENTH; + + //要先取整(/6) 再乘6 才是正确的开始时间 + s_agps_file_extend.start_time = (cur_rtc_hour/6)*6*3600 + SECONDS_FROM_UTC_TO_GPS_START; + s_agps_file_extend.last = SIX_HOUR_SECONDS; + s_agps_file_extend.gps_dev_type = (u8)GM_GPS_TYPE_MTK_EPO; + s_agps_file_extend.len = 0; + + LOG(DEBUG,"clock(%d) agps_msg_parse_epo_ack start(%d) total(%d).", util_clock(), s_agps_socket_extend.data_start, s_agps_socket_extend.data_len); + + data_len = s_agps_socket_extend.data_len - s_agps_file_extend.len; + data_len = data_len > AGPS_MSG_REQ_LENTH?AGPS_MSG_REQ_LENTH:data_len; + agps_msg_send_get_file(data_len); + } + else + { + if(file_flag != s_agps_file_extend.file_flag) + { + LOG(WARN,"clock(%d) agps_msg_parse_taidou_ack file_flag changed(%04x->%04x) current start %d.",util_clock(), + s_agps_file_extend.file_flag, file_flag, s_agps_socket_extend.data_start); + s_agps_file_extend.file_flag = 0; + s_agps_socket_extend.data_len = 0; + s_agps_socket_extend.data_start = 1; + agps_msg_send_get_file(AGPS_MSG_REQ_LENTH); + return; + } + + //后继包 + GM_memcpy(&s_agps_file_extend.data[s_agps_file_extend.len], &pdata[19], len - AGPS_MSG_PACKAGE_LENTH); + s_agps_file_extend.len += (len - AGPS_MSG_PACKAGE_LENTH); + s_agps_socket_extend.data_start += (len - AGPS_MSG_PACKAGE_LENTH); + + LOG(DEBUG,"clock(%d) agps_msg_parse_epo_ack file_len(%d) start(%d).", + util_clock(),s_agps_file_extend.len, s_agps_socket_extend.data_start); + + if(s_agps_file_extend.len < s_agps_socket_extend.data_len) + { + data_len = s_agps_socket_extend.data_len - s_agps_file_extend.len; + data_len = data_len > AGPS_MSG_REQ_LENTH?AGPS_MSG_REQ_LENTH:data_len; + agps_msg_send_get_file(data_len); + } + else + { + s_agps_file_extend.len = s_agps_socket_extend.data_len; + agps_write_data_file(EPO_FILE_PATH); + agps_service_close_for_reconnect(); + } + } +} + +static void agps_msg_parse_taidou_ack(u8 *pdata, u16 len) +{ + u16 idx = 0; + u8 item_num = 0; + u32 file_flag; + struct tm agps_time; + time_t agps_utc; + u16 data_len = 0; + + if (len <= AGPS_MSG_PACKAGE_LENTH) + { + LOG(WARN,"clock(%d) agps_msg_parse_taidou_ack assert(len(%d)) failed.", util_clock(), len); + return; + } + + file_flag = MKDWORD(pdata[9], pdata[10], pdata[11], pdata[12]); + + if(s_agps_socket_extend.data_start == 1) + { + if(0 == GM_memcmp(&pdata[19],s_techtotop_flag,sizeof(s_at6558_flag))) + { + //首包 + s_agps_file_extend.file_flag = file_flag; + s_agps_file_extend.gps_dev_type = (u8)GM_GPS_TYPE_TD_AGPS; + + idx = 19 + 36; + item_num = agps_data_check_item_num(&pdata[idx], len-idx); + if (4 == item_num) + { + s_agps_socket_extend.data_len = (pdata[idx] & 0x0F) * 1000 + (pdata[idx+1] & 0x0F) * 100 + (pdata[idx+2] & 0x0F) * 10 + (pdata[idx+3] & 0x0F) - 1; + } + if ((26 >= s_agps_socket_extend.data_len) || (4 != item_num)) + { + LOG(WARN,"clock(%d) agps_msg_parse_taidou_ack assert(data_len(%d,%d)) failed.", util_clock(), s_agps_socket_extend.data_len,item_num); + agps_service_close_for_reconnect(); + return; + } + idx += (item_num + 1); + if ((0x23 == pdata[idx]) && (0x3E == pdata[idx+1]) && (0x04 == pdata[idx+2]) && (0x02 == pdata[idx+3])) + { + // 泰斗的闰秒是BDT润秒+28 + s_agps_file_extend.leap_seconds = pdata[idx +6]; + agps_time.tm_year = MKWORD(pdata[idx +8], pdata[idx +7]) - 1900; + agps_time.tm_mon = pdata[idx +9] - 1; + agps_time.tm_mday = pdata[idx +10]; + agps_time.tm_hour = pdata[idx +11]; + agps_time.tm_min = pdata[idx +12]; + agps_time.tm_sec = pdata[idx +13]; + agps_time.tm_isdst = 0; + + agps_utc = util_mktime(&agps_time); + // agps_utc -= 28800; // 东8区 + if(agps_utc <= (time_t)0) + { + LOG(WARN,"clock(%d) agps_msg_parse_taidou_ack assert(agps_time(%d-%02d-%02d %02d:%02d:%02d)) failed.", + util_clock(),MKWORD(pdata[idx +8], pdata[idx +7]),pdata[idx +9],pdata[idx +10],pdata[idx +11],pdata[idx +12],pdata[idx +13]); + agps_service_close_for_reconnect(); + return; + } + + s_agps_file_extend.start_time = agps_utc; + s_agps_file_extend.last = TWO_HOUR_SECONDS; + idx += 26; + } + else + { + LOG(WARN,"clock(%d) agps_msg_parse_taidou_ack assert(agps_time) failed.",util_clock()); + agps_service_close_for_reconnect(); + return; + } + s_agps_socket_extend.data_len -= 26; + LOG(DEBUG,"clock(%d) agps_msg_parse_taidou_ack agps_time(%d-%02d-%02d %02d:%02d:%02d) leap(%d) file_total(%d).", + util_clock(),agps_time.tm_year + 1900, agps_time.tm_mon+1,agps_time.tm_mday,agps_time.tm_hour,agps_time.tm_min,agps_time.tm_sec, + s_agps_file_extend.leap_seconds, s_agps_socket_extend.data_len); + + if (len <= (idx + 2)) + { + LOG(WARN,"clock(%d) agps_msg_parse_taidou_ack assert(len(%d>%d)) failed.",util_clock(),len, (idx + 2)); + agps_service_close_for_reconnect(); + return; + } + + s_agps_file_extend.len = len - idx - 2; // idx include 19 bytes header + GM_memcpy(&s_agps_file_extend.data[0], &pdata[idx], s_agps_file_extend.len); + //data_start从开始 + s_agps_socket_extend.data_start = len - AGPS_MSG_PACKAGE_LENTH + 1; + LOG(DEBUG,"clock(%d) agps_msg_parse_taidou_ack from(%d) file_len(%d) start_time(%d).", + util_clock(),idx, s_agps_file_extend.len, s_agps_socket_extend.data_start); + + data_len = s_agps_socket_extend.data_len - s_agps_file_extend.len; + data_len = data_len > AGPS_MSG_REQ_LENTH?AGPS_MSG_REQ_LENTH:data_len; + agps_msg_send_get_file(data_len); + } + else + { + LOG(WARN,"clock(%d) agps_msg_parse_taidou_ack assert(s_techtotop_flag) failed.",util_clock()); + agps_service_close_for_reconnect(); + return; + } + } + else + { + if(file_flag != s_agps_file_extend.file_flag) + { + LOG(WARN,"clock(%d) agps_msg_parse_taidou_ack file_flag changed(%04x->%04x) current start %d.",util_clock(), + s_agps_file_extend.file_flag, file_flag, s_agps_socket_extend.data_start); + s_agps_file_extend.file_flag = 0; + s_agps_socket_extend.data_len = 0; + s_agps_socket_extend.data_start = 1; + agps_msg_send_get_file(AGPS_MSG_REQ_LENTH); + return; + } + + //后继包 + GM_memcpy(&s_agps_file_extend.data[s_agps_file_extend.len], &pdata[19], len - AGPS_MSG_PACKAGE_LENTH); + s_agps_file_extend.len += (len - AGPS_MSG_PACKAGE_LENTH); + s_agps_socket_extend.data_start += (len - AGPS_MSG_PACKAGE_LENTH); + + LOG(DEBUG,"clock(%d) agps_msg_parse_taidou_ack file_len(%d) start(%d).", + util_clock(),s_agps_file_extend.len, s_agps_socket_extend.data_start); + + if(s_agps_file_extend.len < s_agps_socket_extend.data_len) + { + data_len = s_agps_socket_extend.data_len - s_agps_file_extend.len; + data_len = data_len > AGPS_MSG_REQ_LENTH?AGPS_MSG_REQ_LENTH:data_len; + agps_msg_send_get_file(data_len); + } + else + { + s_agps_file_extend.len = s_agps_socket_extend.data_len; + agps_write_data_file(AGPS_FILE_PATH); + agps_service_close_for_reconnect(); + } + } +} + +static void agps_msg_parse_zkw_ack(u8 *pdata, u16 len) +{ + u16 idx = 0; + u8 item_num = 0; + u32 file_flag; + u16 data_len = 0; + file_flag = MKDWORD(pdata[9], pdata[10], pdata[11], pdata[12]); + + if(s_agps_socket_extend.data_start == 1) + { + if(0 == GM_memcmp(&pdata[19],s_at6558_flag,sizeof(s_at6558_flag))) + { + //首包 + s_agps_file_extend.file_flag = file_flag; + s_agps_file_extend.gps_dev_type = (u8)GM_GPS_TYPE_AT_AGPS; + + idx = 19 + 35; + item_num = goome_agps_at6558_check_item_num(&pdata[idx], len-idx); + if (4 == item_num) + { + s_agps_socket_extend.data_len = (pdata[idx] & 0x0F) * 1000 + (pdata[idx+1] & 0x0F) * 100 + (pdata[idx+2] & 0x0F) * 10 + (pdata[idx+3] & 0x0F); + } + else + { + LOG(WARN,"clock(%d) agps_msg_parse_zkw_ack assert(data_len(%d,%d)) failed.",util_clock(), s_agps_socket_extend.data_len,item_num); + agps_service_close_for_reconnect(); + return; + } + idx += (item_num+2); + item_num = goome_agps_at6558_check_item_num(&pdata[idx], len-idx); + idx += (item_num+2); //idx减header长度 是s_agps_file_extend.data数据应该开始的位置 + + s_agps_file_extend.start_time = file_flag; //取服务器时间, 据説四小时内有效,但这里只取2小时 + s_agps_file_extend.last = TWO_HOUR_SECONDS - 1800; //服务器每半小时获取一次数据,所以减半小时 + + s_agps_file_extend.len = len - idx - 2; // idx include 19 bytes header + GM_memcpy(&s_agps_file_extend.data[0], &pdata[idx], s_agps_file_extend.len); + //data_start从开始 + s_agps_socket_extend.data_start = len - AGPS_MSG_PACKAGE_LENTH + 1; + LOG(DEBUG,"clock(%d) agps_msg_parse_zkw_ack file_len(%d) start(%d).", + util_clock(),s_agps_file_extend.len, s_agps_socket_extend.data_start); + + data_len = s_agps_socket_extend.data_len - s_agps_file_extend.len; + data_len = data_len > AGPS_MSG_REQ_LENTH?AGPS_MSG_REQ_LENTH:data_len; + agps_msg_send_get_file(data_len); + } + else + { + LOG(WARN,"clock(%d) agps_msg_parse_zkw_ack assert(s_at6558_flag) failed.",util_clock()); + agps_service_close_for_reconnect(); + return; + } + } + else + { + if(file_flag != s_agps_file_extend.file_flag) + { + LOG(WARN,"clock(%d) agps_msg_parse_taidou_ack file_flag changed(%04x->%04x) current start %d.",util_clock(), + s_agps_file_extend.file_flag, file_flag, s_agps_socket_extend.data_start); + s_agps_file_extend.file_flag = 0; + s_agps_socket_extend.data_len = 0; + s_agps_socket_extend.data_start = 1; + agps_msg_send_get_file(AGPS_MSG_REQ_LENTH); + return; + } + + //后继包 + GM_memcpy(&s_agps_file_extend.data[s_agps_file_extend.len], &pdata[19], len - AGPS_MSG_PACKAGE_LENTH); + s_agps_file_extend.len += (len - AGPS_MSG_PACKAGE_LENTH);; + s_agps_socket_extend.data_start += (len - AGPS_MSG_PACKAGE_LENTH); + + LOG(DEBUG,"clock(%d) agps_msg_parse_zkw_ack file_len(%d) start(%d).", + util_clock(),s_agps_file_extend.len, s_agps_socket_extend.data_start); + + if(s_agps_file_extend.len < s_agps_socket_extend.data_len) + { + data_len = s_agps_socket_extend.data_len - s_agps_file_extend.len; + data_len = data_len > AGPS_MSG_REQ_LENTH?AGPS_MSG_REQ_LENTH:data_len; + agps_msg_send_get_file(data_len); + } + else + { + s_agps_file_extend.len = s_agps_socket_extend.data_len; + agps_write_data_file(AGPS_FILE_PATH); + agps_service_close_for_reconnect(); + } + } +} + + +static u8 agps_data_check_item_num(u8 *pdata, u16 len) +{ + u16 idx = 0; + u16 index = 0; + + for (idx=0; idx (sizeof(AgpsFileExtend) - AGPS_FILE_EXTEND_HEAD_SIZE )) + { + LOG(DEBUG,"clock(%d) agps_write_data_file assert(len(%d)) failed.",util_clock(),s_agps_file_extend.len); + return; + } + GM_memcpy(&s_agps_file_inuse, &s_agps_file_extend, fs_len); + + //如果需要写串口,就写 + write_agps_succ = agps_service_write_to_gps(); + { + //report logs + JsonObject* p_json_log = json_create(); + json_add_string(p_json_log,"event","write_agps3"); + json_add_int(p_json_log,"start",s_agps_file_inuse.start_time); + json_add_int(p_json_log,"last",s_agps_file_inuse.last); + json_add_int(p_json_log,"ret",write_agps_succ?1:0); + log_service_upload(INFO, p_json_log); + } + + p = (u8 * )&s_agps_file_extend.gps_dev_type; + s_agps_file_extend.crc = applied_math_calc_common_crc16(p , (fs_len-2)); + LOG(DEBUG,"clock(%d) agps_write_data_file crc(%d) devtype(%d) leap(%d) flag(%d) len(%d) start(%d) lng(%f) lat(%f) last(%d).", + util_clock(),s_agps_file_extend.crc,s_agps_file_extend.gps_dev_type,s_agps_file_extend.leap_seconds, + s_agps_file_extend.file_flag,s_agps_file_extend.len,s_agps_file_extend.start_time, + s_agps_file_extend.lng,s_agps_file_extend.lat,s_agps_file_extend.last); + + util_delete_file(file_name); + handle = GM_FS_Open(file_name, GM_FS_READ_WRITE | GM_FS_ATTR_ARCHIVE | GM_FS_CREATE); + if (handle < 0) + { + LOG(DEBUG,"clock(%d) agps_write_data_file assert(GM_FS_Open) failed. return %d.",util_clock(),handle); + return; + } + + + // 预先占用指定长度 + p = (u8 * )&s_agps_file_extend.crc; + will_write = fs_len; + while(writen_total != fs_len) + { + if((fs_len - writen_total) < will_write) + { + will_write = (fs_len - writen_total); + } + + ret = GM_FS_Write(handle, (void *)(p + writen_total), will_write, &writen); + if ((ret < 0) || (writen==0)) + { + LOG(DEBUG,"clock(%d) agps_write_data_file assert(GM_FS_Write(ret:%d, writen:%d)) failed.",util_clock(), ret, writen); + GM_FS_Close(handle); + handle = -1; + return; + } + writen_total += writen; + } + GM_FS_Close(handle); + handle = -1; + LOG(DEBUG,"clock(%d) agps_write_data_file length(%d).",util_clock(),fs_len); + return; +} + + + +static void agps_read_data_file(const U16 * file_name) +{ + u32 will_read = 0; + u32 read_total = 0; + u32 read_len = 0; + int handle = -1; + int ret; + + handle = GM_FS_Open(file_name, GM_FS_READ_ONLY | GM_FS_ATTR_ARCHIVE ); + if (handle < 0) + { + GM_memset(&s_agps_file_inuse, 0, sizeof(s_agps_file_inuse)); + return; + } + + + ret = GM_FS_Read(handle, (void *)&s_agps_file_inuse.crc, AGPS_FILE_EXTEND_HEAD_SIZE, &read_len); + if (ret != 0 || AGPS_FILE_EXTEND_HEAD_SIZE != read_len) + { + LOG(INFO,"clock(%d) agps_read_data_file GM_FS_Read failed, ret:%d, read_len:%d.",util_clock(), ret, read_len); + GM_FS_Close(handle); + handle = -1; + GM_memset(&s_agps_file_inuse, 0, sizeof(s_agps_file_inuse)); + return; + } + + LOG(DEBUG,"clock(%d) agps_read_data_file crc(%d) devtype(%d) leap(%d) flag(%d) len(%d) start(%d) lng(%f) lat(%f) last(%d).", + util_clock(),s_agps_file_inuse.crc,s_agps_file_inuse.gps_dev_type,s_agps_file_inuse.leap_seconds, + s_agps_file_inuse.file_flag,s_agps_file_inuse.len,s_agps_file_inuse.start_time, + s_agps_file_inuse.lng,s_agps_file_inuse.lat,s_agps_file_inuse.last); + + //长度合法 + if(s_agps_file_inuse.len > sizeof(s_agps_file_inuse.data)) + { + LOG(INFO,"clock(%d) agps_read_data_file assert(datalen(%d)) failed.",util_clock(), s_agps_file_inuse.len); + GM_FS_Close(handle); + handle = -1; + GM_memset(&s_agps_file_inuse, 0, sizeof(s_agps_file_inuse)); + return; + } + + //读数据区 + read_total = 0; + while(read_total != s_agps_file_inuse.len) + { + will_read = (s_agps_file_inuse.len - read_total); + + ret = GM_FS_Read(handle, (void *)(s_agps_file_inuse.data + read_total), will_read, &read_len); + if ((ret < 0) || (read_len==0)) + { + LOG(DEBUG,"clock(%d) agps_read_data_file assert(GM_FS_Read(ret:%d, read_len:%d)) failed.",util_clock(), ret, read_len); + GM_FS_Close(handle); + handle = -1; + GM_memset(&s_agps_file_inuse, 0, sizeof(s_agps_file_inuse)); + return; + } + read_total += read_len; + } + GM_FS_Close(handle); + handle = -1; + + if(s_agps_file_inuse.crc != applied_math_calc_common_crc16(&s_agps_file_inuse.gps_dev_type , s_agps_file_inuse.len + (AGPS_FILE_EXTEND_HEAD_SIZE - 2))) + { + LOG(DEBUG,"clock(%d) agps_read_data_file assert(GM_FS_Read(ret:%d, read_len:%d)) failed.",util_clock(), + s_agps_file_inuse.crc, applied_math_calc_common_crc16(&s_agps_file_inuse.gps_dev_type , s_agps_file_inuse.len + (AGPS_FILE_EXTEND_HEAD_SIZE - 2))); + GM_memset(&s_agps_file_inuse, 0, sizeof(s_agps_file_inuse)); + return; + } + + //s_agps_file_extend是刚刚从服务器获取的最新数据 + s_agps_file_inuse.lng = s_agps_file_extend.lng; + s_agps_file_inuse.lat = s_agps_file_extend.lat; + s_agps_file_inuse.leap_seconds = s_agps_file_extend.leap_seconds; + //数据合法 + return; +} + + +bool agps_service_require_to_gps(AgpsToGpsEnum type,bool re_download) +{ + static u16 seg_index = 0; + u16 seg_size = 0; + u16 left_size = 0; + GM_ERRCODE ret; + + if(! s_agps_socket_extend.required_agps) + { + s_agps_socket_extend.required_agps = 1; + } + + if(0 == s_agps_file_inuse.start_time) + { + //等待校时 + LOG(DEBUG,"clock(%d) agps_service_require_to_gps waiting for timing.",util_clock()); + return false;; + } + + //由于agps文件是多管半小时的, 所以提前拿文件没必要, 多加180是防止本地时间不太准 + if((s_agps_file_inuse.start_time > (util_get_utc_time()+180)) || + (s_agps_file_inuse.start_time+s_agps_file_inuse.last ) < util_get_utc_time() ) + { + seg_index = 0; + LOG(DEBUG,"clock(%d) agps_service_require_to_gps assert(s_agps_file_inuse) failed.",util_clock()); + return false; + } + + if(type == AGPS_TO_GPS_LNGLAT_TIME) + { + ret = gps_write_agps_info(s_agps_file_inuse.lng, s_agps_file_inuse.lat, s_agps_file_inuse.leap_seconds); + seg_index = 0; + LOG(DEBUG,"clock(%d) agps_service_require_to_gps write lng(%f),lat(%f),leap(%d).", + util_clock(),s_agps_file_inuse.lng, s_agps_file_inuse.lat, s_agps_file_inuse.leap_seconds); + return (GM_SUCCESS == ret); + } + + if(re_download && seg_index > 0) + { + // 数据错误(re_download), 则重新获取 + agps_service_reset(); + seg_index = 0; + return false; + } + + + switch(s_agps_file_inuse.gps_dev_type) + { + case GM_GPS_TYPE_MTK_EPO: + seg_size = sizeof(U32)*18; // 一次18个U32 + break; + case GM_GPS_TYPE_TD_AGPS: + seg_size = 73; // 一次一个辅助信息长度 + break; + case GM_GPS_TYPE_AT_AGPS: + seg_size = s_agps_file_inuse.len; //可以整个儿发送 + break; + default: + seg_index = 0; + LOG(DEBUG,"clock(%d) agps_service_require_to_gps assert(dev_type(%d)) failed.",util_clock(),s_agps_file_inuse.gps_dev_type); + return false; + } + + // AGPS_TO_GPS_DATA + left_size = s_agps_file_inuse.len - seg_index * seg_size; + if(left_size > seg_size) + { + //序号要从1开始 + ret = gps_write_agps_data(seg_index + 1, &s_agps_file_inuse.data[seg_index * seg_size], seg_size); + seg_index++; + //LOG(DEBUG,"clock(%d) agps_service_require_to_gps write seg_size(%d).",util_clock(),seg_size); + return (GM_SUCCESS == ret); + } + else + { + ret = gps_write_agps_data(seg_index + 1, &s_agps_file_inuse.data[seg_index * seg_size], left_size); + + seg_index = 0; + + LOG(DEBUG,"clock(%d) Wrote the last segment(%d).",util_clock(),left_size); + s_agps_socket_extend.required_agps = 0; + + + //false 中止agps_service_require_to_gps 后继回调 + return false; + } + +} + +void agps_service_delele_file(void) +{ + util_delete_file(AGPS_FILE_PATH); + util_delete_file(EPO_FILE_PATH); +} + + +static void agps_service_check_and_read_file(void) +{ + if(0 == s_agps_file_inuse.start_time) + { + switch(config_service_get_gps_type()) + { + case GM_GPS_TYPE_MTK_EPO: + agps_read_data_file(EPO_FILE_PATH); + break; + case GM_GPS_TYPE_TD_AGPS: + agps_read_data_file(AGPS_FILE_PATH); + break; + case GM_GPS_TYPE_AT_AGPS: + agps_read_data_file(AGPS_FILE_PATH); + break; + default: + LOG(WARN,"clock(%d) agps_service_check_and_read_file assert(config_service_get_gps_type(%d) failed.", util_clock(),config_service_get_gps_type()); + break; + } + } + + //lz add for print agps file content + { + u16 seg_size = 0; + static u16 print_start = 0; + u16 loop_count = 0; + switch(config_service_get_gps_type()) + { + case GM_GPS_TYPE_MTK_EPO: + seg_size = sizeof(U32)*18; // 一次18个U32 + break; + case GM_GPS_TYPE_TD_AGPS: + seg_size = 73; // 一次一个辅助信息长度 + break; + case GM_GPS_TYPE_AT_AGPS: + seg_size = 100; //可以整个儿发送 + break; + default: + break; + } + for(; print_start < s_agps_file_inuse.len; print_start+=seg_size) + { + u16 print_len = seg_size; + ++loop_count; + if((print_start + print_len) >= s_agps_file_inuse.len) + { + print_len = s_agps_file_inuse.len - print_start - 1; + } + log_service_print_hex((const char *)&s_agps_file_inuse.data[print_start], print_len); + if(loop_count > 4) + { + break; + } + } + } +} + +float agps_service_get_unfix_lng(void) +{ + return s_agps_file_extend.lng; +} + +float agps_service_get_unfix_lat(void) +{ + return s_agps_file_extend.lat; +} + +/* +agps_service模块传送数据给gps后, 长时间无法响应, 一般是文件内容错, 要求重新获取. +*/ +static void agps_service_reset(void) +{ + agps_service_delele_file(); + GM_memset(&s_agps_file_inuse, 0, sizeof(s_agps_file_inuse)); + GM_memset(&s_agps_file_extend, 0, sizeof(s_agps_file_extend)); + agps_service_transfer_status(SOCKET_STATUS_INIT); +} + + diff --git a/src/applied_math.c b/src/applied_math.c new file mode 100644 index 0000000..52fc0af --- /dev/null +++ b/src/applied_math.c @@ -0,0 +1,279 @@ +/** + * Copyright ? Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: applied_math.c + * Author: 王志华 + * Version: 1.0 + * Date: 2019-02-28 + * Description: 应用数学运算 + * Others: + * Function List: + 1. 获取数值的符号 + 2. 四舍五入取整 + 3. 三维向量取模 + 4. 二维向量取模 + 5. 三维向量的归一化处理 + 6. 二维向量的归一化处理 + 7. 三维向量内积(点积) + 8. 二维向量内积(点积) + 9. 三维向量叉积 + 10.三维向量之间的夹角 + 11.根据经纬度计算两点间距离 + * History: + 1. Date: 2019-02-28 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include "applied_math.h" +#include +#include + + +static const float PI = 3.1415926535898; + +//地球半径(公里) +static const float EARTH_RADIUS = 6378.137; + + +// CRC-ITU 查表算法 +static const U16 common_crc16_tab[] = +{ + 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, + 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, + 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, + 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, + 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, + 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, + 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, + 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, + 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, + 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, + 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, + 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, + 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, + 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, + 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, + 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, + 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, + 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, + 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, + 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, + 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, + 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, + 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, + 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, + 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, + 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, + 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, + 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, + 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, + 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, + 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, + 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78, +}; + + + +static const U8 epo_crc16_tab_h[] = +{ + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 +}; + + +static const U8 epo_crc16_tab_l[] = +{ + 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, + 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, + 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, + 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, + 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, + 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, + 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, + 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, + 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, + 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, + 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, + 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, + 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, + 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, + 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, + 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 +}; + + +char applied_math_get_sign(double value) +{ + return value < -1E-6 ? -1 : value > 1E-6; +} + +S32 applied_math_round(double value) +{ + return (int)(applied_math_get_sign(value) * (fabs(value) + 0.50001)); +} + +double applied_math_get_magnitude_3d(Vector3D v) +{ + return sqrt(v.x * v.x + v.y * v.y + v.z * v.z); +} + +double applied_math_get_magnitude_2d(Vector2D v) +{ + return sqrt(v.x * v.x + v.y * v.y); +} + +Vector3D applied_math_normalize_3d(Vector3D v) +{ + Vector3D ret_aclr = {0, 0, 0}; + double mag = applied_math_get_magnitude_3d(v); + ret_aclr.x = v.x / mag; + ret_aclr.y = v.y / mag; + ret_aclr.z = v.z / mag; + return ret_aclr; +} + +Vector2D applied_math_normalize_2d(Vector2D v) +{ + Vector2D ret_aclr = {0, 0}; + double mag = applied_math_get_magnitude_2d(v); + ret_aclr.x = v.x / mag; + ret_aclr.y = v.y / mag; + return ret_aclr; +} + +float applied_math_inner_product_3d(Vector3D a, Vector3D b) +{ + return (a.x * b.x + a.y * b.y + a.z * b.z); +} + +float applied_math_inner_product_2d(Vector2D a, Vector2D b) +{ + return (a.x * b.x + a.y * b.y); +} + +Vector3D applied_math_cross_product_3d(Vector3D u, Vector3D v) +{ + Vector3D ret_aclr = {0, 0, 0}; + ret_aclr.x = u.y * v.z - u.z * v.y; + ret_aclr.y = u.z * v.x - u.x * v.z; + ret_aclr.z = u.x * v.y - u.y * v.x; + return ret_aclr; +} + +U8 applied_math_get_angle_3d(Vector3D a, Vector3D b) +{ + float product = 0; + float a_magnitude = 0; + float b_magnitude = 0; + float cosine = 0; + float radian = 0; + float angle = 0; + + product = applied_math_inner_product_3d(a, b); + a_magnitude = applied_math_get_magnitude_3d(a); + b_magnitude = applied_math_get_magnitude_3d(b); + if (fabs(a_magnitude * b_magnitude) < 1E-8) + { + return 0; + } + cosine = product / (a_magnitude * b_magnitude); + radian = acos(cosine); + angle = 180 * radian / PI; + + return applied_math_round(angle); +} + +U16 applied_math_get_angle_diff(U16 angle_degree1, U16 angle_degree2) +{ + U16 diff = abs((angle_degree1 + 360 - angle_degree2)%360); + return (diff > 180) ? (180 - diff%180) : diff; +} + +double applied_math_get_distance(double start_lng, double start_lat, double end_lng, double end_lat) +{ + double start_lat_rad = start_lat * PI / 180.0; + double start_lng_rad = start_lng * PI / 180.0; + double end_lat_rad = end_lat * PI / 180.0; + double end_lng_rad = end_lng * PI / 180.0; + double lat_diff = end_lat_rad - start_lat_rad; + double lng_diff = end_lng_rad - start_lng_rad; + double a = pow(sin(lat_diff / 2),2) + cos(start_lat_rad)*cos(end_lat_rad)*pow(sin(lng_diff / 2),2); + double distance = 2 * asin(sqrt(a)) * EARTH_RADIUS * 1000; + return distance; +} + +U16 applied_math_calc_common_crc16(const U8 * p_data, U32 len) +{ + U16 crc = 0xFFFF; + + if (NULL == p_data || len > 0x48000) + { + return crc; + } + + while(len > 0) + { + crc = (crc >> 8) ^ common_crc16_tab[(crc ^ (*p_data)) & 0xFF]; + p_data++; + len--; + } + + return ~crc; +} + +U32 applied_math_calc_epo_crc16(const U8* p_data, U32 len, U32 pre_val) +{ + U32 crc_h = (pre_val & 0xFF00) >> 8; + U32 crc_l = pre_val & 0xFF00; + U32 tab_index = 0; + U32 i = 0; + + if (NULL == p_data || len > 0x28000) + { + return ((crc_h & 0x00FF) << 8) | (crc_l & 0x00FF) & 0xFFFF; + } + + for (i = 0; i < len; ++i) + { + tab_index = (crc_l ^ p_data[i]) & 0x00FF; + crc_l = crc_h ^ epo_crc16_tab_h[tab_index]; + crc_h = epo_crc16_tab_l[tab_index]; + } + + return ((crc_h & 0x00FF) << 8) | (crc_l & 0x00FF) & 0xFFFF; +} + +float applied_math_lowpass_filter(const float last_value, const float new_value, float alpha) +{ + return last_value * alpha + new_value * (1 - alpha); +} + +float applied_math_avage(const float* p_array,const U16 len) +{ + U16 index = 0; + float sum = 0; + for(index = 0;index < len;index++) + { + sum += p_array[index]; + } + return sum/len; +} + diff --git a/src/auto_test.c b/src/auto_test.c new file mode 100644 index 0000000..72202c5 --- /dev/null +++ b/src/auto_test.c @@ -0,0 +1,951 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: auto_test.c + * Author: 王志华 + * Version: 1.0 + * Date: 2019-05-25 + * Description: 定时输出日志到串口,供自动化测试程序检测 + * Others: + * Function List: + 1. 创建auto_test模块 + 2. 销毁auto_test模块 + 3. auto_test模块定时处理入口 + * History: + 1. Date: 2019-05-25 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include +#include +#include +#include +#include "auto_test.h" +#include "system_state.h" +#include "log_service.h" +#include "hard_ware.h" +#include "gps.h" +#include "g_sensor.h" +#include "config_service.h" +#include "gsm.h" +#include "gprs.h" +#include "system_state.h" +#include "utility.h" +#include "relay.h" +#include "agps_service.h" +#include "gps_service.h" +#include "applied_math.h" +#include "uart.h" +#include "uart.h" + +#pragma diag_suppress 870 + +//5分钟自检成功 +#define SELF_TEST_TIME_STANDARD (5*SECONDS_PER_MIN) +#define TEST_FAIL_FILE L"Z:\\goome\\GmTestFailFile\0" +#define REALY_ACC_PERIOD 20 +#define AUTO_TEST_MAGIC_NUMBER 0xFEFEFEFE +#define BATTERY_VOLTAGE_STANDARD 3.9 + + + +typedef struct +{ + //数据长度 + U16 data_len; + + //16比特CRC + U16 crc; + + //特征码 + U32 magic; + + //必选项,一次成功即成功的项 + bool required_items_test_pass; + + //必选项,一次失败即失败的项 + bool required_items_test_fail; + + //必选项测试结果,true通过 + bool required_items_result; + + //可选项,一次成功即成功的项 + bool optional_items_test_pass; + + //可选项,一次失败即失败的项 + bool optional_items_test_fail; + + //必选项测试结果,true通过 + bool all_items_result; + + //必选检查项:测试时长,一次成功即成功 + U16 test_time_seconds; + + char app_version[64]; + char kernal_version[64]; + + //必选检查项:外电电压,一次失败即失败 + bool power_fail; + float voltage_min; + float voltage_max; + + //必选检查项:SIM卡,一次失败即失败 + bool sim_fail; + char imei[20]; + char chip_rid[50]; + u8 iccid[30]; + + //必选检查项:校准,一次失败即失败 + bool adjust_fail; + U8 adjust_code[65]; + bool channels_adjust_fail[4]; + + //必选检查项:网络,一次失败即失败 + bool network_fail; + U32 csq_counts; + float csq_avg; + U8 csq_min; + U16 network_fail_counts; + //交给工具检查这2个次 + U16 heart_counts; + U16 location_data_counts; + + + //可选检查项:电池,一次成功即成功 + bool battery_ok; + float battery_voltage; + + //可选检查项:ACC,一次失败即失败 + bool acc_fail; + U8 acc_on_count; + U8 acc_off_count; + + //必选检查项:重启次数,一次失败即失败 + bool reboot_counts_fail; + //断网重启次数 + U16 reboot_for_power_counts; + //断网重启次数 + U16 reboot_for_net_counts; + //升级重启次数 + U16 reboot_for_upgrade_counts; + //异常重启次数 + U16 reboot_for_exception_counts; + + //必选检查项:GPS,一次失败即失败 + bool gps_fail; + //首次定位时间 + U16 first_fix_time; + float snr_avg; + U32 snr_counts; + + + //必选检查项:运动传感,一次失败即失败 + bool g_sensor_fail; + U32 g_sensor_error_counts; + U32 g_sensor_sleep_time; + U32 g_sensor_shake_counts; +}AutoTestResult; + +typedef struct +{ + bool is_self_check; + bool start; + AutoTestResult test_result; +}AutoTest; + + +static AutoTest s_auto_test; + +static void init_test_result(AutoTestResult* p_test_result); +static void auto_test_self_test(void); +static void struct_to_jsonstr(const AutoTestResult result,char* json_str); +static GM_ERRCODE read_result_from_file(const U16* FileName,AutoTestResult* p_result); +static void auto_test_save_to_file(const U16* FileName); + + +static void auto_test_check_power(void); +static void auto_test_check_sim(void); +static void auto_test_check_adjust(void); +static void auto_test_check_network(void); +static void auto_test_check_battery_status(void); +static void auto_test_check_acc(void); +static void auto_test_check_reboot(void); +static void auto_test_check_gps_location(void); +static void auto_test_check_gsensor(void); + +static U32 auto_test_calc_hashnr(const u8 *key, u32 len); +static void auto_test_check_chip_rid(void); +static bool is_device_05(ConfigDeviceTypeEnum dev_type); + +GM_ERRCODE auto_test_create(bool is_self_check) +{ + + //防止重复多次进入自检 + if (s_auto_test.start && is_self_check) + { + LOG(INFO,"Already start self check!"); + return GM_ERROR_STATUS; + } + + //如果不是缺省IMEI,不自检 + if (!config_service_is_default_imei() && is_self_check) + { + LOG(INFO,"It is not default imei!"); + return GM_ERROR_STATUS; + } + + LOG(INFO,"start test,is_self_check=%d",is_self_check); + s_auto_test.start = true; + s_auto_test.is_self_check = is_self_check; + + init_test_result(&s_auto_test.test_result); + + log_service_enable_print(false); + config_service_set_test_mode(true); + + auto_test_check_chip_rid(); + + GM_ReleaseVerno((U8*)s_auto_test.test_result.kernal_version); + + return GM_SUCCESS; +} + +GM_ERRCODE auto_test_destroy(void) +{ + LOG_TEST("Exit test mode."); + s_auto_test.start = false; + + log_service_enable_print(true); + config_service_set_test_mode(false); + + return GM_SUCCESS; +} + +GM_ERRCODE auto_test_reset(void) +{ + init_test_result(&s_auto_test.test_result); + GM_FS_Delete(TEST_FAIL_FILE); + return GM_SUCCESS; +} + +GM_ERRCODE auto_test_timer_proc(void) +{ + if(!s_auto_test.start) + { + init_test_result(&s_auto_test.test_result); + return GM_SUCCESS; + } + + s_auto_test.test_result.test_time_seconds++; + if (s_auto_test.test_result.test_time_seconds % (REALY_ACC_PERIOD/2) == 0) + { + if(system_state_get_device_relay_state()) + { + relay_off(); + } + else + { + relay_on(false); + } + } + + + auto_test_self_test(); + + return GM_SUCCESS; +} + +static void init_test_result(AutoTestResult* p_test_result) +{ + if (NULL == p_test_result) + { + return; + } + + GM_memset(p_test_result,0,sizeof(AutoTestResult)); + + p_test_result->data_len = sizeof(AutoTestResult) - 2*sizeof(U16) - sizeof(U32); + p_test_result->magic = AUTO_TEST_MAGIC_NUMBER; + p_test_result->voltage_min = 200; + p_test_result->csq_min = 31; +} + +static void auto_test_self_test(void) +{ + //IMEI + gsm_get_imei((U8*)s_auto_test.test_result.imei); + + //APP版本 + GM_snprintf(s_auto_test.test_result.app_version,sizeof(s_auto_test.test_result.app_version),"%s(%X)", VERSION_NUMBER, system_state_get_bin_checksum()); + + auto_test_check_chip_rid(); + auto_test_check_power(); + auto_test_check_sim(); + auto_test_check_adjust(); + auto_test_check_network(); + auto_test_check_battery_status(); + auto_test_check_acc(); + auto_test_check_reboot(); + auto_test_check_gps_location(); + auto_test_check_gsensor(); + + if (s_auto_test.is_self_check) + { + + s_auto_test.test_result.required_items_test_pass = ((s_auto_test.test_result.heart_counts > s_auto_test.test_result.test_time_seconds/GOOME_HEARTBEAT_DEFAULT*0.8) && + (s_auto_test.test_result.location_data_counts > s_auto_test.test_result.test_time_seconds/CONFIG_UPLOAD_TIME_DEFAULT*0.8) && + (s_auto_test.test_result.test_time_seconds > SELF_TEST_TIME_STANDARD) && + (s_auto_test.test_result.g_sensor_shake_counts >= G_SHAKE_BUF_LEN)); + } + else + { + + s_auto_test.test_result.required_items_test_pass = ((s_auto_test.test_result.heart_counts >= 1) && + (s_auto_test.test_result.location_data_counts >= 1) && + (s_auto_test.test_result.test_time_seconds > 30) && + (s_auto_test.test_result.g_sensor_shake_counts > 2)); + } + + s_auto_test.test_result.required_items_result = (!s_auto_test.test_result.required_items_test_fail && s_auto_test.test_result.required_items_test_pass); + + s_auto_test.test_result.optional_items_test_pass = s_auto_test.test_result.battery_ok; + s_auto_test.test_result.optional_items_test_fail = s_auto_test.test_result.acc_fail; + + s_auto_test.test_result.all_items_result = (!s_auto_test.test_result.required_items_test_fail && + s_auto_test.test_result.required_items_test_pass && + s_auto_test.test_result.optional_items_test_pass && + !s_auto_test.test_result.optional_items_test_fail); + + if(s_auto_test.test_result.test_time_seconds % SECONDS_PER_MIN == 0) + { + auto_test_save_to_file(TEST_FAIL_FILE); + } + + if(!s_auto_test.is_self_check) + { + char test_result[1024] = {0}; + auto_test_get_result(false,test_result); + GM_snprintf(test_result + GM_strlen(test_result), (1024 - GM_strlen(test_result)), "\r\n"); + uart_write(GM_UART_DEBUG, (U8*)test_result, GM_strlen(test_result)); + } + +} + +void auto_test_acc_on(void) +{ + s_auto_test.test_result.acc_on_count++; +} + +void auto_test_acc_off(void) +{ + s_auto_test.test_result.acc_off_count++; +} + +static GM_ERRCODE read_result_from_file(const U16* FileName,AutoTestResult* p_result) +{ + U32 file_len = 0; + S32 file_handle = -1; + S32 ret = -1; + U16 crc = 0; + + file_handle = GM_FS_Open(FileName, GM_FS_READ_ONLY | GM_FS_ATTR_ARCHIVE | GM_FS_CREATE); + if (file_handle < 0) + { + LOG(INFO,"Failed to open self check result file!"); + return GM_SYSTEM_ERROR; + } + + ret = GM_FS_Read(file_handle, (void *)p_result, sizeof(AutoTestResult), &file_len); + if (ret < 0) + { + LOG(ERROR,"Failed to read system state file[%d]", ret); + GM_FS_Close(file_handle); + return GM_SYSTEM_ERROR; + } + + GM_FS_Close(file_handle); + + + crc = applied_math_calc_common_crc16((U8*)(p_result->required_items_test_pass), p_result->data_len); + + + if (p_result->magic != AUTO_TEST_MAGIC_NUMBER) + { + LOG(ERROR,"magic error:%x, ", s_auto_test.test_result.magic); + return GM_SYSTEM_ERROR; + } + + if (p_result->crc != crc) + { + LOG(ERROR,"crc error:%x, %x", p_result->crc, crc); + return GM_SYSTEM_ERROR; + } + return GM_SUCCESS; +} + +void auto_test_save_to_file(const U16* FileName) +{ + U32 file_len = 0; + S32 file_handle = -1; + S32 ret = -1; + + if (!config_service_is_default_imei()) + { + return; + } + + file_handle = GM_FS_Open(FileName, GM_FS_READ_WRITE | GM_FS_ATTR_ARCHIVE | GM_FS_CREATE); + if (file_handle < 0) + { + LOG_TEST("Failed to open test file[%d]", file_handle); + } + + s_auto_test.test_result.crc = applied_math_calc_common_crc16((u8*)&(s_auto_test.test_result.required_items_test_pass), s_auto_test.test_result.data_len); + + ret = GM_FS_Write(file_handle, (void *)&s_auto_test.test_result, sizeof(s_auto_test.test_result), &file_len); + if (ret < 0) + { + LOG_TEST("Failed to write test file[%d]", ret); + GM_FS_Close(file_handle); + } + else + { + LOG_TEST("Succeed to write test file", ret); + } + + + GM_FS_Commit(file_handle); + GM_FS_Close(file_handle); + +} + +void auto_test_get_result(bool is_history,char* json_str) +{ + if (is_history) + { + AutoTestResult test_result; + init_test_result(&test_result); + read_result_from_file(TEST_FAIL_FILE,&test_result); + struct_to_jsonstr(test_result,json_str); + } + else + { + struct_to_jsonstr(s_auto_test.test_result,json_str); + } +} + +static void struct_to_jsonstr(const AutoTestResult result,char* json_str) +{ + JsonObject* p_result_root = json_create(); + + json_add_string(p_result_root, "event", "selftest"); + json_add_string(p_result_root, "chip_rid", result.chip_rid); + json_add_string(p_result_root, "imei", (char*)result.imei); + json_add_string(p_result_root, "iccid", (char*)result.iccid); + + json_add_int(p_result_root, "required_items_result", result.required_items_result); + json_add_int(p_result_root, "all_items_result", result.all_items_result); + + json_add_int(p_result_root, "test_time_seconds", result.test_time_seconds); + + json_add_string(p_result_root, "app_version", result.app_version); + json_add_string(p_result_root, "kernal_version", result.kernal_version); + + json_add_double(p_result_root, "voltage_min", result.voltage_min); + json_add_double(p_result_root, "voltage_max", result.voltage_max); + + json_add_int(p_result_root, "sim_fail", result.sim_fail); + json_add_int(p_result_root, "network_fail", result.network_fail); + json_add_int(p_result_root, "csq_counts", result.csq_counts); + json_add_double(p_result_root, "csq_avg", result.csq_avg); + json_add_int(p_result_root, "csq_min", result.csq_min); + + json_add_int(p_result_root, "network_fail_counts", result.network_fail_counts); + json_add_int(p_result_root, "heart_counts", result.heart_counts); + json_add_int(p_result_root, "location_data_counts", result.location_data_counts); + + json_add_double(p_result_root, "battery_voltage", result.battery_voltage); + + json_add_int(p_result_root, "acc_on_count", result.acc_on_count); + json_add_int(p_result_root, "acc_off_count", result.acc_off_count); + + json_add_int(p_result_root, "reboot_for_power_counts", result.reboot_for_power_counts); + json_add_int(p_result_root, "reboot_for_net_counts", result.reboot_for_net_counts); + json_add_int(p_result_root, "reboot_for_upgrade_counts", result.reboot_for_upgrade_counts); + json_add_int(p_result_root, "reboot_for_exception_counts", result.reboot_for_exception_counts); + json_add_int(p_result_root, "reboot_for_hardware_counts", result.reboot_for_power_counts + result.reboot_for_exception_counts); + + json_add_int(p_result_root, "gps_fail", result.gps_fail); + json_add_int(p_result_root, "first_fix_time", result.first_fix_time); + json_add_double(p_result_root, "snr_avg", result.snr_avg); + json_add_int(p_result_root, "snr_counts", result.snr_counts); + json_add_int(p_result_root, "g_sensor_fail", result.g_sensor_fail); + + + json_add_int(p_result_root, "g_sensor_error_counts", result.g_sensor_error_counts); + json_add_int(p_result_root, "g_sensor_sleep_time", result.g_sensor_sleep_time); + json_add_int(p_result_root, "g_sensor_shake_counts", result.g_sensor_shake_counts); + + json_print_to_buffer(p_result_root, json_str, sizeof(json_str) - 1); + json_destroy(p_result_root); + +} + + + +//必选检查项:外电电压,一次失败即失败 +static void auto_test_check_power(void) +{ + float voltage = 0; + static U32 power_fail_counts = 0; + if(util_clock() <= 20) + { + return; + } + hard_ware_get_power_voltage(&voltage); + if(voltage > s_auto_test.test_result.voltage_max) + { + s_auto_test.test_result.voltage_max = voltage; + } + + if(voltage > 7 && voltage < s_auto_test.test_result.voltage_min) + { + s_auto_test.test_result.voltage_min = voltage; + } + + + if (voltage > 7 && voltage < 28) + { + power_fail_counts++; + } + else + { + power_fail_counts = 0; + } + if (power_fail_counts > 10) + { + s_auto_test.test_result.power_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_power!"); + } +} + +//必选检查项:SIM卡,一次失败即失败 +static void auto_test_check_sim(void) +{ + if(util_clock() <= 20) + { + return; + } + if (GM_CheckSimValid()) + { + if(GM_SUCCESS != gsm_get_iccid(s_auto_test.test_result.iccid)) + { + s_auto_test.test_result.sim_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_sim!"); + } + } + else + { + s_auto_test.test_result.sim_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_sim!"); + } +} + +//必选检查项:校准,一次失败即失败 +static void auto_test_check_adjust(void) +{ + U8 index = 0; + u16 nvLib = 0; + s32 result = 0; + l1cal_rampTable_T ramp; + index = GM_GetBarcode(s_auto_test.test_result.adjust_code); + if (index == 64) + { + if (GM_strlen((char*)s_auto_test.test_result.adjust_code) < 30) + { + s_auto_test.test_result.adjust_fail = true; + } + } + else + { + s_auto_test.test_result.adjust_fail = true; + } + + for(index = NVRAM_EF_L1_RAMPTABLE_GSM850_LID;index <= NVRAM_EF_L1_RAMPTABLE_PCS1900_LID;index++) + { + nvLib = GM_ReadNvramLid(index); + GM_ReadWriteNvram(1, nvLib, 1, &ramp, sizeof(ramp), &result); + if ((ramp.rampData.power[0] == ramp.rampData.power[1]) && (ramp.rampData.power[1] == ramp.rampData.power[2]) && + (ramp.rampData.power[2] == ramp.rampData.power[3]) && (ramp.rampData.power[3] == ramp.rampData.power[4])) + { + s_auto_test.test_result.channels_adjust_fail[index - NVRAM_EF_L1_RAMPTABLE_GSM850_LID] = true; + s_auto_test.test_result.adjust_fail = true; + } + else if ((ramp.rampData.power[14] > 850) || (ramp.rampData.power[15] > 850)) + { + s_auto_test.test_result.channels_adjust_fail[index - NVRAM_EF_L1_RAMPTABLE_GSM850_LID] = true; + s_auto_test.test_result.adjust_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_adjust!"); + } + else if (ramp.rampData.power[15] < 400) + { + s_auto_test.test_result.channels_adjust_fail[index - NVRAM_EF_L1_RAMPTABLE_GSM850_LID] = true; + s_auto_test.test_result.adjust_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_adjust!"); + } + else + { + //do nothing + } + } +} + +//必选检查项:网络,一次失败即失败 +static void auto_test_check_network(void) +{ + U8 csq = gsm_get_csq(); + + + if(util_clock() <= 20) + { + return; + } + if (csq < s_auto_test.test_result.csq_min) + { + s_auto_test.test_result.csq_min = csq; + } + s_auto_test.test_result.csq_avg = (s_auto_test.test_result.csq_avg*s_auto_test.test_result.csq_counts + csq)/(s_auto_test.test_result.csq_counts + 1); + s_auto_test.test_result.csq_counts++; + if (s_auto_test.test_result.csq_avg < 10) + { + s_auto_test.test_result.network_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_network1!"); + } + + s_auto_test.test_result.network_fail_counts = gprs_get_call_ok_count() > 0 ? (gprs_get_call_ok_count() - 1) : 0; + s_auto_test.test_result.heart_counts = gps_service_get_heart_counts(); + s_auto_test.test_result.location_data_counts = gps_service_get_location_counts(); +} + +//可选检查项:电池电压,一次成功即成功 +static void auto_test_check_battery_status(void) +{ + static bool battery_ok = false; + static u16 check_count = 0; + float power_voltage = 0; + + hard_ware_get_power_voltage(&power_voltage); + + if (power_voltage < 7) + { + hard_ware_get_internal_battery_voltage(&s_auto_test.test_result.battery_voltage); + if (s_auto_test.test_result.battery_voltage >= BATTERY_VOLTAGE_STANDARD) + { + check_count++; + if (check_count >= 30) + { + battery_ok = true; + auto_test_save_to_file(TEST_FAIL_FILE); + check_count = 0; + } + } + else + { + check_count = 0; + battery_ok = false; + } + } + + if (battery_ok) + { + s_auto_test.test_result.battery_ok = true; + } +} + + +//可选检查项:ACC,一次失败即失败 +static void auto_test_check_acc(void) +{ + if ((s_auto_test.test_result.acc_on_count < (s_auto_test.test_result.test_time_seconds/REALY_ACC_PERIOD - 1)) || (s_auto_test.test_result.acc_off_count < (s_auto_test.test_result.test_time_seconds/REALY_ACC_PERIOD - 1))) + { + s_auto_test.test_result.acc_fail = true; + s_auto_test.test_result.optional_items_test_fail = true; + } +} + +//必选检查项:重启次数,一次失败即失败 +static void auto_test_check_reboot(void) +{ + s_auto_test.test_result.reboot_for_power_counts = system_state_get_reboot_counts(GM_REBOOT_POWER_ON); + s_auto_test.test_result.reboot_for_net_counts = system_state_get_reboot_counts(GM_REBOOT_GPRS); + s_auto_test.test_result.reboot_for_upgrade_counts = system_state_get_reboot_counts(GM_REBOOT_UPDATE); + s_auto_test.test_result.reboot_for_exception_counts = system_state_get_reboot_counts(GM_RREBOOT_UNKNOWN); + + //首次重启不知道原因,归结为意外重 + if(s_auto_test.test_result.reboot_for_exception_counts > 1) + { + s_auto_test.test_result.reboot_counts_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_exception_reboot!,counts=%d",s_auto_test.test_result.reboot_for_exception_counts); + } + + if(s_auto_test.test_result.reboot_for_power_counts > 20) + { + s_auto_test.test_result.reboot_counts_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_power_reboot!,counts=%d",s_auto_test.test_result.reboot_for_power_counts); + } + + + if(s_auto_test.test_result.reboot_for_net_counts > 20) + { + s_auto_test.test_result.reboot_counts_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_net_reboot!,counts=%d",s_auto_test.test_result.reboot_for_net_counts); + } + + + if(s_auto_test.test_result.reboot_for_upgrade_counts > 10) + { + s_auto_test.test_result.reboot_counts_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_net_upgrade_reboot!,counts=%d",s_auto_test.test_result.reboot_for_upgrade_counts); + } +} + +//必选检查项:GPS,一次失败即失败 +static void auto_test_check_gps_location(void) +{ + float snr_avg = 0; + if (gps_is_fixed() && s_auto_test.test_result.test_time_seconds > SECONDS_PER_MIN) + { + float snr[5] = {0}; + U8 index = 0; + + const SNRInfo* snr_info = gps_get_snr_array(); + for(index = 0;index < 5;index++) + { + snr[index] = snr_info[index].snr; + //LOG_TEST("SNR:%f",snr[index]); + } + snr_avg = applied_math_avage(snr,5); + //LOG_TEST("snr_avg:%f",snr[index]); + s_auto_test.test_result.snr_avg = (s_auto_test.test_result.snr_avg * s_auto_test.test_result.snr_counts + snr_avg)/(s_auto_test.test_result.snr_counts + 1); + //LOG_TEST("test_result.snr_avg:%f",snr[index]); + s_auto_test.test_result.snr_counts++; + if (s_auto_test.test_result.snr_avg < 25) + { + s_auto_test.test_result.gps_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_gps_location1!"); + } + + s_auto_test.test_result.first_fix_time = gps_get_fix_time(); + if (s_auto_test.test_result.first_fix_time > 2*SECONDS_PER_MIN) + { + s_auto_test.test_result.gps_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_gps_location2!"); + } + } +} + +static void auto_test_check_gsensor(void) +{ + s_auto_test.test_result.g_sensor_error_counts = g_sensor_get_error_count(); + s_auto_test.test_result.g_sensor_shake_counts = g_sensor_get_shake_event_count_when_read(); + if (s_auto_test.test_result.g_sensor_error_counts > 10) + { + s_auto_test.test_result.g_sensor_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_gsensor because of read error!"); + } + + if (GM_SYSTEM_STATE_SLEEP == system_state_get_work_state()) + { + s_auto_test.test_result.g_sensor_sleep_time++; + + s_auto_test.test_result.g_sensor_fail = true; + s_auto_test.test_result.required_items_test_fail = true; + LOG_TEST("Failed to auto_test_check_gsensor because of sleep!"); + } +} + +static U32 auto_test_calc_hashnr(const u8 *key, u32 len) +{ + const u8 *end = key + len; + u32 hash = 0;; + + for (hash = 0; key < end; key++) + { + hash *= 16777619; + hash ^= (u32) *(u8*) key; + } + return (hash); +} + +static void auto_test_check_chip_rid(void) +{ + u32 hashnr_rid[2] = {0}; + u8 chip_rid[20] = {0}; + GM_memset(chip_rid, 0x00, sizeof(chip_rid)); + GM_memset(hashnr_rid, 0x00, sizeof(hashnr_rid)); + if (0 == GM_GetChipRID(chip_rid)) + { + hashnr_rid[0] = auto_test_calc_hashnr(&chip_rid[0], 8); + hashnr_rid[1] = auto_test_calc_hashnr(&chip_rid[8], 8); + GM_snprintf(s_auto_test.test_result.chip_rid,sizeof(s_auto_test.test_result.chip_rid),"%08X%08X,%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", + hashnr_rid[0], hashnr_rid[1], chip_rid[0], chip_rid[1], chip_rid[2], chip_rid[3], chip_rid[4],chip_rid[5], chip_rid[6], chip_rid[7], chip_rid[8], + chip_rid[9], chip_rid[10], chip_rid[11], chip_rid[12], chip_rid[13], chip_rid[14], chip_rid[15]); + } +} + +static bool is_device_05(ConfigDeviceTypeEnum dev_type) +{ + switch(dev_type) + { + case DEVICE_GS05A: + case DEVICE_GS05B: + case DEVICE_GS05F: + case DEVICE_GS05I: + case DEVICE_GS05H: + return true; + + default: + return false; + } +} + +void auto_test_repair_ramp(void) +{ + l1cal_rampTable_T ramp; + u16 nvLib; + s32 result; + u8 index = 0; + ConfigDeviceTypeEnum dev_type = DEVICE_NONE; + JsonObject* p_json_log = json_create(); + bool need_repair = false; + + config_service_get(CFG_DEVICETYPE, TYPE_SHORT, &dev_type, sizeof(U16)); + json_add_string(p_json_log, "event", "repair ramp"); + + //850 + nvLib = GM_ReadNvramLid(NVRAM_EF_L1_RAMPTABLE_GSM850_LID); + GM_ReadWriteNvram(1, nvLib, 1, &ramp, sizeof(ramp), &result); + + for (index=0; index<15; index++) + { + if (is_device_05(dev_type) && ramp.rampData.power[index] > 520) + { + json_add_int(p_json_log, "GSM850", index); + json_add_int(p_json_log, "power", ramp.rampData.power[index]); + ramp.rampData.power[index] = 520; + need_repair = true; + } + else if (!is_device_05(dev_type) && ramp.rampData.power[index] > 540) + { + json_add_int(p_json_log, "GSM850", index); + json_add_int(p_json_log, "power", ramp.rampData.power[index]); + ramp.rampData.power[index] = 540; + need_repair = true; + } + else + { + LOG(INFO,"GSM850,power[%d]:%d",index,ramp.rampData.power[index]); + } + } + + GM_ReadWriteNvram(0, nvLib, 1, &ramp, sizeof(ramp), &result); + + //900 + nvLib = GM_ReadNvramLid(NVRAM_EF_L1_RAMPTABLE_GSM900_LID); + GM_ReadWriteNvram(1, nvLib, 1, &ramp, sizeof(ramp), &result); + + for (index=0; index<15; index++) + { + if (is_device_05(dev_type) && ramp.rampData.power[index] > 520) + { + json_add_int(p_json_log, "GSM900", index); + json_add_int(p_json_log, "power", ramp.rampData.power[index]); + ramp.rampData.power[index] = 520; + need_repair = true; + } + else if (!is_device_05(dev_type) && ramp.rampData.power[index] > 540) + { + json_add_int(p_json_log, "GSM900", index); + json_add_int(p_json_log, "power", ramp.rampData.power[index]); + ramp.rampData.power[index] = 540; + need_repair = true; + } + else + { + LOG(INFO,"GSM900,power[%d]:%d",index,ramp.rampData.power[index]); + } + } + + GM_ReadWriteNvram(0, nvLib, 1, &ramp, sizeof(ramp), &result); + + //1800 + nvLib = GM_ReadNvramLid(NVRAM_EF_L1_RAMPTABLE_DCS1800_LID); + GM_ReadWriteNvram(1, nvLib, 1, &ramp, sizeof(ramp), &result); + + for (index=0; index<15; index++) + { + if (ramp.rampData.power[index] > 620) + { + json_add_int(p_json_log, "DCS1800", index); + json_add_int(p_json_log, "power", ramp.rampData.power[index]); + ramp.rampData.power[index] = 620; + need_repair = true; + } + else + { + LOG(INFO,"DCS1800,power[%d]:%d",index,ramp.rampData.power[index]); + } + } + + GM_ReadWriteNvram(0, nvLib, 1, &ramp, sizeof(ramp), &result); + + //1900 + nvLib = GM_ReadNvramLid(NVRAM_EF_L1_RAMPTABLE_PCS1900_LID); + GM_ReadWriteNvram(1, nvLib, 1, &ramp, sizeof(ramp), &result); + + for (index=0; index<15; index++) + { + if (ramp.rampData.power[index] > 620) + { + json_add_int(p_json_log, "PCS1900", index); + json_add_int(p_json_log, "power", ramp.rampData.power[index]); + ramp.rampData.power[index] = 620; + need_repair = true; + } + else + { + LOG(INFO,"PCS1900,power[%d]:%d",index,ramp.rampData.power[index]); + } + } + + if (need_repair) + { + GM_ReadWriteNvram(0, nvLib, 1, &ramp, sizeof(ramp), &result); + log_service_upload(INFO, p_json_log); + hard_ware_reboot(GM_REBOOT_CHECKPARA,5); + } + else + { + json_destroy(p_json_log); + p_json_log = NULL; + } +} + + diff --git a/src/bms.c b/src/bms.c new file mode 100644 index 0000000..59b897b --- /dev/null +++ b/src/bms.c @@ -0,0 +1,120 @@ +#include "bms.h" +#include "uart.h" +#include "error_code.h" +#include "gm_stdlib.h" +#include "command.h" +#include "log_service.h" + + +#define BMS_MSG_MAX_LEN 1024 + +GM_ERRCODE bms_uart_receive_data(char* p_cmd, u16 cmd_len, char* p_rsp, void * pmsg) +{ + char buf[BMS_MSG_MAX_LEN] = { 0 }; + U16 index = 0; + + if ((2*cmd_len + 1) >= BMS_MSG_MAX_LEN) + { + return; + } + + for (index = 0; index < cmd_len; ++index) + { + GM_snprintf(buf + 2*index, BMS_MSG_MAX_LEN - 2*index, "%02X", p_cmd[index]); + } + + uart_write(GM_UART_DEBUG, (U8*)buf, GM_strlen(buf)); + uart_write(GM_UART_DEBUG, "\n", 1); + + return GM_SUCCESS; +} + + +GM_ERRCODE bms_msg_receive(char *p_cmd, u16 cmd_len) +{ + if (NULL == p_cmd) + { + return GM_PARAM_ERROR; + } + + if ((p_cmd[0] != 0x3A || (p_cmd[1] != 0x16) || (p_cmd[cmd_len-2] != 0x0D) || (p_cmd[cmd_len-1] != 0x0A))) + { + return GM_PARAM_ERROR; + } + + uart_write(GM_UART_DEBUG,"\n[SEND]:", sizeof("\n[SEND]:")-1); + bms_uart_receive_data(p_cmd,cmd_len,NULL,NULL); + + uart_write(GM_UART_BMS,p_cmd, cmd_len); + + return GM_SUCCESS; +} + + + +GM_ERRCODE bms_cmd_write(char *cmd, u8 len) +{ + u8 bms_buff[50]; + u8 idx = 0; + u8 index = 0; + u16 check_sum = 0; + + //LOG(INFO, "bms_cmd_write cmd = %02X", cmd); + if (NULL == cmd) + { + return GM_PARAM_ERROR; + } + GM_memset(bms_buff, 0x00, sizeof(bms_buff)); + bms_buff[idx++] = 0x3A; + bms_buff[idx++] = 0x16; + bms_buff[idx++] = cmd[0]; + if (len > 1) + { + bms_buff[idx++] = len - 1; + for(index=1; index> 8) & 0xFF; + bms_buff[idx++] = 0x0D; + bms_buff[idx++] = 0x0A; + + uart_write(GM_UART_DEBUG,"\n[SEND]:", sizeof("\n[SEND]:")-1); + bms_uart_receive_data(bms_buff,idx,NULL,NULL); + + uart_write(GM_UART_BMS,bms_buff, idx); + + return GM_SUCCESS; +} + + + +GM_ERRCODE bms_create(void) +{ + uart_open_port(GM_UART_BMS, BAUD_RATE_LOW, 0); + + return GM_SUCCESS; +} + + +GM_ERRCODE bms_destroy(void) +{ + uart_close_port(GM_UART_BMS); + + return GM_SUCCESS; +} + + diff --git a/src/call.c b/src/call.c new file mode 100644 index 0000000..564587d --- /dev/null +++ b/src/call.c @@ -0,0 +1,74 @@ +#include "call.h" + + +static GM_ERRCODE gm_call_status_call_back(void* call_status); + + +static GM_ERRCODE gm_call_status_call_back(void* call_status) +{ + int* status =(int*) call_status; + + switch(*status) + { + case 0: + //phone calling + break; + case 1: + //call OK + break; + case 2: + //call hang + break; + } +} + + + +static GM_ERRCODE gm_call_receive_call_back(void* evt) +{ + u8* phone_number =(u8*) evt; + + printf("RING:%.20s", phone_number); + + GM_CallAnswer(gm_call_status_call_back); + + return GM_SUCCESS; +} + + + +GM_ERRCODE gm_make_phone_call(const u8 *dist_number) +{ + if (NULL == dist_number) + { + return GM_PARAM_ERROR; + } + + if ((GSM_CREG_REGISTER_LOCAL != gm_gsm_get_creg_status()) && (GSM_CREG_REGISTER_ROAM != gm_gsm_get_creg_status())) + { + return GM_ERROR_STATUS; + } + + GM_MakeCall(dist_number, gm_call_status_call_back); + + return GM_SUCCESS; +} + + + +GM_ERRCODE call_create(void) +{ + GM_RegisterCallBack(GM_CB_CALL_RECEIVE, gm_call_receive_call_back); + + return GM_SUCCESS; +} + + +GM_ERRCODE call_destroy(void) +{ + GM_RegisterCallBack(GM_CB_CALL_RECEIVE, 0); + + return GM_SUCCESS; +} + + diff --git a/src/circular_queue.c b/src/circular_queue.c new file mode 100644 index 0000000..9e0ca99 --- /dev/null +++ b/src/circular_queue.c @@ -0,0 +1,239 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: circular_queue.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-07 + * Description: 循环队列,存放整型和浮点型数据,循环覆盖写 + * Others: + * Function List: + 1. 创建circular_queue + 2. 销毁circular_queue + 3. 获取队列容量 + 4. 队列是否为空 + 5. 清空队列 + 6. 队列是否已满 + 7. 获取队列长度 + 8. 入队 + 9. 出队 + 10.获取队列头元素 + 11.获取队列尾元素 + 12.获取队列第n个元素 + * History: + 1. Date: 2019-03-07 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include "circular_queue.h" +#include "gm_memory.h" + +GM_ERRCODE circular_queue_create(PCircularQueue p_queue, const U16 capacity, const GM_QUEUE_TYPE type) +{ + //多申请1个单元,留个空 + p_queue->capacity = (capacity + 1); + if (GM_QUEUE_TYPE_FLOAT == type) + { + p_queue->f_buf = (float*)GM_MemoryAlloc(sizeof(float) * p_queue->capacity); + if (NULL == p_queue->f_buf) + { + return GM_MEM_NOT_ENOUGH; + } + } + else + { + p_queue->i_buf = (S32*)GM_MemoryAlloc(sizeof(S32) * p_queue->capacity); + if (NULL == p_queue->i_buf) + { + return GM_MEM_NOT_ENOUGH; + } + } + p_queue->head = 0; + p_queue->tail = 0; + return GM_SUCCESS; +} + +void circular_queue_destroy(PCircularQueue p_queue, const GM_QUEUE_TYPE type) +{ + if (GM_QUEUE_TYPE_FLOAT == type) + { + GM_MemoryFree(p_queue->f_buf); + p_queue->f_buf = NULL; + p_queue->head = 0; + p_queue->tail = 0; + } + else + { + GM_MemoryFree(p_queue->i_buf); + p_queue->i_buf = NULL; + p_queue->head = 0; + p_queue->tail = 0; + } +} + +U16 circular_queue_get_capacity(const PCircularQueue p_queue) +{ + return (p_queue->capacity - 1); +} + +bool circular_queue_is_empty(const PCircularQueue p_queue) +{ + return (p_queue->head == p_queue->tail); +} + +void circular_queue_empty(PCircularQueue p_queue) +{ + p_queue->head = 0; + p_queue->tail = 0; +} + +bool circular_queue_is_full(const PCircularQueue p_queue) +{ + return (p_queue->head == ((p_queue->tail + 1) % p_queue->capacity)); +} + +U16 circular_queue_get_len(const PCircularQueue p_queue) +{ + return ((p_queue->tail + p_queue->capacity - p_queue->head) % p_queue->capacity); +} + +void circular_queue_en_queue_f(PCircularQueue p_queue, float value) +{ + //如果队列已满,队头被覆盖 + if (circular_queue_is_full(p_queue)) + { + p_queue->head = (p_queue->head + 1) % p_queue->capacity; + } + + *(p_queue->f_buf + p_queue->tail) = value; + p_queue->tail = (p_queue->tail + 1) % p_queue->capacity; +} +void circular_queue_en_queue_i(PCircularQueue p_queue, S32 value) +{ + //如果队列已满,队头被覆盖 + if (circular_queue_is_full(p_queue)) + { + p_queue->head = (p_queue->head + 1) % p_queue->capacity; + } + + *(p_queue->i_buf + p_queue->tail) = value; + p_queue->tail = (p_queue->tail + 1) % p_queue->capacity; +} + +bool circular_queue_de_queue_f(PCircularQueue p_queue, float* p_value) +{ + if (!circular_queue_is_empty(p_queue)) + { + *p_value = *(p_queue->f_buf + p_queue->head); + p_queue->head = (p_queue->head + 1) % p_queue->capacity; + return true; + } + else + { + return false; + } +} + +bool circular_queue_de_queue_i(PCircularQueue p_queue, S32* p_value) +{ + if (!circular_queue_is_empty(p_queue)) + { + *p_value = *(p_queue->i_buf + p_queue->head); + p_queue->head = (p_queue->head + 1) % p_queue->capacity; + return true; + } + else + { + return false; + } +} + +bool circular_queue_get_head_f(const PCircularQueue p_queue, float* p_value) +{ + if (!circular_queue_is_empty(p_queue)) + { + *p_value = *(p_queue->f_buf + p_queue->head); + return true; + } + else + { + return false; + } +} + +bool circular_queue_get_head_i(const PCircularQueue p_queue, S32* p_value) +{ + if (!circular_queue_is_empty(p_queue)) + { + *p_value = *(p_queue->i_buf + p_queue->head); + return true; + } + else + { + return false; + } +} + +bool circular_queue_get_tail_f(const PCircularQueue p_queue, float* p_value) +{ + if (!circular_queue_is_empty(p_queue)) + { + *p_value = *(p_queue->f_buf + (p_queue->tail - 1 + p_queue->capacity) % p_queue->capacity); + return true; + } + else + { + return false; + } +} +bool circular_queue_get_tail_i(const PCircularQueue p_queue, S32* p_value) +{ + if (!circular_queue_is_empty(p_queue)) + { + *p_value = *(p_queue->i_buf + (p_queue->tail - 1 + p_queue->capacity) % p_queue->capacity); + return true; + } + else + { + return false; + } +} + +bool circular_queue_get_by_index_f(const PCircularQueue p_queue, const U16 index, float* p_value) +{ + if (index >= circular_queue_get_capacity(p_queue) || index >= circular_queue_get_len(p_queue)) + { + return false; + } + if (!circular_queue_is_empty(p_queue)) + { + *p_value = *(p_queue->f_buf + (p_queue->tail - 1 - index + 2 * p_queue->capacity) % p_queue->capacity); + return true; + } + else + { + return false; + } +} + +bool circular_queue_get_by_index_i(const PCircularQueue p_queue, const U16 index, S32* p_value) +{ + if (index >= circular_queue_get_capacity(p_queue) || index >= circular_queue_get_len(p_queue)) + { + return false; + } + if (!circular_queue_is_empty(p_queue)) + { + *p_value = *(p_queue->i_buf + (p_queue->tail - 1 - index + 2 * p_queue->capacity) % p_queue->capacity); + return true; + } + else + { + return false; + } +} + diff --git a/src/command.c b/src/command.c new file mode 100644 index 0000000..f7fcd6e --- /dev/null +++ b/src/command.c @@ -0,0 +1,2840 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: command.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-04-19 + * Description: + * Others: + * Function List: + 1. 创建command模块 + 2. 销毁command模块 + 3. command模块定时处理入口 + * History: + 1. Date: 2019-04-19 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include +#include +#include +#include +#include +#include "command.h" +#include "utility.h" +#include "gsm.h" +#include "applied_math.h" +#include "hard_ware.h" +#include "config_service.h" +#include "log_service.h" +#include "system_state.h" +#include "relay.h" +#include "gprs.h" +#include "gps_service.h" +#include "main.h" +#include "agps_service.h" +#include "gm_sms.h" +#include "g_sensor.h" +#include "auto_test.h" +#include "bms.h" + + +#pragma diag_suppress 870 + +#define CMD_NAME_MAX_LEN 11 + +typedef enum +{ + CMD_DEVICE_TYPE, + CMD_APN, + CMD_APN_INIT, + CMD_APNC, + CMD_AUTO_APN, + CMD_SERVER, + CMD_PROTOCOL, + CMD_UPLOAD_TIM, + CMD_GMT , + CMD_SYSTEM_RESET, + CMD_FACTORY_ALL, + CMD_FACTORY, + CMD_COLD_START, + CMD_RELAY, + CMD_PRELAY, + CMD_DYD, + CMD_HFYD, + CMD_GPSON, + CMD_GPSOFF, + CMD_PARAM, + CMD_WRITEIMEI, + CMD_IMEI, + CMD_ICCID, + CMD_IMSI, + CMD_WHERE, + CMD_STATUS, + CMD_LBS_ON, + CMD_LBS_UPLOAD_ONCE, + CMD_LANGUAGE, + CMD_HEARTBEAT_MIN, + CMD_HEARTBEAT_SEC, + CMD_HBEX, + CMD_OVER_SPEED, + CMD_VER, + CMD_SENSOR_PARA, + CMD_SHAKE_ALARM_SWITCH, + CMD_DEFMODE, + CMD_AUTO_DEFENCE_DELAY, + CMD_SHAKE_ALARM_PARA, + CMD_DEFENCE_ON, + CMD_DEFENCE_OFF, + CMD_BAT_ALM_SWITCH, + CMD_POWER_OFF_ALM_PARA, + CMD_MILEAGE, + CMD_JT808_LOGIN, + CMD_SLEEP_TIME, + CMD_123_POSITION, + CMD_LOG_LEVEL, + CMD_SOS, + CMD_CENTER, + CMD_GPRS_PARA, + CMD_STATIC_UPLOAD, + CMD_TEST, + CMD_EXIT, + CMD_RECORD, + CMD_RESULT, + CMD_PMTK, + CMD_BMS, + CMD_CMD_MAX +}CommandID; + +typedef struct +{ + char cmd_name[CMD_NAME_MAX_LEN]; + CommandID cmd_id; +}CommandInfo; + +static CommandInfo s_cmd_infos[CMD_CMD_MAX + 1] = +{ + {"DEVICETYPE",CMD_DEVICE_TYPE}, + {"APN",CMD_APN}, + {"APNINIT",CMD_APN_INIT}, + {"APNC",CMD_APNC}, + {"ASETAPN",CMD_AUTO_APN}, + {"GMNET",CMD_SERVER}, + {"PROTOCOL",CMD_PROTOCOL}, + {"TIMER",CMD_UPLOAD_TIM}, + {"GMT",CMD_GMT}, + {"RESET",CMD_SYSTEM_RESET}, + {"FACTORYALL",CMD_FACTORY_ALL}, + {"FACTORY",CMD_FACTORY}, + {"COLDSTART",CMD_COLD_START}, + {"RELAY",CMD_RELAY}, + {"PRELAY",CMD_PRELAY}, + {"DYD",CMD_DYD}, + {"HFYD",CMD_HFYD}, + {"GPSON",CMD_GPSON}, + {"GPSOFF",CMD_GPSOFF}, + {"PARAM",CMD_PARAM}, + {"GOOIMEI",CMD_WRITEIMEI}, + {"IMEI",CMD_IMEI}, + {"ICCID",CMD_ICCID}, + {"IMSI",CMD_IMSI}, + {"WHERE",CMD_WHERE}, + {"STATUS",CMD_STATUS}, + {"LBSON",CMD_LBS_ON}, + {"LBS",CMD_LBS_UPLOAD_ONCE}, + {"LANG",CMD_LANGUAGE}, + {"HBT",CMD_HEARTBEAT_MIN}, + {"HBTS",CMD_HEARTBEAT_SEC}, + {"HBEX",CMD_HBEX}, + {"SPEED",CMD_OVER_SPEED}, + {"VERSION",CMD_VER}, + {"GMVER",CMD_VER}, + {"SENSORSET",CMD_SENSOR_PARA}, + {"SENALM",CMD_SHAKE_ALARM_SWITCH}, + {"DEFMODE",CMD_DEFMODE}, + {"DEFENSE",CMD_AUTO_DEFENCE_DELAY}, + {"SENSOR",CMD_SHAKE_ALARM_PARA}, + {"000",CMD_DEFENCE_OFF}, + {"111",CMD_DEFENCE_ON}, + {"BATALM",CMD_BAT_ALM_SWITCH}, + {"POWERALM",CMD_POWER_OFF_ALM_PARA}, + {"MILEAGE",CMD_MILEAGE}, + {"LOGIN",CMD_JT808_LOGIN}, + {"SENDS",CMD_SLEEP_TIME}, + {"123",CMD_123_POSITION}, + {"LOGLEVEL",CMD_LOG_LEVEL}, + {"SOS",CMD_SOS}, + {"CENTER",CMD_CENTER}, + {"GPRSSET",CMD_GPRS_PARA}, + {"STATICREP",CMD_STATIC_UPLOAD}, + {"TEST",CMD_TEST}, + {"EXIT",CMD_EXIT}, + {"RECORD",CMD_RECORD}, + {"RESULT",CMD_RESULT}, + {"PMTK",CMD_PMTK}, + {"BMS",CMD_BMS}, +}; + +static CommandID get_cmd_id(const char* cmd_name); +static const char* set_success_rsp(CommandReceiveFromEnum from); +static const char* set_fail_rsp(CommandReceiveFromEnum from); +static const char* get_protocol_str(U16 lang,CommandReceiveFromEnum from,U8 protocol_type); +static const char* get_enable_str(U16 lang,CommandReceiveFromEnum from,bool is_on); +static char command_scan(const char* p_command, const char* p_format, ...); + +static CommandID get_cmd_id(const char* cmd_name) +{ + U8 index = 0; + for (index = 0; index < CMD_CMD_MAX + 1; ++index) + { + if (!GM_strcmp(cmd_name, s_cmd_infos[index].cmd_name)) + { + return s_cmd_infos[index].cmd_id; + } + } + return CMD_CMD_MAX; +} + +static const char set_success_rsp_en[] = "Exec Success."; +static const char set_success_rsp_ch[] = "设置成功"; +static const char set_fail_rsp_en[] = "Exec failure!"; +static const char set_fail_rsp_ch[] = "指令错误"; + +static const char* set_success_rsp(CommandReceiveFromEnum from) +{ + U16 lang = 0; + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &lang, sizeof(lang)); + + if (1 == lang && COMMAND_GPRS == from) + { + return set_success_rsp_ch; + } + else + { + return set_success_rsp_en; + } +} + +static const char* set_fail_rsp(CommandReceiveFromEnum from) +{ + U16 lang = 0; + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &lang, sizeof(lang)); + + if (1 == lang && COMMAND_GPRS == from) + { + return set_fail_rsp_ch; + } + else + { + return set_fail_rsp_en; + } +} + +static const char* get_protocol_str(U16 lang,CommandReceiveFromEnum from,U8 protocol_type) +{ + static char protocol_str[20] = {0}; + if (1 == lang && COMMAND_GPRS == from) + { + if (1 == protocol_type) + { + GM_strcpy(protocol_str, "谷米协议"); + } + else if(2 == protocol_type) + { + GM_strcpy(protocol_str, "康凯斯协议"); + } + else if(3 == protocol_type) + { + GM_strcpy(protocol_str, "部标808"); + } + else + { + GM_strcpy(protocol_str, "未知协议"); + } + + } + else + { + if (1 == protocol_type) + { + GM_strcpy(protocol_str, "GOOME"); + } + else if(2 == protocol_type) + { + GM_strcpy(protocol_str, "CONCOX"); + } + else if(3 == protocol_type) + { + GM_strcpy(protocol_str, "JT808"); + } + else + { + GM_strcpy(protocol_str, "unknown"); + } + } + return protocol_str; +} + +static const char* get_enable_str(U16 lang,CommandReceiveFromEnum from,bool is_on) +{ + static char is_on_str[20] = {0}; + + if (1 == lang && COMMAND_GPRS == from) + { + if(is_on) + { + GM_strcpy(is_on_str, "打开"); + } + else + { + GM_strcpy(is_on_str, "关闭"); + } + } + else + { + if(is_on) + { + GM_strcpy(is_on_str, "enable"); + } + else + { + GM_strcpy(is_on_str, "disable"); + } + } + return is_on_str; +} + +//0:关闭,1:未定位,2:已定位 +static const char* get_fixstate_str(U16 lang,CommandReceiveFromEnum from,GPSState state) +{ + static char is_on_str[20] = {0}; + + if (1 == lang && COMMAND_GPRS == from) + { + if(GM_GPS_OFF == state) + { + GM_strcpy(is_on_str, "关闭"); + } + else if(state >= GM_GPS_FIX_3D) + { + GM_strcpy(is_on_str, "已定位"); + } + else + { + GM_strcpy(is_on_str, "未定位"); + } + } + else + { + if(GM_GPS_OFF == state) + { + GM_strcpy(is_on_str, "close"); + } + else if(state >= GM_GPS_FIX_3D) + { + GM_strcpy(is_on_str, "fixed"); + } + else + { + GM_strcpy(is_on_str, "unfixed"); + } + } + return is_on_str; +} + +//0:运动,1:静止 +static const char* get_vehiclestate_str(U16 lang,CommandReceiveFromEnum from,VehicleState state) +{ + static char is_on_str[20] = {0}; + + if (1 == lang && COMMAND_GPRS == from) + { + if(VEHICLE_STATE_RUN == state) + { + GM_strcpy(is_on_str, "运动"); + } + else + { + GM_strcpy(is_on_str, "静止"); + } + } + else + { + if(VEHICLE_STATE_RUN == state) + { + GM_strcpy(is_on_str, "run"); + } + else + { + GM_strcpy(is_on_str, "static"); + } + } + return is_on_str; +} + +GM_ERRCODE command_on_receive_data(CommandReceiveFromEnum from, char* p_cmd, u16 cmd_len, char* p_rsp, void * pmsg) +{ + char cmd_name[CMD_NAME_MAX_LEN] = {0}; + char* p_cmd_content = NULL; + char para_num = 0; + CommandID cmd_id = CMD_CMD_MAX; + gm_sms_new_msg_struct* p_sms = NULL; + U16 lang = 0; + + if (NULL == p_cmd || 0 == cmd_len || cmd_len > (CMD_MAX_LEN - 1) || NULL == p_rsp) + { + return GM_PARAM_ERROR; + } + + p_cmd_content = (char*)GM_MemoryAlloc(cmd_len + 1); + GM_memcpy(p_cmd_content, p_cmd, cmd_len); + p_cmd_content[cmd_len] = 0; + LOG(INFO,"From %d received cmd:%s len:%d",from,p_cmd_content, cmd_len); + + util_remove_char((U8*)p_cmd_content,cmd_len,' '); + util_remove_char((U8*)p_cmd_content,cmd_len,'\r'); + util_remove_char((U8*)p_cmd_content,cmd_len,'\n'); + cmd_len = GM_strlen(p_cmd_content); + + + if (p_cmd_content[cmd_len -1] != '#') + { + GM_snprintf(p_rsp,CMD_MAX_LEN,"invalid cmd from %d,len=%d:%s",from,cmd_len,p_cmd_content); + GM_MemoryFree(p_cmd_content); + p_cmd_content = NULL; + return GM_PARAM_ERROR; + } + + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &lang, sizeof(lang)); + + command_scan((char*)p_cmd_content, "s", cmd_name); + util_string_upper((U8*)cmd_name,GM_strlen(cmd_name)); + cmd_id = get_cmd_id(cmd_name); + switch (cmd_id) + { + case CMD_DEVICE_TYPE: + { + char dev_type_str[16] = {0}; + ConfigDeviceTypeEnum dev_type_id = DEVICE_MAX; + para_num = command_scan((char*)p_cmd_content, "s;s", cmd_name,&dev_type_str); + if (para_num == 1) + { + config_service_get(CFG_DEVICETYPE, TYPE_SHORT, &dev_type_id, sizeof(U16)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "设备型号:%s", (char*)config_service_get_device_type(dev_type_id)); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Device type:%s", (char*)config_service_get_device_type(dev_type_id)); + } + } + else if(para_num == 2) + { + //设置设备类型 + dev_type_id = config_service_get_device_type_id(dev_type_str); + if (dev_type_id == DEVICE_NONE || dev_type_id >= DEVICE_MAX) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + config_service_set_device((ConfigDeviceTypeEnum)dev_type_id); + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_APN: + { + char apn_name[CMD_NAME_MAX_LEN] = {0}; + char user_name[CMD_NAME_MAX_LEN] = {0}; + char pass_word[CMD_NAME_MAX_LEN] = {0}; + + para_num = command_scan((char*)p_cmd_content, "s;sss", cmd_name,apn_name,user_name,pass_word); + + if (para_num == 1) + { + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "APN名称:%s,用户名:%s,密码:%s", (char*)config_service_get_pointer(CFG_APN_NAME),(char*)config_service_get_pointer(CFG_APN_USER),(char*)config_service_get_pointer(CFG_APN_PWD)); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "APN name:%s,user:%s,passpord:%s", (char*)config_service_get_pointer(CFG_APN_NAME),(char*)config_service_get_pointer(CFG_APN_USER),(char*)config_service_get_pointer(CFG_APN_PWD)); + } + } + else if(para_num == 2) + { + //设置APN + if(0 == GM_strlen(apn_name)) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + config_service_set(CFG_APN_NAME, TYPE_STRING, apn_name, GM_strlen(apn_name)); + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + system_state_set_gpss_reboot_reason("cmd apn param2"); + gprs_destroy(); + } + + } + else if(para_num == 3) + { + //设置APN + config_service_set(CFG_APN_NAME, TYPE_STRING, apn_name, GM_strlen(apn_name)); + config_service_set(CFG_APN_USER, TYPE_STRING, user_name, GM_strlen(user_name)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + system_state_set_gpss_reboot_reason("cmd apn param3"); + gprs_destroy(); + } + } + else if(para_num == 4) + { + //设置APN + config_service_set(CFG_APN_NAME, TYPE_STRING, apn_name, GM_strlen(apn_name)); + config_service_set(CFG_APN_USER, TYPE_STRING, user_name, GM_strlen(user_name)); + config_service_set(CFG_APN_PWD, TYPE_STRING, pass_word, GM_strlen(pass_word)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + system_state_set_gpss_reboot_reason("cmd apn param4"); + gprs_destroy(); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_APN_INIT: + { + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + //APN初始化 + config_service_set(CFG_APN_NAME, TYPE_STRING, APN_DEFAULT, GM_strlen((const char *)APN_DEFAULT)); + config_service_set(CFG_APN_USER, TYPE_STRING, APN_USER_DEFAULT, GM_strlen((const char *)APN_USER_DEFAULT)); + config_service_set(CFG_APN_PWD, TYPE_STRING, APN_USER_DEFAULT, GM_strlen((const char *)APN_USER_DEFAULT)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + system_state_set_gpss_reboot_reason("cmd apn init"); + gprs_destroy(); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_APNC: + { + u16 mcc = 0; + u16 mnc = 0; + para_num = command_scan((char*)p_cmd_content, "s;ii", &mcc,&mnc); + if(para_num == 3) + { + //设置移动国家代码和移动网络代码 + goome_auto_apn_struct auto_apn; + auto_apn.mcc = mcc; + auto_apn.mnc = mnc; + GM_AutoApnCheck(&auto_apn); + } + + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_AUTO_APN: + { + bool is_on = 0; + para_num = command_scan((char*)p_cmd_content, "s;w", cmd_name,&is_on); + if (para_num == 1) + { + config_service_get(CFG_APN_CHECK, TYPE_BOOL, &is_on, sizeof(is_on)); + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Auto APN:%s",get_enable_str(lang,from,is_on)); + } + else if(para_num == 2) + { + + config_service_set(CFG_APN_CHECK, TYPE_BOOL, &is_on, sizeof(is_on)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + system_state_set_gpss_reboot_reason("cmd auto apn"); + gprs_destroy(); + } + + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_SERVER: + { + char addr[GOOME_DNS_MAX_LENTH] = {0}; + U32 port = 0; + bool is_udp = false; + para_num = command_scan((char*)p_cmd_content, "s;siw", cmd_name,addr,&port,&is_udp); + + if (para_num == 1) + { + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "平台:%s", (char*)config_service_get_pointer(CFG_SERVERADDR)); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Server:%s", (char*)config_service_get_pointer(CFG_SERVERADDR)); + } + } + else if(para_num == 3 || para_num == 4) + { + //设置 + bool is_lock_ip = true; + char server_addr[64] = {0}; + config_service_get(CFG_SERVERLOCK, TYPE_BYTE, &is_lock_ip, sizeof(is_lock_ip)); + if (is_lock_ip) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + break; + } + GM_snprintf(server_addr, 31, "%s:%d", addr,port); + LOG(INFO,"Set server addr:%s",server_addr); + config_service_set(CFG_SERVERADDR, TYPE_STRING, server_addr, GM_strlen(server_addr)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + gps_service_change_config(); + gps_power_on(true); + g_sensor_reset_noshake_time(); + system_state_set_reported_gps_since_modify_ip(false); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_PROTOCOL: + { + U8 protocol_type = 0; + U8 protocol_ver = 0; + para_num = command_scan((char*)p_cmd_content, "s;ii", cmd_name,&protocol_type,&protocol_ver); + if (para_num == 1) + { + config_service_get(CFG_PROTOCOL, TYPE_BYTE, &protocol_type, sizeof(protocol_type)); + config_service_get(CFG_PROTOCOL_VER, TYPE_BYTE, &protocol_ver, sizeof(protocol_ver)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "协议:%s,协议版本:%d", get_protocol_str(lang,from,protocol_type),protocol_ver); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Protocol:%s,protocol version:%d", get_protocol_str(lang,from,protocol_type),protocol_ver); + } + } + else if(para_num == 2) + { + if(protocol_type >= PROTOCOL_MAX) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + config_service_set(CFG_PROTOCOL, TYPE_BYTE, &protocol_type, sizeof(protocol_type)); + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else if(para_num == 3) + { + if(protocol_type >= PROTOCOL_MAX || protocol_ver >= PROTOCOL_APP_MAX) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + config_service_set(CFG_PROTOCOL, TYPE_BYTE, &protocol_type, sizeof(protocol_type)); + config_service_set(CFG_PROTOCOL_VER, TYPE_BYTE, &protocol_ver, sizeof(protocol_ver)); + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_UPLOAD_TIM: + { + U16 upload_time = 0; + para_num = command_scan((char*)p_cmd_content, "s;i", cmd_name,&upload_time); + if (para_num == 1) + { + config_service_get(CFG_UPLOADTIME, TYPE_SHORT, &upload_time, sizeof(upload_time)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "上传间隔:%d秒", upload_time); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Upload interval:%d seconds", upload_time); + } + } + else if(para_num == 2) + { + //设置 + if(upload_time < CONFIG_UPLOAD_TIME_MIN || upload_time > CONFIG_UPLOAD_TIME_MAX) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + config_service_set(CFG_UPLOADTIME, TYPE_SHORT, &upload_time, sizeof(U16)); + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_GMT: + { + char east_or_west = 'E'; + S8 time_zone = 0; + para_num = command_scan((char*)p_cmd_content, "s;ci", cmd_name,&east_or_west,&time_zone); + + if (para_num == 1) + { + time_zone = config_service_get_zone(); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "时区:%d", time_zone); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Timezone:%d", time_zone); + } + } + else if(para_num == 3 || para_num == 4) + { + east_or_west = util_to_upper(east_or_west); + //设置 + if (east_or_west == 'E') + { + + } + else if (east_or_west == 'W') + { + time_zone *= -1; + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + break; + } + config_service_set(CFG_TIME_ZONE, TYPE_BYTE, &time_zone, sizeof(time_zone)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_SYSTEM_RESET: + { + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + //延时重启 + hard_ware_reboot(GM_REBOOT_CMD,5); + if (1 == lang && COMMAND_GPRS == from) + { + GM_memcpy(p_rsp, "系统正在重启", CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, "System is restaring", CMD_MAX_LEN); + } + } + else + { + //错误 + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_FACTORY_ALL: + case CMD_FACTORY: + { + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + //恢复出厂设置 + config_service_restore_factory_config(cmd_id == CMD_FACTORY_ALL); + agps_service_delele_file(); + gps_service_his_file_delete(); + system_state_reset(); + if (cmd_id == CMD_FACTORY_ALL) + { + auto_test_reset(); + } + + //延时重启 + hard_ware_reboot(GM_REBOOT_CMD,5); + if (1 == lang && COMMAND_GPRS == from) + { + GM_memcpy(p_rsp, "系统正在恢复出厂设置并重启", CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, "System is recovering and restarting.", CMD_MAX_LEN); + } + + } + else + { + //错误 + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_COLD_START: + { + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + agps_service_delele_file(); + gps_service_his_file_delete(); + system_state_set_cold_boot(true); + + //延时重启 + hard_ware_reboot(GM_REBOOT_CMD,5); + if (1 == lang && COMMAND_GPRS == from) + { + GM_memcpy(p_rsp, "设置下次启动为冷启动,重启中。。。", CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, "Set full cold start and restarting.", CMD_MAX_LEN); + } + + } + else + { + //错误 + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_RELAY: + case CMD_PRELAY: + { + U16 lang = 0; + bool is_on = true; + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &lang, sizeof(lang)); + para_num = command_scan((char*)p_cmd_content, "s;w", cmd_name,&is_on); + if (para_num == 1) + { + char is_on_str[10] = {0}; + is_on = system_state_get_device_relay_state(); + if (1 == lang && COMMAND_GPRS == from) + { + if(is_on) + { + GM_strcpy(is_on_str, "已断开"); + } + else + { + GM_strcpy(is_on_str, "未断开"); + } + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, "油电状态:%s", is_on_str); + } + else + { + if(is_on) + { + GM_strcpy(is_on_str, "ON"); + } + else + { + GM_strcpy(is_on_str, "OFF"); + } + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, " Relay:%s", is_on_str); + } + + } + else if(para_num == 2) + { + GM_ERRCODE ret = GM_SUCCESS; + if (is_on) + { + ret = relay_on(cmd_id == CMD_RELAY); + if (GM_SUCCESS == ret) + { + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, "断油电成功"); + } + else + { + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, "Succeed to cut off the oil and circut."); + } + } + else if(GM_WILL_DELAY_EXEC == ret) + { + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, "车辆正在高速行驶或者速度未知,断油电可能会引发事故,系统会在速度较低时自动执行断油电"); + } + else + { + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, "System will cut off the oil and circut when speed is safe."); + } + } + else + { + char fail_english[CMD_MAX_LEN] = "Exec failure!"; + char fail_chinese[CMD_MAX_LEN] = "断油电失败(设备故障)"; + if (0 == lang || COMMAND_SMS == from) + { + GM_memcpy(p_rsp, fail_english, GM_strlen(fail_english)); + } + else + { + GM_memcpy(p_rsp, fail_chinese, GM_strlen(fail_chinese)); + } + } + } + else + { + ret = relay_off(); + if (GM_SUCCESS == ret) + { + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, set_success_rsp(from),is_on); + } + else + { + char fail_chinese[CMD_MAX_LEN] = "恢复油电失败(设备故障)"; + if (1 == lang || COMMAND_GPRS == from) + { + GM_memcpy(p_rsp, fail_chinese, GM_strlen(fail_chinese)); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp_en, GM_strlen(set_fail_rsp_en)); + } + } + } + } + else + { + char wrong_command_rsp_chinese[CMD_MAX_LEN] = "指令格式错误,请修改后重试"; + if (1 == lang || COMMAND_GPRS == from) + { + GM_memcpy(p_rsp, wrong_command_rsp_chinese, GM_strlen(wrong_command_rsp_chinese)); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp_en, GM_strlen(set_fail_rsp_en)); + } + } + } + break; + + case CMD_HFYD: + { + U16 lang = 0; + bool is_on = true; + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &lang, sizeof(lang)); + para_num = command_scan((char*)p_cmd_content, "s;w", cmd_name,&is_on); + if (para_num == 1) + { + char is_on_str[10] = {0}; + is_on = system_state_get_device_relay_state(); + if (1 == lang && COMMAND_GPRS == from) + { + if(is_on) + { + GM_strcpy(is_on_str, "已断开"); + } + else + { + GM_strcpy(is_on_str, "未断开"); + } + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, "油电状态:%s", is_on_str); + } + else + { + if(is_on) + { + GM_strcpy(is_on_str, "ON"); + } + else + { + GM_strcpy(is_on_str, "OFF"); + } + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, " Relay:%s", is_on_str); + } + + } + else if(para_num == 2) + { + GM_ERRCODE ret = GM_SUCCESS; + if (! is_on) + { + ret = relay_off(); + } + if (GM_SUCCESS == ret) + { + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, set_success_rsp(from),is_on); + } + else + { + char fail_chinese[CMD_MAX_LEN] = "恢复油电失败(设备故障)"; + if (1 == lang || COMMAND_GPRS == from) + { + GM_memcpy(p_rsp, fail_chinese, GM_strlen(fail_chinese)); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp_en, GM_strlen(set_fail_rsp_en)); + } + } + } + else + { + char wrong_command_rsp_chinese[CMD_MAX_LEN] = "指令格式错误,请修改后重试"; + if (1 == lang || COMMAND_GPRS == from) + { + GM_memcpy(p_rsp, wrong_command_rsp_chinese, GM_strlen(wrong_command_rsp_chinese)); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp_en, GM_strlen(set_fail_rsp_en)); + } + } + } + break; + + case CMD_DYD: + { + U16 lang = 0; + bool is_on = true; + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &lang, sizeof(lang)); + para_num = command_scan((char*)p_cmd_content, "s;w", cmd_name,&is_on); + if (para_num == 1) + { + char is_on_str[10] = {0}; + is_on = system_state_get_device_relay_state(); + if (1 == lang && COMMAND_GPRS == from) + { + if(is_on) + { + GM_strcpy(is_on_str, "已断开"); + } + else + { + GM_strcpy(is_on_str, "未断开"); + } + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, "油电状态:%s", is_on_str); + } + else + { + if(is_on) + { + GM_strcpy(is_on_str, "ON"); + } + else + { + GM_strcpy(is_on_str, "OFF"); + } + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, " Relay:%s", is_on_str); + } + + } + else if(para_num == 2) + { + GM_ERRCODE ret = GM_SUCCESS; + if (is_on) + { + ret = relay_on(cmd_id == CMD_RELAY); + } + if (GM_SUCCESS == ret) + { + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, "断油电成功"); + } + else + { + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, "Succeed to cut off the oil and circut."); + } + } + else if(GM_WILL_DELAY_EXEC == ret) + { + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, "车辆正在高速行驶或者速度未知,断油电可能会引发事故,系统会在速度较低时自动执行断油电"); + } + else + { + GM_snprintf((char*)p_rsp,CMD_MAX_LEN, "System will cut off the oil and circut when speed is safe."); + } + } + else + { + char fail_english[CMD_MAX_LEN] = "Exec failure!"; + char fail_chinese[CMD_MAX_LEN] = "断油电失败(设备故障)"; + if (0 == lang || COMMAND_SMS == from) + { + GM_memcpy(p_rsp, fail_english, GM_strlen(fail_english)); + } + else + { + GM_memcpy(p_rsp, fail_chinese, GM_strlen(fail_chinese)); + } + } + } + else + { + char wrong_command_rsp_chinese[CMD_MAX_LEN] = "指令格式错误,请修改后重试"; + if (1 == lang || COMMAND_GPRS == from) + { + GM_memcpy(p_rsp, wrong_command_rsp_chinese, GM_strlen(wrong_command_rsp_chinese)); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp_en, GM_strlen(set_fail_rsp_en)); + } + } + } + break; + + case CMD_GPSON: + { + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + gps_power_on(true); + g_sensor_reset_noshake_time(); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_GPSOFF: + { + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + bool gps_close = true; + config_service_set(CFG_GPS_CLOSE,TYPE_BOOL,&gps_close,sizeof(gps_close)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_PARAM: + { + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + char server[32] = {0}; + ConfigProtocolEnum protocol = config_service_get_app_protocol(); + U8 protocol_ver = 0; + U16 upload_time = 0; + U16 heartbeat_time = 0; + + config_service_get(CFG_SERVERADDR, TYPE_STRING, server, sizeof(server)); + config_service_get(CFG_PROTOCOL_VER, TYPE_BYTE, &protocol_ver, sizeof(protocol_ver)); + config_service_get(CFG_UPLOADTIME, TYPE_SHORT, &upload_time, sizeof(upload_time)); + config_service_get(CFG_HEART_INTERVAL, TYPE_SHORT, &heartbeat_time, sizeof(heartbeat_time)); + + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "服务器:%s,协议:%s,协议版本:%d,上传间隔:%d秒,心跳间隔:%d分钟,APN:%s", server,get_protocol_str(lang,from,protocol),protocol_ver,upload_time,heartbeat_time/SECONDS_PER_MIN,(char*)config_service_get_pointer(CFG_APN_NAME)); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Server:%s,protocol:%s,protocol version:%d,upload interval:%d seconds,heartbeat interval:%d minutes,APN:%s", server,get_protocol_str(lang,from,protocol),protocol_ver,upload_time,heartbeat_time/SECONDS_PER_MIN,(char*)config_service_get_pointer(CFG_APN_NAME)); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_WRITEIMEI: + { + char imei[32] = {0}; + para_num = command_scan((char*)p_cmd_content, "s;s", cmd_name,imei); + if(para_num == 2) + { + if (GM_SUCCESS == gsm_set_imei((U8*)imei)) + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_IMEI: + { + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + char imei[32] = {0}; + gsm_get_imei((U8*)imei); + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "IMEI:%s", imei); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_ICCID: + { + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + char iccid[32] = {0}; + gsm_get_iccid((U8*)iccid); + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "ICCID:%s", iccid); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_IMSI: + { + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + char imsi[32] = {0}; + gsm_get_imsi((U8*)imsi); + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "IMSI:%s", imsi); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_WHERE: + { + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + GPSData gps_data; + bool ret = true; + ret = gps_get_last_data(&gps_data); + if (true == ret) + { + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "纬度:%f,经度:%f,速度:%d公里/小时,方向:%d度", gps_data.lat,gps_data.lng,(U16)gps_data.speed,(U16)gps_data.course); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Latitude:%f,longitude:%f,speed:%d km/h,course:%d", gps_data.lat,gps_data.lng,(U16)gps_data.speed,(U16)gps_data.course); + } + } + else + { + U16 lang = 0; + char fail_english[CMD_MAX_LEN] = "GPS Unfixed,please retry later"; + char fail_chinese[CMD_MAX_LEN] = "GPS未定位,请稍后重试"; + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &lang, sizeof(lang)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_memcpy(p_rsp, fail_chinese, GM_strlen(fail_chinese)); + } + else + { + GM_memcpy(p_rsp, fail_english, GM_strlen(fail_english)); + } + } + + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_STATUS: + { + + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + float power_voltage = 0; + float battery_voltage = 0; + bool is_defence_by_hand = false; + bool acc_state = false; + + hard_ware_get_power_voltage(&power_voltage); + hard_ware_get_internal_battery_voltage(&battery_voltage); + hard_ware_get_acc_level(&acc_state); + config_service_get(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &is_defence_by_hand, sizeof(is_defence_by_hand)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "GSM信号强度:%d,GPRS状态:%d(0:掉线,1:上线),GPS:%s,电源电压:%.1fV,电池电压%.1fV,ACC:%d,运动传感器:%s,油电状态:%d(0:未断开,1:已断开),设防模式:%d(0:自动,1:手动),设防状态:%d(0:撤防,1:设防)", + gsm_get_csq(), + gprs_is_ok(), + get_fixstate_str(lang, from, gps_get_state()), + power_voltage, + battery_voltage, + acc_state, + get_vehiclestate_str(lang, from, system_state_get_vehicle_state()), + system_state_get_device_relay_state(), + is_defence_by_hand, + system_state_get_defence()); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "GSM:%d,GPRS:%d,GPS:%s,voltage:%.1fV,battery:%.1fV,ACC:%d,g_sensor:%s,relay:%d,defence mode:%d,defence state:%d", + gsm_get_csq(), + gprs_is_ok(), + get_fixstate_str(lang, from, gps_get_state()), + power_voltage, + battery_voltage, + acc_state, + get_vehiclestate_str(lang, from, system_state_get_vehicle_state()), + system_state_get_device_relay_state(), + is_defence_by_hand, + system_state_get_defence()); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_LBS_ON: + { + bool is_on = false; + u16 lbs_interval = 0; + u16 wait_gps_time = 0; + para_num = command_scan((char*)p_cmd_content, "s;wii", cmd_name,&is_on,&lbs_interval,&wait_gps_time); + if (para_num == 1) + { + config_service_get(CFG_IS_LBS_ENABLE, TYPE_BOOL, &is_on, sizeof(is_on)); + config_service_get(CFG_LBS_INTERVAL, TYPE_SHORT, &lbs_interval, sizeof(lbs_interval)); + config_service_get(CFG_WAIT_GPS_TIME, TYPE_SHORT, &wait_gps_time, sizeof(wait_gps_time)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "上传基站:%s,基站上传间隔:%d秒,等待GPS定位%d秒",get_enable_str(lang,from,is_on),lbs_interval,wait_gps_time); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "LBS:%s,upload interval:%d seconds,wait for GPS %d seconds",get_enable_str(lang,from,is_on),lbs_interval,wait_gps_time); + } + } + else if(para_num == 2) + { + config_service_set(CFG_IS_LBS_ENABLE, TYPE_BOOL, &is_on, sizeof(is_on)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else if(para_num == 3) + { + config_service_set(CFG_IS_LBS_ENABLE, TYPE_BOOL, &is_on, sizeof(is_on)); + config_service_set(CFG_LBS_INTERVAL, TYPE_SHORT, &lbs_interval, sizeof(lbs_interval)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else if(para_num == 4) + { + config_service_set(CFG_IS_LBS_ENABLE, TYPE_BOOL, &is_on, sizeof(is_on)); + config_service_set(CFG_LBS_INTERVAL, TYPE_SHORT, &lbs_interval, sizeof(lbs_interval)); + config_service_set(CFG_WAIT_GPS_TIME, TYPE_SHORT, &wait_gps_time, sizeof(wait_gps_time)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_LBS_UPLOAD_ONCE: + { + gps_service_push_lbs(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + break; + + case CMD_LANGUAGE: + { + U16 language = 0; + para_num = command_scan((char*)p_cmd_content, "s;i", cmd_name,&language); + if (para_num == 1) + { + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &language, sizeof(language)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "语言:%d(0:英语,1:中文)",language); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Language:%d(0:English,1:Chinese)",language); + } + } + else if(para_num == 2) + { + if (language <= 1) + { + config_service_set(CFG_LANGUAGE, TYPE_SHORT, &language, sizeof(language)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_HEARTBEAT_MIN: + case CMD_HEARTBEAT_SEC: + { + U16 heart_interval = 0; + para_num = command_scan((char*)p_cmd_content, "s;i", cmd_name,&heart_interval); + if (para_num == 1) + { + config_service_get(CFG_HEART_INTERVAL, TYPE_SHORT, &heart_interval, sizeof(heart_interval)); + if (CMD_HEARTBEAT_MIN == cmd_id) + { + heart_interval /= SECONDS_PER_MIN; + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "心跳间隔:%d分钟",heart_interval); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Heart beat interval:%d minutes",heart_interval); + } + } + else + { + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "心跳间隔:%d秒",heart_interval); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Heart beat interval:%d seconds",heart_interval); + } + } + } + else if(para_num == 2) + { + if (CMD_HEARTBEAT_MIN == cmd_id) + { + heart_interval *= SECONDS_PER_MIN; + } + //限制范围在1秒到10分钟 + if(heart_interval < GOOME_HEARTBEAT_MIN || heart_interval > GOOME_HEARTBEAT_MAX) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + config_service_set(CFG_HEART_INTERVAL, TYPE_SHORT, &heart_interval, sizeof(heart_interval)); + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_HBEX: + { + U8 heart_protocol = 0; + para_num = command_scan((char*)p_cmd_content, "s;i", cmd_name,&heart_protocol); + if (para_num == 1) + { + config_service_get(CFG_HBPROTOCOL, TYPE_BYTE, &heart_protocol, sizeof(heart_protocol)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "使用扩展心跳:%d(1:普通心跳,2:扩展心跳)",heart_protocol); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Extend protocol of heart beat:%d",heart_protocol); + } + } + else if(para_num == 2) + { + if (heart_protocol <= 1) + { + config_service_set(CFG_HBPROTOCOL, TYPE_BYTE, &heart_protocol, sizeof(heart_protocol)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_OVER_SPEED: + { + bool is_on = true; + U8 check_time = 0; + U8 speed_threshold = 0; + para_num = command_scan((char*)p_cmd_content, "s;wii", cmd_name,&is_on,&check_time,&speed_threshold); + if (para_num == 1) + { + config_service_get(CFG_SPEED_ALARM_ENABLE, TYPE_BOOL, &is_on, sizeof(is_on)); + config_service_get(CFG_SPEED_CHECK_TIME, TYPE_BYTE, &check_time, sizeof(check_time)); + config_service_get(CFG_SPEEDTHR, TYPE_BYTE, &speed_threshold, sizeof(speed_threshold)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "超速报警开关:%s,检测时间:%d秒,超速阈值:%d公里/小时",get_enable_str(lang, from, is_on),check_time,speed_threshold); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Speed alarm:%s,check time:%d seconds,speed threshold:%d km/h",get_enable_str(lang, from, is_on),check_time,speed_threshold); + } + } + else if(para_num == 2) + { + config_service_set(CFG_SPEED_ALARM_ENABLE, TYPE_BOOL, &is_on, sizeof(is_on)); + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + else if(para_num == 3) + { + if (check_time >=3 && check_time <= 100) + { + config_service_set(CFG_SPEED_ALARM_ENABLE, TYPE_BOOL, &is_on, sizeof(is_on)); + config_service_set(CFG_SPEED_CHECK_TIME, TYPE_BYTE, &check_time, sizeof(check_time)); + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + else if(para_num == 4) + { + if (check_time >=3 && check_time <= 100 && speed_threshold >=CONFIG_SPEEDTHR_MIN && speed_threshold <= CONFIG_SPEEDTHR_MAX) + { + config_service_set(CFG_SPEED_ALARM_ENABLE, TYPE_BOOL, &is_on, sizeof(is_on)); + config_service_set(CFG_SPEED_CHECK_TIME, TYPE_BYTE, &check_time, sizeof(check_time)); + config_service_set(CFG_SPEEDTHR, TYPE_BYTE, &speed_threshold, sizeof(speed_threshold)); + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_VER: + { + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + char kernel_version[80]; + ConfigDeviceTypeEnum dev_type_id = DEVICE_MAX; + + GM_memset(kernel_version, 0, sizeof(kernel_version)); + GM_ReleaseVerno((U8*)kernel_version); + GM_sprintf(kernel_version + GM_strlen(kernel_version), "(%s)",GM_BuildDateTime()); + config_service_get(CFG_DEVICETYPE, TYPE_SHORT, &dev_type_id, sizeof(U16)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "版本:%s(%s),内核:%s,校验码:%4X,设备型号:%s",VERSION_NUMBER,SW_APP_BUILD_DATE_TIME,kernel_version,system_state_get_bin_checksum(),(char*)config_service_get_device_type(dev_type_id)); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Version:%s(%s),kernel:%s,check sum:%4X,device type:%s",VERSION_NUMBER,SW_APP_BUILD_DATE_TIME,kernel_version,system_state_get_bin_checksum(),(char*)config_service_get_device_type(dev_type_id)); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + //SENSORSET,10,2,2,1#(唤醒时间,唤醒检测次数,震动报警检测次数,震动报警检测时间) + case CMD_SENSOR_PARA: + { + U8 awake_check_time = 0; + U8 awake_check_count = 0; + U8 shake_check_time = 0; + U8 shake_check_count = 0; + para_num = command_scan((char*)p_cmd_content, "s;iiii", cmd_name,&awake_check_time,&awake_check_count,&shake_check_count,&shake_check_time); + if (para_num == 1) + { + config_service_get(CFG_AWAKE_CHECK_TIME, TYPE_BYTE, &awake_check_time, sizeof(awake_check_time)); + config_service_get(CFG_AWAKE_COUNT, TYPE_BYTE, &awake_check_count, sizeof(awake_check_count)); + config_service_get(CFG_SHAKE_CHECK_TIME, TYPE_BYTE, &shake_check_time, sizeof(shake_check_time)); + config_service_get(CFG_SHAKE_COUNT, TYPE_BYTE, &shake_check_count, sizeof(shake_check_count)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "唤醒检测时间:%d秒,唤醒检测次数:%d,震动报警检测时间:%d秒,震动报警检测次数:%d",awake_check_time,awake_check_count,shake_check_time,shake_check_count); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Awake check time:%d seconds,awake check count:%d,shake alarm check time:%d seconds,shake alarm check count:%d",awake_check_time,awake_check_count,shake_check_time,shake_check_count); + } + } + else if(para_num == 2) + { + config_service_set(CFG_AWAKE_CHECK_TIME, TYPE_BYTE, &awake_check_time, sizeof(awake_check_time)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else if(para_num == 3) + { + config_service_set(CFG_AWAKE_CHECK_TIME, TYPE_BYTE, &awake_check_time, sizeof(awake_check_time)); + config_service_set(CFG_AWAKE_COUNT, TYPE_BYTE, &awake_check_count, sizeof(awake_check_count)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else if(para_num == 4) + { + config_service_set(CFG_AWAKE_CHECK_TIME, TYPE_BYTE, &awake_check_time, sizeof(awake_check_time)); + config_service_set(CFG_AWAKE_COUNT, TYPE_BYTE, &awake_check_count, sizeof(awake_check_count)); + config_service_set(CFG_SHAKE_CHECK_TIME, TYPE_BYTE, &shake_check_time, sizeof(shake_check_time)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else if(para_num == 5) + { + config_service_set(CFG_AWAKE_CHECK_TIME, TYPE_BYTE, &awake_check_time, sizeof(awake_check_time)); + config_service_set(CFG_AWAKE_COUNT, TYPE_BYTE, &awake_check_count, sizeof(awake_check_count)); + config_service_set(CFG_SHAKE_CHECK_TIME, TYPE_BYTE, &shake_check_time, sizeof(shake_check_time)); + config_service_set(CFG_SHAKE_COUNT, TYPE_BYTE, &shake_check_count, sizeof(shake_check_count)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_SHAKE_ALARM_SWITCH: + { + bool is_on = false; + para_num = command_scan((char*)p_cmd_content, "s;w", cmd_name,&is_on); + if (para_num == 1) + { + config_service_get(CFG_IS_SHAKE_ALARM_ENABLE, TYPE_BOOL, &is_on, sizeof(is_on)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "震动报警开关:%s",get_enable_str(lang, from, is_on)); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Shake alarm:%s",get_enable_str(lang, from, is_on)); + } + } + else if(para_num == 2) + { + + config_service_set(CFG_IS_SHAKE_ALARM_ENABLE, TYPE_BOOL, &is_on, sizeof(is_on)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_DEFMODE: + { + bool is_manual_defence = false; + para_num = command_scan((char*)p_cmd_content, "s;w", cmd_name,&is_manual_defence); + if (para_num == 1) + { + config_service_get(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &is_manual_defence, sizeof(is_manual_defence)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "设防模式:%d(0:自动设防,1:手动设防)",is_manual_defence); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Defence mode:%d(0:auto defence,1:manual defence)",is_manual_defence); + } + } + else if(para_num == 2) + { + + config_service_set(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &is_manual_defence, sizeof(is_manual_defence)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_AUTO_DEFENCE_DELAY: + { + U16 auto_defence_delay = 0; + para_num = command_scan((char*)p_cmd_content, "s;i", cmd_name,&auto_defence_delay); + if (para_num == 1) + { + config_service_get(CFG_AUTO_DEFENCE_DELAY, TYPE_SHORT, &auto_defence_delay, sizeof(auto_defence_delay)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "自动设防延时:%秒",auto_defence_delay); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Auto defence delay:%d seconds",auto_defence_delay); + } + } + else if(para_num == 2) + { + auto_defence_delay *= SECONDS_PER_MIN; + config_service_set(CFG_AUTO_DEFENCE_DELAY, TYPE_SHORT, &auto_defence_delay, sizeof(auto_defence_delay)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + //SENSOR,10,180,30#(震动报警检测时间10S,自动设防模式下震动报警延时180秒,震动报警间隔1800秒(30分钟)) + case CMD_SHAKE_ALARM_PARA: + { + //CMD_SENSOR_PARA也设置了这个参数 + U8 shake_check_time = 0; + U16 shake_alarm_delay = 0; + U16 shake_alarm_interval = 0; + para_num = command_scan((char*)p_cmd_content, "s;iii", cmd_name,&shake_check_time,&shake_alarm_delay,&shake_alarm_interval); + if (para_num == 1) + { + config_service_get(CFG_SHAKE_CHECK_TIME, TYPE_BYTE, &shake_check_time, sizeof(shake_check_time)); + config_service_get(CFG_SHAKE_ALARM_DELAY, TYPE_SHORT, &shake_alarm_delay, sizeof(shake_alarm_delay)); + config_service_get(CFG_SHAKE_ALARM_INTERVAL, TYPE_SHORT, &shake_alarm_interval, sizeof(shake_alarm_interval)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "震动报警检测时间%d秒,自动设防模式下震动报警延时%d秒,震动报警间隔%d分钟",shake_check_time,shake_alarm_delay,shake_alarm_interval/SECONDS_PER_MIN); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "shake alarm check time %d seconds,shake alarm delay %d seconds,report interval %d minutes",shake_check_time,shake_alarm_delay,shake_alarm_interval/SECONDS_PER_MIN); + } + } + else if(para_num == 2) + { + config_service_set(CFG_SHAKE_CHECK_TIME, TYPE_BYTE, &shake_check_time, sizeof(shake_check_time)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else if(para_num == 3) + { + config_service_set(CFG_SHAKE_CHECK_TIME, TYPE_BYTE, &shake_check_time, sizeof(shake_check_time)); + config_service_set(CFG_SHAKE_ALARM_DELAY, TYPE_SHORT, &shake_alarm_delay, sizeof(shake_alarm_delay)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else if(para_num == 4) + { + shake_alarm_interval *= SECONDS_PER_MIN; + config_service_set(CFG_SHAKE_CHECK_TIME, TYPE_BYTE, &shake_check_time, sizeof(shake_check_time)); + config_service_set(CFG_SHAKE_ALARM_DELAY, TYPE_SHORT, &shake_alarm_delay, sizeof(shake_alarm_delay)); + config_service_set(CFG_SHAKE_ALARM_INTERVAL, TYPE_SHORT, &shake_alarm_interval, sizeof(shake_alarm_interval)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_DEFENCE_ON: + { + bool is_defence_by_hand = false; + config_service_get(CFG_IS_MANUAL_DEFENCE,TYPE_BOOL, &is_defence_by_hand, sizeof(is_defence_by_hand)); + if (is_defence_by_hand) + { + system_state_set_defence(true); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + else + { + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "当前为自动设防模式,不能手动设防"); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Could not set defence on manually because of auto defence mode"); + } + } + } + break; + + case CMD_DEFENCE_OFF: + { + bool is_defence_by_hand = false; + config_service_get(CFG_IS_MANUAL_DEFENCE,TYPE_BOOL, &is_defence_by_hand, sizeof(is_defence_by_hand)); + if (is_defence_by_hand) + { + system_state_set_defence(false); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + else + { + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "当前为自动设防模式,不能手动撤防"); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Could not set defence off manually because of auto defence mode."); + } + } + } + break; + + case CMD_BAT_ALM_SWITCH: + { + u8 is_on = 0; + para_num = command_scan((char*)p_cmd_content, "s;w", cmd_name,&is_on); + if (para_num == 1) + { + config_service_get(CFG_LOWBATTALM_DISABLE, TYPE_BYTE, &is_on, sizeof(is_on)); + is_on = is_on ? 0: 1; // 0,打开,1:关闭 + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "内置电池电压过低报警开关:%s",get_enable_str(lang, from, is_on)); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Low voltage alarm of battery:%s",get_enable_str(lang, from, is_on)); + } + } + else if(para_num == 2) + { + is_on = is_on ? 0: 1; // 0,打开,1:关闭 + config_service_set(CFG_LOWBATTALM_DISABLE, TYPE_BYTE, &is_on, sizeof(is_on)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + //POWERALM,ON,10,100#(断电检测10秒,接电后100S后才能产生断电报警) POWERALM,OFF#关闭断电报警 + case CMD_POWER_OFF_ALM_PARA: + { + u8 is_on = 0; //0,打开,1:关闭 + U16 power_alarm_check_time = 0; + U16 power_off_alarm_delay = 0; + para_num = command_scan((char*)p_cmd_content, "s;wii", cmd_name,&is_on,&power_alarm_check_time,&power_off_alarm_delay); + if (para_num == 1) + { + + config_service_get(CFG_CUTOFFALM_DISABLE, TYPE_BYTE, &is_on, sizeof(is_on)); + is_on = is_on? 0: 1; //0,打开,1:关闭 + config_service_get(CFG_POWER_CHECK_TIME, TYPE_SHORT, &power_alarm_check_time, sizeof(power_alarm_check_time)); + config_service_get(CFG_POWER_CHARGE_MIN_TIME, TYPE_SHORT, &power_off_alarm_delay, sizeof(power_off_alarm_delay)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "断电报警:%s,断电检测%s秒,接电后%d秒后才会产生断电报警",get_enable_str(lang, from, is_on),power_alarm_check_time,power_off_alarm_delay); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Power off alarm:%s, check time:%d seconds,report power off alarm %d seconds later than power on",get_enable_str(lang, from, is_on),power_alarm_check_time,power_off_alarm_delay); + } + } + else if(para_num == 2) + { + is_on = is_on? 0: 1; //0,打开,1:关闭 + config_service_set(CFG_CUTOFFALM_DISABLE, TYPE_BYTE, &is_on, sizeof(is_on)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + + } + else if(para_num == 3) + { + is_on = is_on? 0: 1; //0,打开,1:关闭 + config_service_set(CFG_CUTOFFALM_DISABLE, TYPE_BYTE, &is_on, sizeof(is_on)); + config_service_set(CFG_POWER_CHECK_TIME, TYPE_SHORT, &power_alarm_check_time, sizeof(power_alarm_check_time)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + + } + else if(para_num == 4) + { + is_on = is_on? 0: 1; //0,打开,1:关闭 + config_service_set(CFG_CUTOFFALM_DISABLE, TYPE_BYTE, &is_on, sizeof(is_on)); + config_service_set(CFG_POWER_CHECK_TIME, TYPE_SHORT, &power_alarm_check_time, sizeof(power_alarm_check_time)); + config_service_set(CFG_POWER_CHARGE_MIN_TIME, TYPE_SHORT, &power_off_alarm_delay, sizeof(power_off_alarm_delay)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_MILEAGE: + { + S32 mileage = 0; + para_num = command_scan((char*)p_cmd_content, "s;i", cmd_name,&mileage); + if (para_num == 1) + { + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "里程:%d公里",system_state_get_mileage()); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Mileage:%d km",system_state_get_mileage()); + } + } + else if(para_num == 2) + { + system_state_set_mileage(mileage); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + //LOGIN,44,33,11111,0,0000099,1,粤B88888# + case CMD_JT808_LOGIN: + { + U16 province_id = 0; // 省域ID + U16 city_id = 0; // 市域ID + char oem_id[32] = {0}; // OEM商ID + U8 protocol_type = 0; // 部标协议类型(标准 补充) + char device_id[32] = {0}; // 终端ID + U8 license_color = 0; // 车牌颜色 + char license_number[32] = {0}; // 机动车号牌 + + para_num = command_scan((char*)p_cmd_content, "s;iisisis", cmd_name,&province_id,&city_id,oem_id,&protocol_type,device_id,&license_color,license_number); + if (para_num == 1) + { + config_service_get(CFG_JT_PROVINCE, TYPE_SHORT, &province_id, sizeof(province_id)); + config_service_get(CFG_JT_CITY, TYPE_SHORT, &city_id, sizeof(city_id)); + config_service_get(CFG_JT_OEM_ID, TYPE_STRING, oem_id, sizeof(oem_id)); + config_service_get(CFG_JT_AT_TYPE, TYPE_BYTE, &protocol_type, sizeof(protocol_type)); + config_service_get(CFG_JT_DEVICE_ID, TYPE_STRING, device_id, sizeof(device_id)); + config_service_get(CFG_JT_VEHICLE_COLOR, TYPE_BYTE, &license_color, sizeof(license_color)); + config_service_get(CFG_JT_VEHICLE_NUMBER, TYPE_STRING, license_number, sizeof(license_number)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "省域ID:%d,市域ID:%d,OEM商ID:%s,部标协议类型(标准 补充):%d,终端ID:%s,车牌颜色:%d,机动车号牌:%s",province_id,city_id,oem_id,protocol_type,device_id,license_color,license_number); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Province ID:%d,city ID:%d,OEM ID:%s,protocol type:%d,device ID:%s,license colour:%d,license number:%s",province_id,city_id,oem_id,protocol_type,device_id,license_color,license_number); + } + } + else if(para_num == 8) + { + + if(0 == device_id[0] || 0 == oem_id[0] || 0 == license_number[0] || protocol_type > GB_ATTYPE_CUSTOM) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + config_service_set(CFG_JT_PROVINCE, TYPE_SHORT, &province_id, sizeof(province_id)); + config_service_set(CFG_JT_CITY, TYPE_SHORT, &city_id, sizeof(city_id)); + config_service_set(CFG_JT_OEM_ID, TYPE_STRING, oem_id, sizeof(oem_id)); + config_service_set(CFG_JT_AT_TYPE, TYPE_BYTE, &protocol_type, sizeof(protocol_type)); + config_service_set(CFG_JT_DEVICE_ID, TYPE_STRING, device_id, sizeof(device_id)); + config_service_set(CFG_JT_VEHICLE_COLOR, TYPE_BYTE, &license_color, sizeof(license_color)); + config_service_set(CFG_JT_VEHICLE_NUMBER, TYPE_STRING, license_number, sizeof(license_number)); + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + + } + break; + + case CMD_SLEEP_TIME: + { + U16 sleep_time = 0; + para_num = command_scan((char*)p_cmd_content, "s;i", cmd_name,&sleep_time); + if (para_num == 1) + { + config_service_get(CFG_SLEEP_TIME, TYPE_SHORT, &sleep_time, sizeof(sleep_time)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "休眠时间:%d分钟",sleep_time); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Sleep time:%d minutes",sleep_time); + } + } + else if(para_num == 2) + { + if (sleep_time >= MINS_PER_HOUR) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + break; + } + config_service_set(CFG_SLEEP_TIME, TYPE_SHORT, &sleep_time, sizeof(sleep_time)); + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_123_POSITION: + { + if(! pmsg) break; + p_sms =(gm_sms_new_msg_struct*)pmsg; + + para_num = command_scan((char*)p_cmd_content, "s", cmd_name); + if (para_num == 1) + { + gps_service_push_position_request((u8*)&p_sms->asciiNum[0], GM_strlen(&p_sms->asciiNum[0]), (u8*)cmd_name, GM_strlen(cmd_name)); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_LOG_LEVEL: + { + LogLevel log_level = WARN; + LogLevel upload_level = FATAL; + para_num = command_scan((char*)p_cmd_content, "s;ii", cmd_name,&log_level,&upload_level); + if(para_num == 1) + { + log_service_get_level(&log_level, &upload_level); + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Log level:%d , Upload level:%d",log_level, upload_level); + } + else if(para_num == 2) + { + upload_level = FATAL; + if (log_level <= FATAL) + { + log_service_set_level(log_level, upload_level); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + else if(para_num == 3) + { + if (log_level <= FATAL && upload_level > DEBUG && upload_level <= FATAL) + { + log_service_set_level(log_level, upload_level); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_SOS: + { + //设置SOS号码[特权号] SOS,A,号码1,号码2,号码3# + // SOS,A,13800138000# 设置第1个SOS电话 + //SOS,D,1,2,3# + char add_or_del = 0; + char sos_num[3][16] = {"","",""}; //长度定义要与g_para一致 + + para_num = command_scan((char*)p_cmd_content, "s;csss", cmd_name,&add_or_del,sos_num[0],sos_num[1],sos_num[2]); + if(para_num < 2) + { + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "SOS号码:%s,%s,%s", + config_service_get_pointer(CFG_USER1_NUMBER),config_service_get_pointer(CFG_USER2_NUMBER), + config_service_get_pointer(CFG_USER3_NUMBER)); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "SOSNumber:%s,%s,%s", + config_service_get_pointer(CFG_USER1_NUMBER),config_service_get_pointer(CFG_USER2_NUMBER), + config_service_get_pointer(CFG_USER3_NUMBER)); + } + } + else if(para_num >= 3) + { + if(add_or_del == 'A' || add_or_del == 'a') + { + if(sos_num[0][0] != 0 && GM_strlen(sos_num[0])< sizeof(sos_num[0])) + { + config_service_set(CFG_USER1_NUMBER, TYPE_STRING, sos_num[0], GM_strlen((char *)sos_num[0])); + } + if(sos_num[1][0] != 0 && GM_strlen(sos_num[1])< sizeof(sos_num[1])) + { + config_service_set(CFG_USER2_NUMBER, TYPE_STRING, sos_num[1], GM_strlen((char *)sos_num[1])); + } + if(sos_num[2][0] != 0 && GM_strlen(sos_num[2])< sizeof(sos_num[2])) + { + config_service_set(CFG_USER3_NUMBER, TYPE_STRING, sos_num[2], GM_strlen((char *)sos_num[2])); + } + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + config_service_save_to_local(); + } + else if(add_or_del == 'D' || add_or_del == 'd') + { + U8 index = 0; + for (index = 0; index < 3; ++index) + { + S32 del_index = GM_atoi(sos_num[0]); + switch (del_index) + { + case 1: + { + config_service_set(CFG_USER1_NUMBER, TYPE_STRING, "", 0); + break; + } + case 2: + { + config_service_set(CFG_USER2_NUMBER, TYPE_STRING, "", 0); + break; + } + case 3: + { + config_service_set(CFG_USER3_NUMBER, TYPE_STRING, "", 0); + break; + } + + } + } + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_CENTER: + { + /* + CENTER,A,中心号码# + CENTER,D# + CENTER,A,13800138000# SET CENTER OK + CENTER,D# DEL CENTER OK + */ + char add_or_del = '\0'; + char cent_num[20] = {0}; + + para_num = command_scan((char*)p_cmd_content, "s;cs", cmd_name,&add_or_del,cent_num); + if(para_num < 2) + { + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "中心号码:%s",config_service_get_pointer(CFG_CENTER_NUMBER)); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "CenterNumber:%s",config_service_get_pointer(CFG_CENTER_NUMBER)); + } + } + else if(para_num == 2) + { + if(add_or_del == 'D' || add_or_del == 'd') + { + config_service_set(CFG_CENTER_NUMBER, TYPE_STRING, cent_num, 0); + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + else if(para_num == 3) + { + if((add_or_del == 'A' || add_or_del == 'a') && cent_num[0] != 0) + { + config_service_set(CFG_CENTER_NUMBER, TYPE_STRING, cent_num, GM_strlen((char *)cent_num)); + config_service_save_to_local(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_GPRS_PARA: + { + bool is_on = true; + config_service_get(CFG_APN_CHECK, TYPE_BOOL, &is_on, sizeof(is_on)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "自适应APN:%s,APN名称:%s,用户名:%s,密码:%s,服务器:%s",get_enable_str(lang,from,is_on),(char*)config_service_get_pointer(CFG_APN_NAME),(char*)config_service_get_pointer(CFG_APN_USER),(char*)config_service_get_pointer(CFG_APN_PWD),(char*)config_service_get_pointer(CFG_SERVERADDR)); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Auto APN:%s,APN name:%s,user:%s,passpord:%s,server:%s",get_enable_str(lang,from,is_on),(char*)config_service_get_pointer(CFG_APN_NAME),(char*)config_service_get_pointer(CFG_APN_USER),(char*)config_service_get_pointer(CFG_APN_PWD),(char*)config_service_get_pointer(CFG_SERVERADDR)); + } + } + break; + + case CMD_STATIC_UPLOAD: + { + bool is_on = false; + para_num = command_scan((char*)p_cmd_content, "s;w", cmd_name,&is_on); + if (para_num == 1) + { + config_service_get(CFG_IS_STATIC_UPLOAD, TYPE_BOOL, &is_on, sizeof(is_on)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "静止上传:%s",get_enable_str(lang, from, is_on)); + } + else + { + GM_snprintf((char*)p_rsp, CMD_MAX_LEN, "Upload when static:%s",get_enable_str(lang, from, is_on)); + } + } + else if(para_num == 2) + { + + config_service_set(CFG_IS_STATIC_UPLOAD, TYPE_BOOL, &is_on, sizeof(is_on)); + if(GM_SUCCESS != config_service_save_to_local()) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_TEST: + { + if (COMMAND_SMS == from) + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + else + { + auto_test_create(false); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_EXIT: + { + auto_test_destroy(); + GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + break; + + case CMD_RECORD: + { + auto_test_get_result(true,p_rsp); + } + break; + + case CMD_RESULT: + { + auto_test_get_result(false,p_rsp); + } + break; + + case CMD_PMTK: + { + char pmtk_cmd[20] = {0}; + char pmtk_para1[20] = {0}; + char pmtk_para2[20] = {0}; + char pmtk_para3[20] = {0}; + char pmtk_para4[20] = {0}; + char pmtk_para5[20] = {0}; + para_num = command_scan((char*)p_cmd_content, "s;ssssss", cmd_name,pmtk_cmd,pmtk_para1,pmtk_para2,pmtk_para3,pmtk_para4,pmtk_para5); + + if(para_num == 7) + { + char pmtk_cmd_full[100] = {0}; + GM_snprintf(pmtk_cmd_full, 50, "%s,%s,%s,%s,%s,%s", pmtk_cmd,pmtk_para1,pmtk_para2,pmtk_para3,pmtk_para4,pmtk_para5); + gps_write_mtk_cmd(pmtk_cmd_full); + } + else if(para_num == 6) + { + char pmtk_cmd_full[100] = {0}; + GM_snprintf(pmtk_cmd_full, 50, "%s,%s,%s,%s,%s", pmtk_cmd,pmtk_para1,pmtk_para2,pmtk_para3,pmtk_para4); + gps_write_mtk_cmd(pmtk_cmd_full); + } + else if(para_num == 5) + { + char pmtk_cmd_full[100] = {0}; + GM_snprintf(pmtk_cmd_full, 50, "%s,%s,%s,%s", pmtk_cmd,pmtk_para1,pmtk_para2,pmtk_para3); + gps_write_mtk_cmd(pmtk_cmd_full); + } + else if(para_num == 4) + { + char pmtk_cmd_full[50] = {0}; + GM_snprintf(pmtk_cmd_full, 50, "%s,%s,%s", pmtk_cmd,pmtk_para1,pmtk_para2); + gps_write_mtk_cmd(pmtk_cmd_full); + } + else if(para_num == 3) + { + char pmtk_cmd_full[50] = {0}; + GM_snprintf(pmtk_cmd_full, 50, "%s,%s", pmtk_cmd,pmtk_para1); + gps_write_mtk_cmd(pmtk_cmd_full); + } + else if(para_num == 2) + { + gps_write_mtk_cmd(pmtk_cmd); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + case CMD_BMS: + { + char cmdString[5]; + char cmd1String[5]; + char cmd[5]; + + GM_memset(cmdString, 0x00, sizeof(cmdString)); + GM_memset(cmd1String, 0x00, sizeof(cmd1String)); + para_num = command_scan((char*)p_cmd_content, "s;ss", cmd_name,&cmdString,&cmd1String); + if(para_num == 2) + { + if (2 == GM_strlen(cmdString)) + { + cmd[0] = (util_chr(cmdString[0]) << 4) | (util_chr(cmdString[1])); + } + else if (1 == GM_strlen(cmdString)) + { + cmd[0] = util_chr(cmdString[0]); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + break; + } + + bms_cmd_write(cmd,1); + //GM_memcpy(p_rsp, set_success_rsp(from), CMD_MAX_LEN); + } + else if (para_num == 3) + { + if (2 == GM_strlen(cmdString)) + { + cmd[0] = (util_chr(cmdString[0]) << 4) | (util_chr(cmdString[1])); + } + else if (1 == GM_strlen(cmdString)) + { + cmd[0] = util_chr(cmdString[0]); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + break; + } + + if (2 == GM_strlen(cmd1String)) + { + cmd[1] = (util_chr(cmd1String[0]) << 4) | (util_chr(cmd1String[1])); + } + else if (1 == GM_strlen(cmd1String)) + { + cmd[1] = util_chr(cmd1String[0]); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + break; + } + + bms_cmd_write(cmd,2); + } + else + { + GM_memcpy(p_rsp, set_fail_rsp(from), CMD_MAX_LEN); + } + } + break; + + default: + { + U16 lang = 0; + char wrong_command_rsp_english[CMD_MAX_LEN] = "Do not support the command!"; + char wrong_command_rsp_chinese[CMD_MAX_LEN] = "不支持此指令"; + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &lang, sizeof(lang)); + if (1 == lang && COMMAND_GPRS == from) + { + GM_memcpy(p_rsp, wrong_command_rsp_chinese, GM_strlen(wrong_command_rsp_chinese)); + } + else + { + GM_memcpy(p_rsp, wrong_command_rsp_english, GM_strlen(wrong_command_rsp_english)); + } + } + } + + do + { + JsonObject* p_log = json_create(); + json_add_string(p_log, "event", "command"); + json_add_int(p_log, "from", from); + json_add_string(p_log, "request", p_cmd_content); + json_add_string(p_log, "response", p_rsp); + log_service_upload(INFO, p_log); + }while (0); + + GM_MemoryFree(p_cmd_content); + p_cmd_content = NULL; + return GM_SUCCESS; +} + +//返回参数个数,-1——失败;0——无参数 +static char command_scan(const char* p_command, const char* p_format, ...) +{ + bool para_num = false; + bool optional = false; + const char* p_field = p_command; + char type = 0; + S32 value_32 = 0; + char* p_buf = NULL; + char switch_text[8] = {0}; + + U8 index = 0; + + + va_list ap; + va_start(ap, p_format); + + while (*p_format) + { + type = *p_format++; + + if (type == ';') + { + // 后面所有的域都是可选的 + optional = true; + continue; + } + + if (!p_field && !optional) + { + goto parse_error; + } + + switch (type) + { + case 'c': + { + char value = 0; + if (p_field && util_isprint((U8)*p_field) && *p_field != ',' && *p_field != '#') + { + value = *p_field; + para_num++; + } + *va_arg(ap, char*) = value; + } + break; + + case 'w': + { + index = 0; + if (p_field) + { + while (util_isprint((U8)*p_field) && *p_field != ',' && *p_field != '#') + { + switch_text[index++] = *p_field++; + } + } + switch_text[index] = 0; + + util_string_upper((U8*)switch_text,GM_strlen(switch_text)); + + if (!GM_strcmp(switch_text, "ON") || !GM_strcmp(switch_text, "1")) + { + *va_arg(ap, char*) = true; + para_num++; + } + else if (!GM_strcmp(switch_text, "OFF") || !GM_strcmp(switch_text, "0")) + { + *va_arg(ap, char*) = false; + para_num++; + } + else + { + } + + } + break; + + // Integer value, default 0 (S32). + case 'i': + { + value_32 = 0; + + if (p_field && util_isdigit(*p_field)) + { + char *endptr; + value_32 = util_strtol(p_field, &endptr); + if (util_isprint((U8)*endptr) && *endptr != ',' && *endptr != '#') + { + + goto parse_error; + } + para_num++; + } + *va_arg(ap, S32*) = value_32; + + } + break; + + // String value (char *). + case 's': + { + p_buf = va_arg(ap, char*); + + if (p_field && util_isprint((U8)*p_field) && *p_field != ',' && *p_field != '#') + { + while (util_isprint((U8)*p_field) && *p_field != ',' && *p_field != '#') + { + *p_buf++ = *p_field++; + } + para_num++; + } + *p_buf = '\0'; + } + break; + + default: + { + goto parse_error; + } + } + + /* Progress to the next p_field. */ + while (util_isprint((U8)*p_command) && *p_command != ',' && *p_command != '#') + { + p_command++; + } + /* Make sure there is a p_field there. */ + if (*p_command == ',') + { + p_command++; + p_field = p_command; + } + else + { + p_field = NULL; + } + } + +parse_error: + va_end(ap); + return para_num; +} + diff --git a/src/config_save.c b/src/config_save.c new file mode 100644 index 0000000..bb18792 --- /dev/null +++ b/src/config_save.c @@ -0,0 +1,2406 @@ +#include "gm_type.h" +#include "stdio.h" +#include "gm_stdlib.h" +#include "gm_gprs.h" +#include "config_save.h" +#include "config_service.h" +#include "log_service.h" +#include "utility.h" +#include "gm_memory.h" +#include "gm_fs.h" +#include "g_sensor.h" +#include "system_state.h" +#include "gm_system.h" +#include "g_sensor.h" +#include "gsm.h" +#include "applied_math.h" + +#define goome_para_main L"Z:\\goome\\GmParaMain\0" +#define goome_para_minor L"Z:\\goome\\GmParmMinor\0" +#define MAGIC_NUMBER 0xABCDDCBA + +enum +{ + UOP_FAIL = 0, // 错误 + UOP_OK, // 正确 + + UOP_CMD_ERR, // 命令错误 + UOP_LEN_ERR, // 长度错误 + UOP_PARA_ERR, // 参数错误 + UOP_CSM_ERR, // 校验值错误 + UOP_CSM_OK, + UOP_EXIST, // 7 + + UOP_MAGIC_ERR, + UOP_MAGIC_OK, + UOP_STATUS_1, + UOP_STATUS_2, + UOP_STATUS_3, + UOP_STATUS_4, + UOP_STATUS_5, + UOP_STATUS_6, + UOP_STATUS_7, + UOP_STATUS_8, + UOP_STATUS_9, + UOP_STATUS_10, + + UOP_NONE +}; + +typedef struct +{ + u8 IP[4]; + u16 PORT; +} UserTypeIPV4; + +typedef struct +{ + u8 dns[GOOME_DNS_MAX_LENTH]; + u16 port; +} UserTypeDns; + +typedef enum +{ + TCP_IP = 0, + UDP_IP, + DNS_IP, + IP_MAX +}UserIPTypeEnum; + +typedef struct +{ + u8 sock_type; + UserTypeIPV4 sock_ip[IP_MAX]; + UserTypeDns src_dns; +}SocketParamStruct; + + +typedef struct +{ + u8 OemId[5]; // + u16 wProvID; // 省域ID + u16 wCityID; // 市域ID + u8 VehNum[12]; // 机动车号牌 + u8 VehLicCol; // 车牌颜色 + u8 AtType; // 部标协议类型(标准 补充) + u8 DevId[7]; // 终端ID +}Jt808LoginStruct; + + + +// 关键参数结构体 +//#pragma pack(1) +typedef struct +{ + u32 len; + u32 crc; + u32 magic; + + u8 valid_flag; // UOP_OK:正常 UOP_PARA_ERR:参数错误 + u16 para_none; + u16 para_err; + u16 para_open_err; + u16 para_crc_err; + u16 para_mg_err; + + u16 para_from_mem; + u16 para_from_file; + u16 para_from_stm8; + u16 para_from_server; + u16 para_write_total; + u16 para_res1; + u16 para_res2; + u16 para_res3; + u16 para_res4; + + u16 para2_none; + u16 para2_err; + u16 para2_open_err; + u16 para2_crc_err; + u16 para2_mg_err; + + u16 para2_from_mem; + u16 para2_from_file; + u16 para2_write_total; + u16 para2_from_stm8; + u16 para2_from_server; + u16 para2_res1; + u16 para2_res2; + u16 para2_res3; + u16 device_type; + + SocketParamStruct sock[6]; + u8 Apn[GOOME_APN_MAX_LENGTH]; + u8 strUser[GOOME_APN_MAX_LENGTH]; + u8 strPwd[GOOME_APN_MAX_LENGTH]; + u8 strSim[17]; + u8 u1Reserved_14[13]; + u32 dwReserved_1[10]; + + u16 AOnUpTim; //RESERVED + u16 Jt_Heart_Locat_Tim; //用于判断部标位置数据心跳的发送间隔 + u16 UploadTim; // 定时判断时间 + u16 HeartTim; + u32 dwReserved_2; + + u16 u2Reserved_1; + u16 DistThreshold; // 上传时间间隔内,小速度漂移距离 + u8 GpsUpdatTime; //GPS定位检测时间,默认5秒 + u8 HeartMode; //0 自动检测模式 1 谷米正常心跳(0x03) 2 谷米扩展心跳(0x07) + + u8 LocalTime; + u8 LocalTimeMM; + + u8 SpeedSwitch; //默认关 + u8 SpeedThreshold; // 超速阈? + u8 SpeedDetectTim; // 超速检测时? + u8 Drive_Over_Time; //RESERVED + u8 Drive_Relax_Time; //RESERVED + /* + bit0 0 自动设防模式,1 手动设防模式,默认自动设防 + bit1 0:关闭震动报警,1 开启震动报警,默认关闭 + bit3-bit2 震动报警方式 00: 只GPRS方式 01:SMS+GPRS 10: GPRS+SMS+CALL 11:GPRS+CALL 默认:00 + bit4 号码设置权限 + 0: a、任意号码可设置SOS号码; + b、中心号码只有SOS号码可设置 + 1: a、当中心号码为空时,任意号码可设置; + 当中心号码已设置,只有中心号码发指令本身可修改; + b、只有?行暮怕耄ɑ騍OS号码)可设置SOS号码 + + bit5 0-1;参数设置查询权限范围;默认值:0 + bit6 0-1 报警号码权限; 默认值:0 + bit7 电池低压报警开关,默认0,打开,1:关闭 + bit8 电池低压报警方式,0:gprs 1: gprs+sms 默认0 + bit9 断电报警开关,0打开 1关闭 默认0 + bit11-bit10 断电报警方式 00: 只GPRS方式 01:SMS+GPRS 10: GPRS+SMS+CALL 11:GPRS+CALL 默认:01 + bit12 CONCOX协议类型,1新协议 0旧协议 //由protocol_type替代,不再使用 + bit13 静止上传定位点开关 0:开启 1:关闭 + bit14 基站上传开关默认关闭 0:关闭 1:开启 + bit15 自适应APN开关 0:打开 1:关闭 默认打开 + bit16 拐点补传开关 0:打开 1:关闭 默认打开 + bit17 亮灯模式,0:亮灯模式 1:灭灯模式 默认0 + bit18 后台日志上传 0:上传 1:不上传 默认 0 + bit19 电池充电模式 0 底层充电控制 1 APP充电控制 默认0 + bit20 启用EPO/AGPS 0:启用EPO 1:启用AGPS + bit21 支持电压范围 0: 9-36V 1:9-90V 默认 0 + bit22 休眠时是否把串口设置为IO口状态 0: 不设置 1:设置 默认 0 + bit23 是否平滑轨迹 + bit24 是否上传电量 1 :不上传 0:上传 默认0 + bit25 是否有GPS模块 0:有GPS模块,1:无GPS模块 + bit26 串口2波特率 0:115200 1:9600 + bit27 是否支持断油路功能 0:不支持 1:支持 + bit28 是否上传sensor状态日志 0:不上传 1:上传 + bit29 是否开启车辆移动报警 0:关闭 1:打开 + bit30 是否开启加速度报警(急加速、急减速、急转弯报警) 0:关闭 1:打开 + */ + u32 feature_sf; + + u8 Reserved_s; // 休眠模式 + u8 CenNum[20]; // 中心号码 + u8 UserNum1[16]; // 管理号码1 + u8 UserNum2[16]; // 管理号码2 + u8 UserNum3[16]; // 管理号码3 + u8 UserNum4[16]; // 管理号码4 + u8 Reserved_2[40]; + + u8 AccGpsSt; // 关联ACC状态reserved + u8 PowerVal; // PowerVlau + u8 LowPowerVal; // LowPowerVlau + u8 PowerOffVal; // NoPowerVlau + u16 power_alarm_check_tim; //断电报警检测时间 + u16 power_alarm_chr_tim; //断电报警最小充电时间 + + u16 turn_angle; // 拐点补传角度 wFlexInitAng + u8 gps_type; + u16 power_alarm_acc_tim; //断电报警ACC跳变检测时间 + u16 dwReserved_5; + + u16 shake_threshold; // G-SENSOR 震动值(mg) 震动阈值 wShakeVal + u8 reserver_u2; //碰撞阈值修改过来,之前版本默认值400 + Jt808LoginStruct login; + u8 def_cnt; //震动报警判断次数 + u8 map_url[51]; + u8 Reserved_3[9]; + + u8 led_ctrl_mode; // 0xA5:灭灯模式LED_MOD_ALL_OFF 其它:正常灯模式 LED_MOD_NORMAL + u16 language; // 语言 无报警中文:0x00 0x01 无报警英文:0x00 0x02 + u8 angle_view_time; //安装方向显示时间 默认10分钟 0xFF一直显示 + u8 Flex_sw; // 拐点补传 0:开,1:关 + + u8 shake_level; + u8 shake_time; + u8 shake_cnt; + u8 sf_switch; //是否关闭防漂移, 0x00打开 ,0x55 关闭 + u8 shake_durn_tim; + u16 sleep_tim; // 睡眠时间 min + u8 shake_interval; //震动检测间隔时间 + + //低四位应用协议版本 0 :未知,1:V1.0, 2:V1.1 + //高四位应用协议类型 0 :未知,1: goome 2 : concox 3: 808 4 : bsj + u8 protocol_type; + u8 Regis;//注册标志掉电保存 + u8 volt_grade; //外部电压等级12V-24V-36V-48V-60V-72V-84V-96V + u8 chr_delay_tim; // 开机充电延迟时间(外部控制用):分钟; + u8 reopen_gps_time; // 打开GPS多久后AGPS准备好要重新打开GPS + u8 LockIp; // 是否锁IP Dec-11-2018 0:不锁 1:锁汽车在线 2:锁万物在线 3:锁当前设置 + VehicleState init_state; + u8 min_snr; // MTK GPS定位的最小信噪比参数 + + u16 shake_alarm_timeout; //自动设防模式下震动报警延时,默认值为:180秒 + u16 shake_alarm_interval; //震动报警间隔,默认30分钟 + u16 defende_tim; //自动设防延时时间,默认10分钟(600s) + u16 TraceDebug; + u16 staticrepTim; //静止上传检测时间默认20秒 + u8 staticrepSpeed; //静止上传检测最小速度默认6km + u8 staticrepCnt; //静止上传检测次数默认3次 + u16 lbsInterval; + u16 gpsNotFixedTim; + + u16 AccCheckTim; //ACC错误检测时间最小 10分钟,最大24小时 + u16 wReserve10; + u16 wReserve11; + u16 wReserve12; + u16 wReserve13; + u16 wReserve14; + u16 wReserve15; + u16 wReserve16; + + Vector3D gravity_S; + Vector3D gravity_L; + float sensor_threshold[THRESHOLD_ARRAY_LEN]; + + u8 authCode[100];//鉴权码最大100字节 + u8 ReservBuff[156]; + +}GprsParaFileType, *T_GprsParam; + + +static T_GprsParam p_param_mem = NULL; +static p_nvram_ef_goome_param_struct s_nvram = NULL; + +static GprsParaFileType * s_Para = NULL; +static GprsParaFileType * s_Para2 = NULL; + + + + +/* +由于要兼容老配置, 所以直接使用了原来的函数与结构, +这里提供的对外接口,则主要是做结构转换. +*/ + +static void convert_cfg_to_para(GprsParaFileType *para); +static void convert_para_to_cfg(const GprsParaFileType *para); + +static u32 goome_file_param_main_write(void); +static u32 goome_file_param_main_read(void); +static u32 goome_file_write_minor_param(void); +static u32 goome_file_read_minor_param(void); +static s32 goome_delete_file(u8 *file); +static u8 param_write_back_free_mem(void); +static u8 param_read_back_free_mem(void); +static void config_service_set_deault(void); +static bool check_para_ok(const GprsParaFileType *para); +static bool check_address_para_ok(u8 * param); +static void goome_file_nvram_save(void); + + + + + +/************************************************************************ + Function : + Description : + Parameter : + Return : + Author: + Date: Aug-29-2018 +************************************************************************/ +static u32 goome_file_param_main_write(void) +{ + u32 fs_len; + int handle, ret; + + handle = GM_FS_Open(goome_para_main, GM_FS_READ_WRITE | GM_FS_ATTR_ARCHIVE | GM_FS_CREATE); + if (handle < 0) + { + LOG(INFO,"goome_file_param_main_write param main file: open fail [%d]", handle); + return 0; + } + + s_Para->magic = MAGIC_NUMBER; + s_Para->valid_flag = UOP_OK; + + s_Para->para_write_total++; + s_Para2->para_write_total++; + + s_Para->len = sizeof(GprsParaFileType); + s_Para->crc = applied_math_calc_common_crc16((u8*)&s_Para->magic, sizeof(GprsParaFileType)-8); // 968 + + + ret = GM_FS_Write(handle, (void *)s_Para, sizeof(GprsParaFileType), &fs_len); + if (ret < 0) + { + LOG(INFO,"goome_file_param_main_write param main file: write fail [%d]", ret); + + GM_FS_Close(handle); + return 0; + } + + GM_FS_Close(handle); + + LOG(INFO,"goome_file_param_main_write param main file, len:%d", fs_len); + + + return 1; +} + + +/************************************************************************ + Function : + Description : + Parameter : + Return : + Author: + Date: Aug-29-2018 +************************************************************************/ +static u32 goome_file_param_main_read(void) +{ + u32 fs_len, crc; + int handle, ret; + + handle = GM_FS_Open(goome_para_main, GM_FS_READ_ONLY | GM_FS_ATTR_ARCHIVE | GM_FS_CREATE); + if (handle < 0) + { + LOG(INFO,"goome_file_param_main_read param main read: open fail [%d]", handle); + s_Para->para_open_err++; + return UOP_FAIL; + } + + + ret = GM_FS_Read(handle, (void *)s_Para, sizeof(GprsParaFileType), &fs_len); + if (ret < 0 || fs_len != sizeof(GprsParaFileType)) + { + LOG(INFO,"goome_file_param_main_read param main read: read fail len:%d ret:%d.",fs_len, ret); + s_Para->para_open_err++; + GM_FS_Close(handle); + return UOP_FAIL; + } + + GM_FS_Close(handle); + + crc = applied_math_calc_common_crc16((u8*)&s_Para->magic, sizeof(GprsParaFileType)-8); + + if (GM_strlen((const char* )s_Para->sock[SOCKET_INDEX_MAIN].src_dns.dns) >= sizeof(s_Para->sock[SOCKET_INDEX_MAIN].src_dns.dns)-1) + { + GM_memset(&s_Para->sock[SOCKET_INDEX_MAIN].src_dns.dns, 0x00, sizeof(s_Para->sock[SOCKET_INDEX_MAIN].src_dns.dns)); + } + + if (s_Para->crc != crc) + { + LOG(INFO,"goome_file_param_main_read param main crc err:%x, %x ", s_Para->crc, crc); + s_Para->para_crc_err++; + + return UOP_CSM_ERR; + } + + if (s_Para->magic != MAGIC_NUMBER) + { + LOG(INFO,"goome_file_param_main_read param main magic err:%x, ", s_Para->magic); + s_Para->para_mg_err++; + return UOP_MAGIC_ERR; + } + + return UOP_OK;; +} + + + + + + +/************************************************************************ + Function : + Description : + Parameter : + Return : + Author: + Date: Sep-18-2018 +************************************************************************/ +static u32 goome_file_write_minor_param(void) +{ + u32 fs_len; + int handle, ret; + + handle = GM_FS_Open(goome_para_minor, GM_FS_READ_WRITE | GM_FS_ATTR_ARCHIVE | GM_FS_CREATE); + if (handle < 0) + { + LOG(INFO,"goome_file_write_minor_param open minor file fail [%d] \r\n", handle); + return 0; + } + + s_Para2->magic = MAGIC_NUMBER; + s_Para2->valid_flag = UOP_OK; + + s_Para->para2_write_total++; + s_Para2->para2_write_total++; + + s_Para2->len = sizeof(GprsParaFileType); + s_Para2->crc = applied_math_calc_common_crc16((u8*)&s_Para2->magic, sizeof(GprsParaFileType)-8); // 968 + + + ret = GM_FS_Write(handle, (void *)s_Para2, sizeof(GprsParaFileType), &fs_len); + if (ret < 0) + { + LOG(INFO,"goome_file_write_minor_param write minor file fail [%d] \r\n", ret); + + GM_FS_Close(handle); + return 0; + } + + GM_FS_Close(handle); + + return 1; +} + + + + +/************************************************************************ + Function : + Description : + Parameter : + Return : + Author: + Date: Sep-18-2018 +************************************************************************/ +static u32 goome_file_read_minor_param(void) +{ + u32 fs_len, crc; + int handle, ret; + + handle = GM_FS_Open(goome_para_minor, GM_FS_READ_ONLY | GM_FS_ATTR_ARCHIVE | GM_FS_CREATE); + if (handle < 0) + { + LOG(INFO,"goome_file_read_minor_param open minor file read fail [%d] \r\n", handle); + s_Para->para2_open_err++; + s_Para2->para2_open_err++; + + return UOP_FAIL; + } + + + ret = GM_FS_Read(handle, (void *)s_Para2, sizeof(GprsParaFileType), &fs_len); + if (ret < 0) + { + LOG(INFO,"goome_file_read_minor_param read minor file read fail [%d] \r\n", ret); + s_Para->para2_open_err++; + s_Para2->para2_open_err++; + + GM_FS_Close(handle); + return UOP_FAIL; + } + + GM_FS_Close(handle); + + crc = applied_math_calc_common_crc16((u8*)&s_Para2->magic, sizeof(GprsParaFileType)-8); // -18 + + + if (GM_strlen((const char* )s_Para2->sock[SOCKET_INDEX_MAIN].src_dns.dns) >= sizeof(s_Para2->sock[SOCKET_INDEX_MAIN].src_dns.dns)-1) + { + GM_memset(s_Para2->sock[SOCKET_INDEX_MAIN].src_dns.dns, 0x00, sizeof(s_Para2->sock[SOCKET_INDEX_MAIN].src_dns.dns)); + } + + if (s_Para2->crc != crc) + { + LOG(INFO,"goome_file_read_minor_param read minor file read crc err:%x, %x ", s_Para2->crc, crc); + s_Para->para2_crc_err++; + s_Para2->para2_crc_err++; + + return UOP_CSM_ERR; + } + + if (s_Para2->magic != MAGIC_NUMBER) + { + LOG(INFO,"goome_file_read_minor_param read minor file read magic err:%x, ", s_Para2->magic); + s_Para->para2_mg_err++; + s_Para2->para2_mg_err++; + + return UOP_MAGIC_ERR; + } + + return UOP_OK; +} + + + + +/************************************************************************ + Function : + Description : + Parameter : + Return : + Author: + Date: May-12-2016 +************************************************************************/ +static s32 goome_delete_file(u8 *file) +{ + s32 ret=0; + s32 handle; + u8 buff[100]; + + + // 检查文件是否存在 + handle = GM_FS_CheckFile((u16 *)file); + if (handle >= 0) + { + // 文件存在删掉,重新创建 + ret = GM_FS_Delete((u16 *)file); + + #if 1 + util_ucs2_to_ascii((u8*)file, buff, 160); + + LOG(INFO,"goome_delete_file deletfile:%.66s,ret:%d \r\n", buff,ret); + #endif + } + + + return ret; +} + + +/************************************************************************ + Function : + Description : + Parameter : + Return : + Author: + Date: Sep-18-2018 +************************************************************************/ +static u8 param_write_back_free_mem(void) +{ + s_Para->magic = MAGIC_NUMBER; + s_Para->valid_flag = UOP_OK; + s_Para->len = sizeof(GprsParaFileType); + s_Para->crc = applied_math_calc_common_crc16((u8*)&s_Para->magic, sizeof(GprsParaFileType)-8); // 968 + + GM_memcpy(p_param_mem, s_Para, sizeof(GprsParaFileType)); + + LOG(INFO,"param_write_back_free_mem param_write_mem:%x %d", s_Para->crc, sizeof(GprsParaFileType)-8); + + return UOP_OK; +} + +/************************************************************************ + Function : + Description : + Parameter : + Return : + Author: + Date: Sep-18-2018 +************************************************************************/ +static u8 param_read_back_free_mem(void) +{ + u32 crc; + + if (p_param_mem->magic != MAGIC_NUMBER) + { + LOG(INFO,"param_read_back_free_mem goome param file free mem magic error:%x ", p_param_mem->magic); + return UOP_MAGIC_ERR; + } + + crc = applied_math_calc_common_crc16((u8*)&p_param_mem->magic, sizeof(GprsParaFileType)-8); // -18 + if (crc != p_param_mem->crc) + { + LOG(INFO,"param_read_back_free_mem goome param file free mem Crc error:%x,%x %d", crc, p_param_mem->crc, sizeof(GprsParaFileType)-8); + return UOP_CSM_ERR; + } + + return UOP_OK; +} + + + + +/************************************************************************ + Function : + Description : 读取系统参数,FreeMem,主参数文件,备份参数文件 + Parameter : + Return : + Author: + Date: Oct-10-2018 +************************************************************************/ +u8 read_param_from_file(void) +{ + u8 file1=0, file2=0, free_mem=0; + + GM_memset(s_Para, 0x00, sizeof(GprsParaFileType)); + GM_memset(s_Para2, 0x00, sizeof(GprsParaFileType)); + + file1=0; + file2=0; + + if (GM_FS_CheckFile((const U16*)goome_para_main) < 0) + { + LOG(INFO,"read_param_from_file no find para_main_file"); + + s_Para->para_none++; + s_Para2->para_none++; + file1 = UOP_FAIL; + } + else + { + file1 = goome_file_param_main_read(); + } + + + if (GM_FS_CheckFile((const U16*)goome_para_minor) < 0) + { + LOG(INFO,"read_param_from_file no find para_minor_file"); + + s_Para->para2_none++; + s_Para2->para2_none++; + file2 = UOP_FAIL; + } + else + { + file2 = goome_file_read_minor_param(); + } + + free_mem = param_read_back_free_mem(); + if (free_mem == UOP_OK) + { + if (file1 != UOP_OK) + { + GM_memcpy(s_Para, p_param_mem, sizeof(GprsParaFileType)); + + s_Para->para_from_mem++; + s_Para2->para_from_mem++; + + goome_delete_file((u8 *)goome_para_main); + goome_file_param_main_write(); + } + + if (file2 != UOP_OK) + { + GM_memcpy(s_Para2, p_param_mem, sizeof(GprsParaFileType)); + + s_Para->para2_from_mem++; + s_Para2->para2_from_mem++; + + goome_delete_file((u8 *)goome_para_minor); + goome_file_write_minor_param(); + } + } + else + { + if(system_state_get_boot_reason(false) == GM_RREBOOT_UNKNOWN) + { + system_state_set_boot_reason(GM_REBOOT_POWER_ON); + } + + if ((file1 == UOP_OK) && (file2 != UOP_OK)) + { + GM_memcpy(s_Para2, s_Para, sizeof(GprsParaFileType)); + + s_Para->para2_from_file++; + s_Para2->para2_from_file++; + + goome_delete_file((u8 *)goome_para_minor); + goome_file_write_minor_param(); + param_write_back_free_mem(); + } + else if ((file1 != UOP_OK) && (file2 == UOP_OK)) + { + GM_memcpy(s_Para, s_Para2, sizeof(GprsParaFileType)); + + s_Para->para_from_file++; + s_Para2->para_from_file++; + + goome_delete_file((u8 *)goome_para_main); + goome_file_param_main_write(); + param_write_back_free_mem(); + } + else if ((file1 != UOP_OK) && (file2 != UOP_OK)) + { + s_Para->valid_flag = UOP_PARA_ERR; + } + } + + return 0; +} + +static void goome_file_nvram_save(void) +{ + s32 lib_index = -1; + s32 result = -1; + + if (NULL == s_nvram) + { + s_nvram = (p_nvram_ef_goome_param_struct )GM_MemoryAlloc(sizeof(nvram_ef_goome_param_struct)); + if (NULL == s_nvram) + { + LOG(ERROR,"goome_file_nvram_save assert(s_nvram) failed."); + return; + } + } + if (NULL == s_Para) + { + LOG(ERROR,"goome_file_nvram_save assert(s_Para) failed."); + return; + } + + s_nvram->DeviceType = s_Para->device_type; + + lib_index = GM_ReadNvramLid(NVRAM_EF_GM_CUSTOMER_PARAM_LID); + GM_ReadWriteNvram(0, lib_index, 1, s_nvram, sizeof(nvram_ef_goome_param_struct), &result); + + //只分配一次,后面一直使用 + //GM_MemoryFree(s_nvram); + //s_nvram = NULL; +} + + +static void read_nvram_device_type(void) +{ + s32 lib_index = -1; + s32 result = -1; + + if (NULL == s_nvram) + { + s_nvram = (p_nvram_ef_goome_param_struct)GM_MemoryAlloc(sizeof(nvram_ef_goome_param_struct)); + if (NULL == s_nvram) + { + LOG(ERROR,"goome_file_nvram_save assert(s_nvram) failed."); + return; + } + } + if (NULL == s_Para) + { + LOG(ERROR,"goome_file_nvram_save assert(s_Para) failed."); + return; + } + + lib_index = GM_ReadNvramLid(NVRAM_EF_GM_CUSTOMER_PARAM_LID); + GM_ReadWriteNvram(1, lib_index, 1, s_nvram, sizeof(nvram_ef_goome_param_struct), &result); +} + + + +/************************************************************************ + Function : + Description : + Parameter : + Return : + Author: + Date: Sep-18-2018 +************************************************************************/ +static u8 goome_file_param_save(void) +{ + param_write_back_free_mem(); + goome_file_param_main_write(); + + GM_memcpy(s_Para2, s_Para, sizeof(GprsParaFileType)); + goome_file_write_minor_param(); + goome_file_nvram_save(); + + return 1; +} + +GM_ERRCODE config_service_save_to_local(void) +{ + bool allocate_here1 = false; + bool allocate_here2 = false; + + if(NULL == s_Para) + { + s_Para = (GprsParaFileType *)GM_MemoryAlloc(sizeof(GprsParaFileType)); + if(!s_Para) + { + LOG(ERROR,"config_service_read_from_local assert(s_Para) failed."); + return GM_MEM_NOT_ENOUGH; + } + allocate_here1 = true; + } + + if(NULL == s_Para2) + { + s_Para2 = (GprsParaFileType *)GM_MemoryAlloc(sizeof(GprsParaFileType)); + if(!s_Para2) + { + LOG(ERROR,"config_service_read_from_local assert(s_Para) failed."); + GM_MemoryFree(s_Para); + s_Para = NULL; + return GM_MEM_NOT_ENOUGH; + } + allocate_here2 = true; + } + + convert_cfg_to_para(s_Para); + goome_file_param_save(); + + if(allocate_here1) + { + GM_MemoryFree(s_Para); + s_Para = NULL; + } + + if(allocate_here2) + { + GM_MemoryFree(s_Para2); + s_Para2 = NULL; + } + return GM_SUCCESS; +} + + +GM_ERRCODE config_service_read_from_local(void) +{ + if(!p_param_mem) + { + p_param_mem = (T_GprsParam)(GM_ImageDummyBase()-2*1024); + } + + if(NULL == s_Para) + { + s_Para = (GprsParaFileType *)GM_MemoryAlloc(sizeof(GprsParaFileType)); + if(!s_Para) + { + LOG(ERROR,"config_service_read_from_local assert(s_Para) failed."); + return GM_MEM_NOT_ENOUGH; + } + } + + if(NULL == s_Para2) + { + s_Para2 = (GprsParaFileType *)GM_MemoryAlloc(sizeof(GprsParaFileType)); + if(!s_Para2) + { + LOG(ERROR,"config_service_read_from_local assert(s_Para) failed."); + GM_MemoryFree(s_Para); + s_Para = NULL; + return GM_MEM_NOT_ENOUGH; + } + } + + //有些新参数在旧设备上没有,要先设置为默认参数,从文件读取后再覆盖 + config_service_set_deault(); + read_nvram_device_type(); + config_service_set_device((ConfigDeviceTypeEnum)s_nvram->DeviceType); + + read_param_from_file(); + if(UOP_PARA_ERR != s_Para->valid_flag && check_para_ok(s_Para)) + { + convert_para_to_cfg(s_Para); + LOG(INFO,"convert_para_to_cfg"); + } + else + { + config_service_save_to_local(); + LOG(INFO,"config_service_save_to_local"); + } + + + GM_MemoryFree(s_Para); + s_Para = NULL; + GM_MemoryFree(s_Para2); + s_Para2 = NULL; + return GM_SUCCESS; +} + + +/* +设置出厂时的默认参数 +不包括 sim, socket, heart_mode, apn, protocol配置. +*/ +static void config_service_set_factory_deault(void) +{ + u8 value_u8 = 0; + s8 value_s8 = 0; + u16 value_u16 = 0; + u32 value_u32 = 0; + float value_float = 0; + + value_u8 = 1; + config_service_set(CFG_SERVERLOCK, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u16 = GOOME_HEARTBEAT_DEFAULT; + config_service_set(CFG_HEART_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = GOOME_HEARTBEAT_DEFAULT; + config_service_set(CFG_JT_HBINTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = CONFIG_UPLOAD_TIME_DEFAULT; + config_service_set(CFG_UPLOADTIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + // 两点间距判断 + value_u16 = 20; + config_service_set(CFG_DISTANCE_FOR_LOW_SPEED, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + //防漂移功能默认打开 + value_u8 = false; + config_service_set(CFG_CLOSE_DRIFT_DETECT, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + + value_u8 = false; + config_service_set(CFG_SPEED_ALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = 120; + config_service_set(CFG_SPEEDTHR, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = 15; + config_service_set(CFG_SPEED_CHECK_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + + value_s8 = 8; + config_service_set(CFG_TIME_ZONE, TYPE_BYTE, &value_s8, sizeof(value_s8)); + + value_u8 = GM_GPS_TYPE_UNKNOWN; + config_service_set(CFG_GPS_TYPE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = 5; + config_service_set(CFG_GPS_UPDATE_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u16 = 20; + config_service_set(CFG_TURN_ANGLE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u32 = 60; + config_service_set(CFG_SHAKE_THRESHOLD, TYPE_INT, &value_u32, sizeof(value_u32)); + + value_u8 = 2; + config_service_set(CFG_SHAKE_LEVEL, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = CONFIG_SHAKECOUT_DEFAULT; + config_service_set(CFG_SHAKE_COUNT, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = SHAKE_TIME_SECONDS; + config_service_set(CFG_AWAKE_CHECK_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = SHAKE_COUNT_TO_AWAKE; + config_service_set(CFG_AWAKE_COUNT, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = 10; + config_service_set(CFG_SHAKE_CHECK_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u16 = GOOME_SLEEPTIME_DEFAULT; + config_service_set(CFG_SLEEP_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = false; + config_service_set(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = 0; + config_service_set(CFG_IS_SHAKE_ALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = false; + config_service_set(CFG_IS_STATIC_UPLOAD, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = false; + config_service_set(CFG_IS_MOVEALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = false; + config_service_set(CFG_SMOOTH_TRACK, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = false; + config_service_set(CFG_IS_ACLRALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = false; + config_service_set(CFG_IS_LBS_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u16 = CONFIG_SHAKEALARMDELAY_DEFAULT; + config_service_set(CFG_SHAKE_ALARM_DELAY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = CONFIG_SHAKEALARMINTERVAL_DEFAULT; + config_service_set(CFG_SHAKE_ALARM_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = 120; + config_service_set(CFG_AUTO_DEFENCE_DELAY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = 0; + config_service_set(CFG_CHARGE_DELAY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + config_service_set(CFG_MAP_URL, TYPE_STRING, GOOME_MAPS_URL_DEFAULT, GM_strlen(GOOME_MAPS_URL_DEFAULT)); + + value_u16 = 5; + config_service_set(CFG_POWER_CHECK_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = 0; + config_service_set(CFG_CUTOFFALM_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u16 = 300; + config_service_set(CFG_POWER_CHARGE_MIN_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = 0; + config_service_set(CFG_POWER_ACC_CHECK_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = PWRALM_GPRS_SMS; + config_service_set(CFG_POWER_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = PWRALM_GPRS; + config_service_set(CFG_SENSOR_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + + value_u8 = (u8)GB_ATTYPE_STANDARD; + config_service_set(CFG_JT_AT_TYPE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + config_service_set(CFG_JT_DEVICE_ID, TYPE_STRING, JT_DEV_ID, GM_strlen(JT_DEV_ID)); + config_service_set(CFG_JT_VEHICLE_NUMBER, TYPE_STRING, JT_VEHICLE_NUMBER, GM_strlen(JT_VEHICLE_NUMBER)); + config_service_set(CFG_JT_OEM_ID, TYPE_STRING, JT_OEM_ID, GM_strlen(JT_OEM_ID)); + config_service_set(CFG_JT_AUTH_CODE, TYPE_STRING, JT_OEM_ID, GM_strlen(JT_OEM_ID)); + + value_u16 = 44; + config_service_set(CFG_JT_PROVINCE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = 303; + config_service_set(CFG_JT_CITY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = 0; + config_service_set(CFG_IS_TEST_MODE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = (u8)0x01; + config_service_set(CFG_JT_VEHICLE_COLOR, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u16 = 0x0001; + config_service_set(CFG_LANGUAGE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = 20; + config_service_set(CFG_STATIC_CHECK_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = 6; + config_service_set(CFG_STATIC_CHECK_SPEED, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = 3; + config_service_set(CFG_STATIC_CHECK_COUNT, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u16 = LBS_UPLOAD_DEFAULT; + config_service_set(CFG_LBS_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = GPS_NOT_FIXED_DEFAULT; + config_service_set(CFG_WAIT_GPS_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = 30; + config_service_set(CFG_REOPEN_GSP_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u16 = 720; + config_service_set(CFG_ACC_CHECK_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = 16; + config_service_set(CFG_MIN_SNR, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = CONFIG_ANGLETIME_DEFAULT; + config_service_set(CFG_SEN_ANGLE_SHOW_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_float = RAPID_ACLR_THRESHOLD; + config_service_set(CFG_SEN_RAPID_ACLR, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = EMERGENCY_BRAKE_THRESHOLD; + config_service_set(CFG_SEN_EMERGENCY_BRAKE, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = SLIGHT_COLLISION_MIN_ACLR; + config_service_set(CFG_SEN_SLIGHT_COLLISION, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = NORMAL_COLLISION_MIN_ACLR; + config_service_set(CFG_SEN_NORMAL_COLLISION, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = SERIOUS_COLLISION_MIN_ACLR; + config_service_set(CFG_SEN_SERIOUS_COLLISION, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = SUDDEN_TURN_THRESHOLD; + config_service_set(CFG_SEN_SUDDEN_TURN, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = LOW_VOLTAGE_ALARM_PERCENT; + config_service_set(CFG_SEN_LOWVOlTAGE_ALARM, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = QUAKE_ACLR_THRESHOLD; + config_service_set(CFG_SEN_QUAKE_ALARM, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = STATIC_ACLR_THRESHOLD; + config_service_set(CFG_SEN_STATIC, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = RUN_ACLR_THRESHOLD; + config_service_set(CFG_SEN_RUN, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_u8 = false; + config_service_set(CFG_JT_ISREGISTERED, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + config_service_set(CFG_CENTER_NUMBER, TYPE_STRING, "", 0); + config_service_set(CFG_USER1_NUMBER, TYPE_STRING, "", 0); + config_service_set(CFG_USER2_NUMBER, TYPE_STRING, "", 0); + config_service_set(CFG_USER3_NUMBER, TYPE_STRING, "", 0); + config_service_set(CFG_USER4_NUMBER, TYPE_STRING, "", 0); + + value_u8 = true; + config_service_set(CFG_ALARM_SMS_ONE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + //upgrade preset parameters + config_service_set(CFG_TERM_VERSION, TYPE_STRING, VERSION_NUMBER, GM_strlen(VERSION_NUMBER)); + LOG(INFO,"current version(%s).",VERSION_NUMBER); + + config_service_set(CFG_CUSTOM_CODE, TYPE_STRING,UPDATE_OEM_CODE, GM_strlen(UPDATE_OEM_CODE)); + config_service_set(CFG_TERM_MODEL, TYPE_STRING, UPDATE_DEVICE_CODE, GM_strlen(UPDATE_DEVICE_CODE)); + config_service_set(CFG_TERM_BOOT_CHECK, TYPE_STRING,UPDATE_BOOT_CODE, GM_strlen(UPDATE_BOOT_CODE)); +} + + + +/* +设置 默认参数 +包括 sim, socket, heart_mode, apn, protocol配置. +*/ +static void config_service_set_deault(void) +{ + u8 value_u8; + //u16 value_u16; + //u32 value_u32; + //float value_float; + + config_service_set_factory_deault(); + + config_service_set(CFG_SERVERADDR, TYPE_STRING, CONFIG_GOOCAR_SERVER_ADDERSS, GM_strlen(CONFIG_GOOCAR_SERVER_ADDERSS)); + config_service_set(CFG_CFGSERVERADDR, TYPE_STRING, CONFIG_SERVER_ADDERSS, GM_strlen(CONFIG_SERVER_ADDERSS)); + config_service_set(CFG_TEST_SERVERADDR, TYPE_STRING, CONFIG_FACTORY_SERVER_ADDERSS, GM_strlen(CONFIG_FACTORY_SERVER_ADDERSS)); + config_service_set(CFG_AGPSSERVERADDR, TYPE_STRING, CONFIG_AGPS_SERVER_ADDERSS, GM_strlen(CONFIG_AGPS_SERVER_ADDERSS)); + config_service_set(CFG_LOGSERVERADDR, TYPE_STRING, CONFIG_LOG_SERVER_ADDERSS, GM_strlen(CONFIG_LOG_SERVER_ADDERSS)); + config_service_set(CFG_UPDATESERVERADDR, TYPE_STRING, GOOME_UPDATE_SERVER_DNS, GM_strlen(GOOME_UPDATE_SERVER_DNS)); + config_service_set(CFG_UPDATEFILESERVER, TYPE_STRING, GOOME_UPDATE_SERVER_DNS, GM_strlen(GOOME_UPDATE_SERVER_DNS)); + + + config_service_set(CFG_APN_NAME, TYPE_STRING, APN_DEFAULT, GM_strlen((const char *)APN_DEFAULT)); + config_service_set(CFG_APN_USER, TYPE_STRING, APN_USER_DEFAULT, GM_strlen((const char *)APN_USER_DEFAULT)); + config_service_set(CFG_APN_PWD, TYPE_STRING, APN_USER_DEFAULT, GM_strlen((const char *)APN_USER_DEFAULT)); + + + value_u8 = (u8)PROTOCOL_GOOME; + config_service_set(CFG_PROTOCOL, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = (u8)PROTOCOL_VER_GT02; + config_service_set(CFG_PROTOCOL_VER, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = (u8)HEART_SMART; + config_service_set(CFG_HBPROTOCOL, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = true; + config_service_set(CFG_APN_CHECK, TYPE_BOOL, &value_u8, sizeof(value_u8)); +} + + + +/* +设置当前设备型号 +并根据设备型号设置相关默认配置 +*/ +void config_service_set_device(ConfigDeviceTypeEnum type) +{ + u8 value_u8; + u16 value_u16; + + value_u16 = (u16)type; + if(value_u16 >= DEVICE_MAX || value_u16 <= DEVICE_NONE) + { + LOG(ERROR,"config_service_set_device assert(type(%d) failed.",value_u16); + + //先给个型号 + value_u16 = DEVICE_GS03A; + } + + config_service_set(CFG_DEVICETYPE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = false; + config_service_set(CFG_GPS_CLOSE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = true; + config_service_set(CFG_IS_90V_POWER, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + if(config_service_is_main_server_goome()) + { + value_u8 = 3; + } + else + { + value_u8 = 0; + } + config_service_set(CFG_SERVERLOCK, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = false; + config_service_set(CFG_OPEN_APGS, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = false; + config_service_set(CFG_APP_BATTERT_MGR, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = true; + config_service_set(CFG_IS_RELAY_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + //文件中只有CFG_IS_DOUBLE_GSENSOR,所以要 与 CFG_GSENNUM要一起设置 + value_u8 = 1; + config_service_set(CFG_GSENNUM, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = false; + config_service_set(CFG_IS_UART_9600, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = true; + config_service_set(CFG_IS_UART_IO_WHEN_SLEEP, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = false; + config_service_set(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = 0; + config_service_set(CFG_BATTUPLOAD_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = 0; + config_service_set(CFG_LOWBATTALM_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u16 = GOOME_HEARTBEAT_DEFAULT; + config_service_set(CFG_JT_HBINTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = true; + config_service_set(CFG_OPEN_APGS, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + switch(type) + { + case DEVICE_GS03A: + case DEVICE_GM06E: + case DEVICE_AS03A: + value_u8 = false; + config_service_set(CFG_IS_90V_POWER, TYPE_BOOL, &value_u8, sizeof(value_u8)); + break; + + case DEVICE_GS03F: + case DEVICE_AS03F: + value_u8 = false; + config_service_set(CFG_IS_90V_POWER, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = false; + config_service_set(CFG_IS_RELAY_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + break; + + case DEVICE_GS03B: + case DEVICE_AS03B: + value_u8 = false; + config_service_set(CFG_IS_90V_POWER, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = 1; + config_service_set(CFG_LOWBATTALM_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + value_u8 = false; + config_service_set(CFG_IS_RELAY_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + break; + + case DEVICE_GS07B: + case DEVICE_AS07B: + value_u8 = false; + config_service_set(CFG_IS_RELAY_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + break; + + case DEVICE_GS03I: + case DEVICE_AS03I: + value_u8 = false; + config_service_set(CFG_IS_90V_POWER, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = 1; + config_service_set(CFG_LOWBATTALM_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + value_u8 = false; + config_service_set(CFG_IS_RELAY_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = 2; + config_service_set(CFG_GSENNUM, TYPE_BYTE, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + break; + + case DEVICE_GS03H: + value_u8 = false; + config_service_set(CFG_IS_90V_POWER, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = 2; + config_service_set(CFG_GSENNUM, TYPE_BYTE, &value_u8, sizeof(value_u8)); + break; + + case DEVICE_GS05A: + value_u8 = true; + config_service_set(CFG_APP_BATTERT_MGR, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_IS_UART_9600, TYPE_BOOL, &value_u8, sizeof(value_u8)); + break; + + case DEVICE_GS05B: + value_u8 = 1; + config_service_set(CFG_LOWBATTALM_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_IS_UART_9600, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = false; + config_service_set(CFG_IS_RELAY_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_APP_BATTERT_MGR, TYPE_BOOL, &value_u8, sizeof(value_u8)); + break; + + case DEVICE_GS05F: + value_u8 = true; + config_service_set(CFG_IS_UART_9600, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = false; + config_service_set(CFG_IS_RELAY_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_APP_BATTERT_MGR, TYPE_BOOL, &value_u8, sizeof(value_u8)); + break; + + case DEVICE_GS05I: + value_u8 = 1; + config_service_set(CFG_LOWBATTALM_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + value_u8 = 2; + config_service_set(CFG_GSENNUM, TYPE_BYTE, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_IS_UART_9600, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = false; + config_service_set(CFG_IS_RELAY_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_APP_BATTERT_MGR, TYPE_BOOL, &value_u8, sizeof(value_u8)); + break; + + case DEVICE_GS05H: + value_u8 = true; + config_service_set(CFG_APP_BATTERT_MGR, TYPE_BOOL, &value_u8, sizeof(value_u8)); + value_u8 = true; + value_u8 = 2; + config_service_set(CFG_GSENNUM, TYPE_BYTE, &value_u8, sizeof(value_u8)); + value_u8 = true; + config_service_set(CFG_IS_UART_9600, TYPE_BOOL, &value_u8, sizeof(value_u8)); + break; + + //case DEVICE_GS07A: + //case DEVICE_AS07A: + default: + break; + } +} + + +void config_service_restore_factory_config(bool is_all) +{ + if(is_all) + { + config_service_set_deault(); + } + else + { + config_service_set_factory_deault(); + } + + config_service_set_device((ConfigDeviceTypeEnum)s_nvram->DeviceType); + config_service_save_to_local(); +} + + +GM_ERRCODE config_service_set_device_sim(u8 *pdata) +{ + u8 device_sim[20]; + u8 device_len = 0; + + if (GM_strstr((const char *)pdata, "#") == 0) + { + return GM_PARAM_ERROR; + } + + GM_memset(device_sim, 0x00, sizeof(device_sim)); + GM_sscanf((const char *)pdata, "%[^#]#", device_sim); + device_len = GM_strlen((const char *)device_sim); + if ((device_len > 16) || (device_len < 11)) + { + return GM_PARAM_ERROR; + } + + config_service_set(CFG_SIM, TYPE_STRING, device_sim, device_len); + + return GM_SUCCESS; +} + + +void config_service_set_test_mode(bool state) +{ + config_service_set(CFG_IS_TEST_MODE, TYPE_BOOL, &state, sizeof(state)); +} + +bool config_service_is_test_mode(void) +{ + bool is_test_mode = false; + config_service_get(CFG_IS_TEST_MODE, TYPE_BOOL, &is_test_mode, sizeof(is_test_mode)); + return is_test_mode; +} + +bool config_service_is_default_imei(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + u8 imei[GM_IMEI_LEN + 1] = {0}; + if(GM_SUCCESS != (ret = gsm_get_imei(imei))) + { + LOG(INFO,"clock(%d) config_service_is_default_imei can not get imei, ret:%d.", util_clock(), ret); + return false; + } + if (0 == GM_strcmp((const char *)imei, (const char *)GOOME_IMEI_DEFAULT)) + { + LOG(INFO,"clock(%d) config_service_is_default_imei(%s) = true.", util_clock(), imei); + return true; + } + LOG(INFO,"clock(%d) config_service_is_default_imei(%s) = false.", util_clock(), imei); + return false; +} + +static void convert_cfg_to_para(GprsParaFileType *para) +{ + u8 value_u8,value_u8_2; + char value_char = 0; + u16 value_u16; + u32 value_u32; + float value_float; + u8 value_str[CONFIG_STRING_MAX_LEN]; + s32 idx; + + GM_memset(para,0, sizeof(GprsParaFileType)); + para->len = sizeof(GprsParaFileType); + para->magic = MAGIC_NUMBER; + para->valid_flag = UOP_OK; + + config_service_get(CFG_DEVICETYPE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->device_type = value_u16; + + para->sock[SOCKET_INDEX_MAIN].sock_type = STREAM_TYPE_STREAM; + GM_memset(value_str, 0x00, sizeof(value_str)); + idx = GM_sscanf((const char*)config_service_get_pointer(CFG_SERVERADDR), "%[^:]:%d", value_str, &value_u32); + if (idx != 2 || GM_strlen((const char*)value_str) >= sizeof(para->sock[SOCKET_INDEX_MAIN].src_dns.dns) || value_u32>65535) + { + LOG(WARN,"convert_cfg_to_para assert(idx ==2) of CFG_SERVERADDR failed."); + return; + } + GM_strcpy((char*)para->sock[SOCKET_INDEX_MAIN].src_dns.dns, (const char*)value_str); + para->sock[SOCKET_INDEX_MAIN].src_dns.port = value_u32; + + para->sock[SOCKET_INDEX_AGPS].sock_type = STREAM_TYPE_DGRAM; + GM_memset(value_str, 0x00, sizeof(value_str)); + idx = GM_sscanf((const char*)config_service_get_pointer(CFG_AGPSSERVERADDR), "%[^:]:%d", value_str, &value_u32); + if (idx != 2 || GM_strlen((const char*)value_str) >= sizeof(para->sock[SOCKET_INDEX_AGPS].src_dns.dns) || value_u32>65535) + { + LOG(WARN,"convert_cfg_to_para assert(idx ==2) of CFG_AGPSSERVERADDR failed."); + return; + } + GM_strcpy((char*)para->sock[SOCKET_INDEX_AGPS].src_dns.dns, (const char*)value_str); + para->sock[SOCKET_INDEX_AGPS].src_dns.port = value_u32; + + para->sock[SOCKET_INDEX_LOG].sock_type = STREAM_TYPE_DGRAM; + GM_memset(value_str, 0x00, sizeof(value_str)); + idx = GM_sscanf((const char*)config_service_get_pointer(CFG_LOGSERVERADDR), "%[^:]:%d", value_str, &value_u32); + if (idx != 2 || GM_strlen((const char*)value_str) >= sizeof(para->sock[SOCKET_INDEX_LOG].src_dns.dns) || value_u32>65535) + { + LOG(WARN,"convert_cfg_to_para assert(idx ==2) of CFG_LOGSERVERADDR failed."); + return; + } + GM_strcpy((char*)para->sock[SOCKET_INDEX_LOG].src_dns.dns, (const char*)value_str); + para->sock[SOCKET_INDEX_LOG].src_dns.port = value_u32; + + para->sock[SOCKET_INDEX_UPDATE].sock_type = STREAM_TYPE_DGRAM; + GM_memset(value_str, 0x00, sizeof(value_str)); + idx = GM_sscanf((const char*)config_service_get_pointer(CFG_UPDATESERVERADDR), "%[^:]:%d", value_str, &value_u32); + if (idx != 2 || GM_strlen((const char*)value_str) >= sizeof(para->sock[SOCKET_INDEX_UPDATE].src_dns.dns) || value_u32>65535) + { + LOG(WARN,"convert_cfg_to_para assert(idx ==2) of CFG_UPDATESERVERADDR failed."); + return; + } + GM_strcpy((char*)para->sock[SOCKET_INDEX_UPDATE].src_dns.dns, (const char*)value_str); + para->sock[SOCKET_INDEX_UPDATE].src_dns.port = value_u32; + + para->sock[SOCKET_INDEX_CONFIG].sock_type = STREAM_TYPE_DGRAM; + GM_memset(value_str, 0x00, sizeof(value_str)); + idx = GM_sscanf((const char*)config_service_get_pointer(CFG_CFGSERVERADDR), "%[^:]:%d", value_str, &value_u32); + if (idx != 2 || GM_strlen((const char*)value_str) >= sizeof(para->sock[SOCKET_INDEX_CONFIG].src_dns.dns) || value_u32>65535) + { + LOG(WARN,"convert_cfg_to_para assert(idx ==2) of CFG_CFGSERVERADDR failed."); + return; + } + GM_strcpy((char*)para->sock[SOCKET_INDEX_CONFIG].src_dns.dns, (const char*)value_str); + para->sock[SOCKET_INDEX_CONFIG].src_dns.port = value_u32; + + config_service_get(CFG_APN_NAME, TYPE_STRING, value_str, sizeof(value_str)); + GM_strcpy((char *)para->Apn,(const char*)value_str); + + config_service_get(CFG_APN_USER, TYPE_STRING, value_str, sizeof(value_str)); + GM_strcpy((char *)para->strUser,(const char*)value_str); + + config_service_get(CFG_APN_PWD, TYPE_STRING, value_str, sizeof(value_str)); + GM_strcpy((char *)para->strPwd,(const char*)value_str); + + + config_service_get(CFG_JT_HBINTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->Jt_Heart_Locat_Tim = value_u16; + + config_service_get(CFG_UPLOADTIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->UploadTim = value_u16; + + // 心跳间隔 + config_service_get(CFG_HEART_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->HeartTim = value_u16; + + config_service_get(CFG_DISTANCE_FOR_LOW_SPEED, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->DistThreshold = value_u16; + + config_service_get(CFG_GPS_UPDATE_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->GpsUpdatTime = value_u8; + + config_service_get(CFG_HBPROTOCOL, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->HeartMode = value_u8; + + config_service_get(CFG_TIME_ZONE, TYPE_BYTE, &value_char, sizeof(value_char)); + para->LocalTime = value_char; + + config_service_get(CFG_SPEED_ALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + para->SpeedSwitch = value_u8; + + config_service_get(CFG_SPEEDTHR, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->SpeedThreshold = value_u8; + + config_service_get(CFG_SPEED_CHECK_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->SpeedDetectTim = value_u8; + + para->Drive_Over_Time = 0; + para->Drive_Relax_Time = 0; + + + + config_service_get(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT0(para->feature_sf); + } + else + { + CLR_BIT0(para->feature_sf); + } + + config_service_get(CFG_IS_SHAKE_ALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT1(para->feature_sf); + } + else + { + CLR_BIT1(para->feature_sf); + } + + config_service_get(CFG_SENSOR_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + switch(value_u8) + { + case PWRALM_GPRS: + CLR_BIT2(para->feature_sf); + CLR_BIT3(para->feature_sf); + break; + case PWRALM_GPRS_SMS: + SET_BIT2(para->feature_sf); + CLR_BIT3(para->feature_sf); + break; + case PWRALM_GPRS_SMS_CALL: + CLR_BIT2(para->feature_sf); + SET_BIT3(para->feature_sf); + break; + case PWRALM_GPRS_CALL: + SET_BIT2(para->feature_sf); + SET_BIT3(para->feature_sf); + break; + } + + config_service_get(CFG_ALARM_SMS_ONE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT6(para->feature_sf); + } + else + { + CLR_BIT6(para->feature_sf); + } + + + config_service_get(CFG_LOWBATTALM_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT7(para->feature_sf); + } + else + { + CLR_BIT7(para->feature_sf); + } + + config_service_get(CFG_CUTOFFALM_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT9(para->feature_sf); + } + else + { + CLR_BIT9(para->feature_sf); + } + + + config_service_get(CFG_APN_CHECK, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT15(para->feature_sf); + } + else + { + CLR_BIT15(para->feature_sf); + } + + config_service_get(CFG_APP_BATTERT_MGR, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT19(para->feature_sf); + } + else + { + CLR_BIT19(para->feature_sf); + } + + config_service_get(CFG_POWER_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + switch(value_u8) + { + case PWRALM_GPRS: + CLR_BIT10(para->feature_sf); + CLR_BIT11(para->feature_sf); + break; + case PWRALM_GPRS_SMS: + SET_BIT10(para->feature_sf); + CLR_BIT11(para->feature_sf); + break; + case PWRALM_GPRS_SMS_CALL: + CLR_BIT10(para->feature_sf); + SET_BIT11(para->feature_sf); + break; + case PWRALM_GPRS_CALL: + SET_BIT10(para->feature_sf); + SET_BIT11(para->feature_sf); + break; + } + + config_service_get(CFG_IS_STATIC_UPLOAD, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + CLR_BIT13(para->feature_sf); + } + else + { + SET_BIT13(para->feature_sf); + } + + config_service_get(CFG_IS_LBS_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT14(para->feature_sf); + } + else + { + CLR_BIT14(para->feature_sf); + } + + + config_service_get(CFG_OPEN_APGS, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT20(para->feature_sf); + } + else + { + CLR_BIT20(para->feature_sf); + } + + config_service_get(CFG_IS_90V_POWER, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT21(para->feature_sf); + } + else + { + CLR_BIT21(para->feature_sf); + } + + config_service_get(CFG_IS_UART_IO_WHEN_SLEEP, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT22(para->feature_sf); + } + else + { + CLR_BIT22(para->feature_sf); + } + + config_service_get(CFG_SMOOTH_TRACK, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT23(para->feature_sf); + } + else + { + CLR_BIT23(para->feature_sf); + } + + config_service_get(CFG_BATTUPLOAD_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT24(para->feature_sf); + } + else + { + CLR_BIT24(para->feature_sf); + } + + config_service_get(CFG_GPS_CLOSE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT25(para->feature_sf); + } + else + { + CLR_BIT25(para->feature_sf); + } + + config_service_get(CFG_IS_UART_9600, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT26(para->feature_sf); + } + else + { + CLR_BIT26(para->feature_sf); + } + + config_service_get(CFG_IS_RELAY_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT27(para->feature_sf); + } + else + { + CLR_BIT27(para->feature_sf); + } + + config_service_get(CFG_IS_MOVEALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT29(para->feature_sf); + } + else + { + CLR_BIT29(para->feature_sf); + } + + config_service_get(CFG_IS_ACLRALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if (value_u8) + { + SET_BIT30(para->feature_sf); + } + else + { + CLR_BIT30(para->feature_sf); + } + + + config_service_get(CFG_CENTER_NUMBER, TYPE_STRING, para->CenNum, sizeof(para->CenNum)); + config_service_get(CFG_USER1_NUMBER, TYPE_STRING, para->UserNum1, sizeof(para->UserNum1)); + config_service_get(CFG_USER2_NUMBER, TYPE_STRING, para->UserNum2, sizeof(para->UserNum2)); + config_service_get(CFG_USER3_NUMBER, TYPE_STRING, para->UserNum3, sizeof(para->UserNum3)); + config_service_get(CFG_USER4_NUMBER, TYPE_STRING, para->UserNum4, sizeof(para->UserNum4)); + + + para->AccGpsSt = 0; + + para->PowerVal = 12; + + // 低电阀值 + para->LowPowerVal = 10; + + // 断电阀值 + para->PowerOffVal = 5; + + config_service_get(CFG_POWER_CHECK_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->power_alarm_check_tim = value_u16; + + config_service_get(CFG_POWER_CHARGE_MIN_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->power_alarm_chr_tim = value_u16; + + config_service_get(CFG_TURN_ANGLE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->turn_angle = (u16)value_u16; + + config_service_get(CFG_GPS_TYPE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->gps_type = value_u8; + + config_service_get(CFG_POWER_ACC_CHECK_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->power_alarm_acc_tim = value_u16; + + config_service_get(CFG_SHAKE_THRESHOLD, TYPE_INT, &value_u32, sizeof(value_u32)); + para->shake_threshold = (u16)value_u32; + + + config_service_get(CFG_JT_DEVICE_ID, TYPE_STRING, value_str, sizeof(value_str)); + GM_memcpy(para->login.DevId, value_str, sizeof(para->login.DevId)); + + config_service_get(CFG_JT_OEM_ID, TYPE_STRING, value_str, sizeof(value_str)); + GM_memcpy(para->login.OemId, value_str, sizeof(para->login.OemId)); + + config_service_get(CFG_JT_VEHICLE_NUMBER, TYPE_STRING, value_str, sizeof(value_str)); + GM_memcpy(para->login.VehNum, value_str, sizeof(para->login.VehNum)); + + config_service_get(CFG_JT_PROVINCE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->login.wProvID = value_u16; + + config_service_get(CFG_JT_CITY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->login.wCityID = value_u16; + + config_service_get(CFG_JT_AT_TYPE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->login.AtType = value_u8; + + config_service_get(CFG_JT_VEHICLE_COLOR, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->login.VehLicCol = value_u8; + + config_service_get(CFG_JT_AUTH_CODE, TYPE_STRING, value_str, sizeof(value_str)); + GM_memcpy(para->authCode, value_str, sizeof(para->authCode)); + + config_service_get(CFG_SHAKE_COUNT, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->def_cnt = value_u8; + + config_service_get(CFG_MAP_URL, TYPE_STRING, value_str, sizeof(value_str)); + GM_strncpy((char *)para->map_url, (const char *)value_str, sizeof(para->map_url)); + + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->language = value_u16; + + config_service_get(CFG_SEN_ANGLE_SHOW_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->angle_view_time = value_u8; + + para->Flex_sw = 0; + + config_service_get(CFG_SHAKE_LEVEL, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->shake_level = value_u8; + + config_service_get(CFG_AWAKE_CHECK_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->shake_time = value_u8; + + config_service_get(CFG_AWAKE_COUNT, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->shake_cnt = value_u8; + + config_service_get(CFG_CLOSE_DRIFT_DETECT, TYPE_BOOL, &value_u8, sizeof(value_u8)); + para->sf_switch = value_u8; + + para->shake_durn_tim = 1; + + config_service_get(CFG_SLEEP_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->sleep_tim = value_u16; + + config_service_get(CFG_SHAKE_CHECK_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->shake_interval = value_u8; + + config_service_get(CFG_PROTOCOL, TYPE_BYTE, &value_u8, sizeof(value_u8)); + config_service_get(CFG_PROTOCOL_VER, TYPE_BYTE, &value_u8_2, sizeof(value_u8_2)); + para->protocol_type = MERGEBCD(value_u8,value_u8_2); + + config_service_get(CFG_JT_ISREGISTERED, TYPE_BOOL, &value_u8, sizeof(value_u8)); + para->Regis = value_u8; + + config_service_get(CFG_CHARGE_DELAY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->chr_delay_tim = value_u16; + + config_service_get(CFG_SERVERLOCK, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->LockIp = value_u8; + + config_service_get(CFG_MIN_SNR, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->min_snr = value_u8; + + config_service_get(CFG_SHAKE_ALARM_DELAY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->shake_alarm_timeout = value_u16; + + config_service_get(CFG_SHAKE_ALARM_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->shake_alarm_interval = value_u16; + + + config_service_get(CFG_AUTO_DEFENCE_DELAY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->defende_tim = value_u16; + + + + config_service_get(CFG_STATIC_CHECK_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->staticrepTim = value_u16; + + config_service_get(CFG_STATIC_CHECK_SPEED, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->staticrepSpeed= value_u8; + + config_service_get(CFG_STATIC_CHECK_COUNT, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->staticrepCnt= value_u8; + + config_service_get(CFG_LBS_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->lbsInterval = value_u16; + + config_service_get(CFG_WAIT_GPS_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->gpsNotFixedTim = value_u16; + + config_service_get(CFG_REOPEN_GSP_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + para->reopen_gps_time = value_u8; + + config_service_get(CFG_ACC_CHECK_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + para->AccCheckTim = value_u16; + + config_service_get(CFG_SEN_RAPID_ACLR, TYPE_FLOAT, &value_float, sizeof(value_float)); + para->sensor_threshold[THRESHOLD_INDEX_FOR_RAPID_ACLR] = value_float; + + config_service_get(CFG_SEN_EMERGENCY_BRAKE, TYPE_FLOAT, &value_float, sizeof(value_float)); + para->sensor_threshold[THRESHOLD_INDEX_FOR_EMERGENCY_BRAKE] = value_float; + + config_service_get(CFG_SEN_SLIGHT_COLLISION, TYPE_FLOAT, &value_float, sizeof(value_float)); + para->sensor_threshold[THRESHOLD_INDEX_FOR_SLIGHT_COLLISION] = value_float; + + config_service_get(CFG_SEN_NORMAL_COLLISION, TYPE_FLOAT, &value_float, sizeof(value_float)); + para->sensor_threshold[THRESHOLD_INDEX_FOR_NORMAL_COLLISION] = value_float; + + config_service_get(CFG_SEN_SERIOUS_COLLISION, TYPE_FLOAT, &value_float, sizeof(value_float)); + para->sensor_threshold[THRESHOLD_INDEX_FOR_SERIOUS_COLLISION] = value_float; + + config_service_get(CFG_SEN_SUDDEN_TURN, TYPE_FLOAT, &value_float, sizeof(value_float)); + para->sensor_threshold[THRESHOLD_INDEX_FOR_SUDDEN_TURN] = value_float; + + config_service_get(CFG_SEN_LOWVOlTAGE_ALARM, TYPE_FLOAT, &value_float, sizeof(value_float)); + para->sensor_threshold[THRESHOLD_INDEX_FOR_LOWVOlTAGE_ALARM] = value_float; + + config_service_get(CFG_SEN_QUAKE_ALARM, TYPE_FLOAT, &value_float, sizeof(value_float)); + para->sensor_threshold[THRESHOLD_INDEX_FOR_QUAKE_ALARM] = value_float; + + config_service_get(CFG_SEN_STATIC, TYPE_FLOAT, &value_float, sizeof(value_float)); + para->sensor_threshold[THRESHOLD_INDEX_FOR_STATIC] = value_float; + + config_service_get(CFG_SEN_RUN, TYPE_FLOAT, &value_float, sizeof(value_float)); + para->sensor_threshold[THRESHOLD_INDEX_FOR_RUN] = value_float; +} + + +static void convert_para_to_cfg(const GprsParaFileType *para) +{ + u8 value_u8,value_u8_2; + s8 value_s8 = 0; + u16 value_u16; + u32 value_u32; + float value_float; + u8 value_str[CONFIG_STRING_MAX_LEN]; + + value_u16 = para->device_type; + config_service_set(CFG_DEVICETYPE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + //lz mod for compatable T808 device config only ip. + if(util_is_valid_dns(para->sock[SOCKET_INDEX_MAIN].src_dns.dns, GM_strlen((const char*)para->sock[SOCKET_INDEX_MAIN].src_dns.dns))) + { + GM_snprintf((char*)value_str,sizeof(value_str), "%s:%d",(char*)para->sock[SOCKET_INDEX_MAIN].src_dns.dns, para->sock[SOCKET_INDEX_MAIN].src_dns.port); + config_service_set(CFG_SERVERADDR, TYPE_STRING, &value_str, GM_strlen((char*)value_str)); + LOG(INFO,"is domain:%s",value_str); + } + else if(util_is_valid_ip(para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].IP, sizeof(para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].IP))) + { + GM_snprintf((char*)value_str,sizeof(value_str), "%d.%d.%d.%d:%d",para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].IP[0], para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].IP[1], + para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].IP[2],para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].IP[3],para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].PORT); + config_service_set(CFG_SERVERADDR, TYPE_STRING, &value_str, GM_strlen((char*)value_str)); + + LOG(INFO,"is IP:%s",value_str); + } + + //以下服务器用默认值,所以不用存储的内容更新 + GM_snprintf((char*)value_str,sizeof(value_str), "%s:%d",(char*)para->sock[SOCKET_INDEX_AGPS].src_dns.dns, para->sock[SOCKET_INDEX_AGPS].src_dns.port); + //config_service_set(CFG_AGPSSERVERADDR, TYPE_STRING, &value_str, GM_strlen((char*)value_str)); + + GM_snprintf((char*)value_str,sizeof(value_str), "%s:%d",(char*)para->sock[SOCKET_INDEX_LOG].src_dns.dns, para->sock[SOCKET_INDEX_LOG].src_dns.port); + //config_service_set(CFG_LOGSERVERADDR, TYPE_STRING, &value_str, GM_strlen((char*)value_str)); + + GM_snprintf((char*)value_str,sizeof(value_str), "%s:%d",(char*)para->sock[SOCKET_INDEX_UPDATE].src_dns.dns, para->sock[SOCKET_INDEX_UPDATE].src_dns.port); + //config_service_set(CFG_UPDATESERVERADDR, TYPE_STRING, &value_str, GM_strlen((char*)value_str)); + + GM_snprintf((char*)value_str,sizeof(value_str), "%s:%d",(char*)para->sock[SOCKET_INDEX_CONFIG].src_dns.dns, para->sock[SOCKET_INDEX_CONFIG].src_dns.port); + //config_service_set(CFG_CFGSERVERADDR, TYPE_STRING, &value_str, GM_strlen((char*)value_str)); + + + config_service_set(CFG_APN_NAME, TYPE_STRING, ¶->Apn, GM_strlen((const char*)para->Apn)); + config_service_set(CFG_APN_USER, TYPE_STRING, ¶->strUser, GM_strlen((const char*)para->strUser)); + config_service_set(CFG_APN_PWD, TYPE_STRING, ¶->strPwd, GM_strlen((const char*)para->strPwd)); + + + value_u16 = para->Jt_Heart_Locat_Tim; + config_service_set(CFG_JT_HBINTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = para->UploadTim; + config_service_set(CFG_UPLOADTIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + // 心跳间隔 + value_u16 = para->HeartTim; + config_service_set(CFG_HEART_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = para->DistThreshold; + config_service_set(CFG_DISTANCE_FOR_LOW_SPEED, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = para->GpsUpdatTime; + config_service_set(CFG_GPS_UPDATE_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = para->HeartMode; + config_service_set(CFG_HBPROTOCOL, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_s8 = para->LocalTime; + config_service_set(CFG_TIME_ZONE, TYPE_BYTE, &value_s8, sizeof(value_s8)); + + value_u8 = para->SpeedSwitch; + config_service_set(CFG_SPEED_ALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = para->SpeedThreshold; + config_service_set(CFG_SPEEDTHR, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = para->SpeedDetectTim; + config_service_set(CFG_SPEED_CHECK_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + if(GET_BIT2(para->feature_sf)) + { + if(GET_BIT3(para->feature_sf)) + { + value_u8 = PWRALM_GPRS_CALL; + config_service_set(CFG_SENSOR_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + } + else + { + value_u8 = PWRALM_GPRS_SMS; + config_service_set(CFG_SENSOR_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + } + } + else + { + if(GET_BIT3(para->feature_sf)) + { + value_u8 = PWRALM_GPRS_SMS_CALL; + config_service_set(CFG_SENSOR_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + } + else + { + value_u8 = PWRALM_GPRS; + config_service_set(CFG_SENSOR_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + } + } + + value_u8 = GET_BIT0(para->feature_sf); + config_service_set(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT1(para->feature_sf); + config_service_set(CFG_IS_SHAKE_ALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT6(para->feature_sf); + config_service_set(CFG_ALARM_SMS_ONE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT7(para->feature_sf); + config_service_set(CFG_LOWBATTALM_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT9(para->feature_sf); + config_service_set(CFG_CUTOFFALM_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + if(GET_BIT10(para->feature_sf)) + { + if(GET_BIT11(para->feature_sf)) + { + value_u8 = PWRALM_GPRS_CALL; + config_service_set(CFG_POWER_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + } + else + { + value_u8 = PWRALM_GPRS_SMS; + config_service_set(CFG_POWER_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + } + } + else + { + if(GET_BIT11(para->feature_sf)) + { + value_u8 = PWRALM_GPRS_SMS_CALL; + config_service_set(CFG_POWER_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + } + else + { + value_u8 = PWRALM_GPRS; + config_service_set(CFG_POWER_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + } + } + + + value_u8 = GET_BIT13(para->feature_sf); + value_u8 = value_u8?false:true; + config_service_set(CFG_IS_STATIC_UPLOAD, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT14(para->feature_sf); + config_service_set(CFG_IS_LBS_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT15(para->feature_sf); + config_service_set(CFG_APN_CHECK, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT19(para->feature_sf); + config_service_set(CFG_APP_BATTERT_MGR, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT20(para->feature_sf); + config_service_set(CFG_OPEN_APGS, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT21(para->feature_sf); + config_service_set(CFG_IS_90V_POWER, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT22(para->feature_sf); + config_service_set(CFG_IS_UART_IO_WHEN_SLEEP, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT23(para->feature_sf); + config_service_set(CFG_SMOOTH_TRACK, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT24(para->feature_sf); + config_service_set(CFG_BATTUPLOAD_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT25(para->feature_sf); + config_service_set(CFG_GPS_CLOSE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT26(para->feature_sf); + config_service_set(CFG_IS_UART_9600, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT27(para->feature_sf); + config_service_set(CFG_IS_RELAY_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT29(para->feature_sf); + config_service_set(CFG_IS_MOVEALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u8 = GET_BIT30(para->feature_sf); + config_service_set(CFG_IS_ACLRALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + config_service_set(CFG_CENTER_NUMBER, TYPE_STRING, para->CenNum, GM_strlen((char *)para->CenNum)); + config_service_set(CFG_USER1_NUMBER, TYPE_STRING, para->UserNum1, GM_strlen((char *)para->UserNum1)); + config_service_set(CFG_USER2_NUMBER, TYPE_STRING, para->UserNum2, GM_strlen((char *)para->UserNum2)); + config_service_set(CFG_USER3_NUMBER, TYPE_STRING, para->UserNum3, GM_strlen((char *)para->UserNum3)); + config_service_set(CFG_USER4_NUMBER, TYPE_STRING, para->UserNum4, GM_strlen((char *)para->UserNum4)); + + + value_u16 = para->power_alarm_check_tim; + config_service_set(CFG_POWER_CHECK_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = para->power_alarm_chr_tim; + config_service_set(CFG_POWER_CHARGE_MIN_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = para->turn_angle; + config_service_set(CFG_TURN_ANGLE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = para->gps_type; + config_service_set(CFG_GPS_TYPE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u16 = para->power_alarm_acc_tim; + config_service_set(CFG_POWER_ACC_CHECK_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u32 = para->shake_threshold; + config_service_set(CFG_SHAKE_THRESHOLD, TYPE_INT, &value_u32, sizeof(value_u32)); + + + //注意以下三处都是sizeof, 因为para指向的结构中,没有为结束符预留位置 + config_service_set(CFG_JT_DEVICE_ID, TYPE_STRING, para->login.DevId, sizeof(para->login.DevId)); + + config_service_set(CFG_JT_OEM_ID, TYPE_STRING, para->login.OemId, sizeof(para->login.OemId)); + + config_service_set(CFG_JT_VEHICLE_NUMBER, TYPE_STRING, para->login.VehNum, sizeof(para->login.VehNum)); + + value_u16 = para->login.wProvID; + config_service_set(CFG_JT_PROVINCE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = para->login.wCityID; + config_service_set(CFG_JT_CITY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = para->login.AtType; + config_service_set(CFG_JT_AT_TYPE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = para->login.VehLicCol; + config_service_set(CFG_JT_VEHICLE_COLOR, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + config_service_set(CFG_JT_AUTH_CODE, TYPE_STRING, para->authCode, GM_strlen((char *)para->authCode)); + + value_u8 = para->def_cnt; + config_service_set(CFG_SHAKE_COUNT, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + config_service_set(CFG_MAP_URL, TYPE_STRING, para->map_url, GM_strlen((char *)para->map_url)); + + value_u16 = para->language; + config_service_set(CFG_LANGUAGE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = para->angle_view_time; + config_service_set(CFG_SEN_ANGLE_SHOW_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + + value_u8 = para->shake_level; + config_service_set(CFG_SHAKE_LEVEL, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = para->shake_time; + config_service_set(CFG_AWAKE_CHECK_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = para->shake_cnt; + config_service_set(CFG_AWAKE_COUNT, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = para->sf_switch; + config_service_set(CFG_CLOSE_DRIFT_DETECT, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + + value_u16 = para->sleep_tim; + config_service_set(CFG_SLEEP_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = para->shake_interval; + config_service_set(CFG_SHAKE_CHECK_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8_2 = BCD_LOW(para->protocol_type); + value_u8 = BCD_HIGH(para->protocol_type); + config_service_set(CFG_PROTOCOL, TYPE_BYTE, &value_u8, sizeof(value_u8)); + config_service_set(CFG_PROTOCOL_VER, TYPE_BYTE, &value_u8_2, sizeof(value_u8_2)); + + value_u8 = para->Regis; + config_service_set(CFG_JT_ISREGISTERED, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + value_u16 = para->chr_delay_tim; + config_service_set(CFG_CHARGE_DELAY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = para->LockIp; + config_service_set(CFG_SERVERLOCK, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = para->min_snr; + config_service_set(CFG_MIN_SNR, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u16 = para->shake_alarm_timeout; + config_service_set(CFG_SHAKE_ALARM_DELAY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = para->shake_alarm_interval; + config_service_set(CFG_SHAKE_ALARM_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + + value_u16 = para->defende_tim; + config_service_set(CFG_AUTO_DEFENCE_DELAY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + + + value_u16 = para->staticrepTim; + config_service_set(CFG_STATIC_CHECK_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = para->staticrepSpeed; + config_service_set(CFG_STATIC_CHECK_SPEED, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u8 = para->staticrepCnt; + config_service_set(CFG_STATIC_CHECK_COUNT, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u16 = para->lbsInterval; + config_service_set(CFG_LBS_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u16 = para->gpsNotFixedTim; + config_service_set(CFG_WAIT_GPS_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + value_u8 = para->reopen_gps_time; + config_service_set(CFG_REOPEN_GSP_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + value_u16 = para->AccCheckTim; + config_service_set(CFG_ACC_CHECK_TIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + + + value_float = para->sensor_threshold[THRESHOLD_INDEX_FOR_RAPID_ACLR]; + config_service_set(CFG_SEN_RAPID_ACLR, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = para->sensor_threshold[THRESHOLD_INDEX_FOR_EMERGENCY_BRAKE]; + config_service_set(CFG_SEN_EMERGENCY_BRAKE, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = para->sensor_threshold[THRESHOLD_INDEX_FOR_SLIGHT_COLLISION]; + config_service_set(CFG_SEN_SLIGHT_COLLISION, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = para->sensor_threshold[THRESHOLD_INDEX_FOR_NORMAL_COLLISION]; + config_service_set(CFG_SEN_NORMAL_COLLISION, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = para->sensor_threshold[THRESHOLD_INDEX_FOR_SERIOUS_COLLISION]; + config_service_set(CFG_SEN_SERIOUS_COLLISION, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = para->sensor_threshold[THRESHOLD_INDEX_FOR_SUDDEN_TURN]; + config_service_set(CFG_SEN_SUDDEN_TURN, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = para->sensor_threshold[THRESHOLD_INDEX_FOR_LOWVOlTAGE_ALARM]; + config_service_set(CFG_SEN_LOWVOlTAGE_ALARM, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = para->sensor_threshold[THRESHOLD_INDEX_FOR_QUAKE_ALARM]; + config_service_set(CFG_SEN_QUAKE_ALARM, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = para->sensor_threshold[THRESHOLD_INDEX_FOR_STATIC]; + config_service_set(CFG_SEN_STATIC, TYPE_FLOAT, &value_float, sizeof(value_float)); + + value_float = para->sensor_threshold[THRESHOLD_INDEX_FOR_RUN]; + config_service_set(CFG_SEN_RUN, TYPE_FLOAT, &value_float, sizeof(value_float)); + +} + +static bool check_address_para_ok(u8 * param) +{ + u8 addr[2*GOOME_DNS_MAX_LENTH]; + u8 IP[4]; + u32 port = 0; + u8 idx = 0; + + GM_memset(addr, 0x00, sizeof(addr)); + idx = GM_sscanf((const char*)param, "%[^:]:%d", addr, &port); + if (idx != 2) + { + LOG(INFO,"check_address_para_ok assert(2 fields(%s)) failed.", param); + return false; + } + + if(GM_SUCCESS != GM_ConvertIpAddr(addr, IP)) + { + if(! util_is_valid_dns(addr, GM_strlen((const char *)addr))) + { + LOG(WARN,"check_address_para_ok assert(dns(%s)) failed.", addr); + return false; + } + } + return true; +} + + +static bool check_para_ok(const GprsParaFileType *para) +{ + u8 value_u8 = 0; + u8 value_u8_2 = 0; + u16 value_u16 = 0; + u8 value_str[CONFIG_STRING_MAX_LEN]; + + + value_u16 = para->device_type; + if(value_u16 <= DEVICE_NONE || value_u16 >= DEVICE_MAX) + { + return false; + } + + value_str[0] = 0; + if(util_is_valid_dns(para->sock[SOCKET_INDEX_MAIN].src_dns.dns, GM_strlen((const char*)para->sock[SOCKET_INDEX_MAIN].src_dns.dns))) + { + GM_snprintf((char*)value_str,sizeof(value_str), "%s:%d",(char*)para->sock[SOCKET_INDEX_MAIN].src_dns.dns, para->sock[SOCKET_INDEX_MAIN].src_dns.port); + LOG(INFO,"domain:%s",value_str); + } + else if(util_is_valid_ip(para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].IP, sizeof(para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].IP))) + { + GM_snprintf((char*)value_str,sizeof(value_str), "%d.%d.%d.%d:%d",para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].IP[0], para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].IP[1], + para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].IP[2],para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].IP[3],para->sock[SOCKET_INDEX_MAIN].sock_ip[TCP_IP].PORT); + LOG(INFO,"ip:%s",value_str); + } + + if(!check_address_para_ok(value_str)) + { + return false; + } + + value_u8_2 = BCD_LOW(para->protocol_type); + value_u8 = BCD_HIGH(para->protocol_type); + if(value_u8 >= PROTOCOL_MAX) + { + return false; + } + if(value_u8_2 >= PROTOCOL_APP_MAX) + { + return false; + } + return true; +} + + diff --git a/src/config_service.c b/src/config_service.c new file mode 100644 index 0000000..7a78879 --- /dev/null +++ b/src/config_service.c @@ -0,0 +1,1717 @@ +#include "gm_type.h" +#include "stdio.h" +#include "gm_stdlib.h" +#include "gm_gprs.h" +#include "fifo.h" +#include "utility.h" +#include "gsm.h" +#include "gm_memory.h" +#include "config_service.h" +#include "gps_service.h" +#include "log_service.h" +#include "agps_service.h" +#include "update_service.h" +#include "g_sensor.h" +#include "auto_test.h" +#include "gprs.h" + +#define CONFIG_PING_TIME 43200 + +typedef struct +{ + u32 last_ok_time; //上一次执行配置检测的时间 + u32 wait; //执行配置检测的间隔 +}ConfigServiceExtend; + +static SocketType s_config_socket = {-1,"",SOCKET_STATUS_ERROR,}; +static ConfigServiceExtend s_config_socket_extend; + +static ConfigParamItems s_configs[CFG_PARAM_MAX]; + + +typedef struct +{ + char cmd_string[CONFIG_CMD_MAX_LEN+1]; + u16 index; +}ConfigParamStruct; + +/***************************************** +DeviceType 0 终端型号 +ServerAddr 1 域名端口 +ServerLock 2 是否锁死平台 +Protocol 3 协议转换 +ProtoVer 4 协议版本号 +HBProtocol 5 心跳协议 +UploadTime 6 上传时间间隔 +HBTS 7 心跳时间间隔 +LBS 8 上传基站定位 +AngleTime 9 角度上报时间 +MoveAlarm 10 车辆移动报警 +BattUpload 11 电量上传 +CutoffALM 12 断电报警 +LowBattALM 13 低电报警 +SpeedTHR 14 超速阈值(km/h) +AclrAlarm 15 加速度报警 +ShakeAlarm 16 震动报警开关 +ShakeCount 17 震动报警检测次数 +ShakeTime 18 震动检测时间 +VibSetWay 19 是否手动设防 +DefenceDel 20 自动设防时间 +ShakeDelay 21 震动报警延时 +ShakeInter 22 震动报警间隔 +Lang 23 语言 +Zone 24 时区 +AccTHR 25 急加速(g) +TurnTHR 26 急转弯(g) +BrakeTHR 27 急减速(g) +CrashTHR_L 28 轻微碰撞(g) +CrashTHR_M 29 一般碰撞(g) +CrashTHR_H 30 严重碰撞(g) +*****************************************/ +static const ConfigParamStruct s_config_param[] = +{ + {"DEVICETYPE", CFG_DEVICETYPE}, + {"SERVERADDR", CFG_SERVERADDR}, + {"SERVERLOCK", CFG_SERVERLOCK}, + {"PROTOCOL", CFG_PROTOCOL}, + {"PROTOVER", CFG_PROTOCOL_VER}, + {"HBPROTOCOL", CFG_HBPROTOCOL}, + {"UPLOADTIME", CFG_UPLOADTIME}, + {"HBTS", CFG_HEART_INTERVAL}, + {"SENDS", CFG_SLEEP_TIME}, + {"LBS", CFG_IS_LBS_ENABLE}, + {"ANGLETIME", CFG_SEN_ANGLE_SHOW_TIME}, + {"MOVEALARM", CFG_IS_MOVEALARM_ENABLE}, + {"BATTUPLOAD", CFG_BATTUPLOAD_DISABLE}, + {"CUTOFFALM", CFG_CUTOFFALM_DISABLE}, + {"LOWBATTALM", CFG_LOWBATTALM_DISABLE}, + {"SPEEDTHR", CFG_SPEEDTHR}, + {"ACLRALARM", CFG_IS_ACLRALARM_ENABLE}, + {"SHAKEALARM", CFG_IS_SHAKE_ALARM_ENABLE}, + {"SHAKECOUNT", CFG_SHAKE_COUNT}, + {"SHAKETIME", CFG_SHAKE_CHECK_TIME}, + {"VIBSETWAY", CFG_IS_MANUAL_DEFENCE}, + {"DEFDELAY", CFG_AUTO_DEFENCE_DELAY}, + {"SHAKEDELAY", CFG_SHAKE_ALARM_DELAY}, + {"SHAKEINTER", CFG_SHAKE_ALARM_INTERVAL}, + {"LANG", CFG_LANGUAGE}, + {"ZONE", CFG_TIME_ZONE}, + {"ACCTHR", CFG_SEN_RAPID_ACLR}, + {"TURNTHR", CFG_SEN_SUDDEN_TURN}, + {"BRAKETHR", CFG_SEN_EMERGENCY_BRAKE}, + {"CRASHTHR_L", CFG_SEN_SLIGHT_COLLISION}, + {"CRASHTHR_M", CFG_SEN_NORMAL_COLLISION}, + {"CRASHTHR_H", CFG_SEN_SERIOUS_COLLISION}, + {"SMOOTH", CFG_SMOOTH_TRACK}, + {"MINSNR", CFG_MIN_SNR}, + {"BMS", CFG_BMS}, + {"BMSVER", CFG_BMS_VER}, +}; + +typedef struct +{ + char device_str[10]; + u16 idx; +}ConfigDeviceTypeStruct; + +static const ConfigDeviceTypeStruct s_config_device[DEVICE_MAX] = +{ + {"UNKNOW", DEVICE_NONE}, + {"GS03A", DEVICE_GS03A}, + {"AS03A", DEVICE_AS03A}, + {"GS03B", DEVICE_GS03B}, + {"AS03B", DEVICE_AS03B}, + {"GS03F", DEVICE_GS03F}, + {"AS03F", DEVICE_AS03F}, + {"GS07A", DEVICE_GS07A}, + {"AS07A", DEVICE_AS07A}, + {"GS07B", DEVICE_GS07B}, + {"AS07B", DEVICE_AS07B}, + {"GS03I", DEVICE_GS03I}, + {"AS03I", DEVICE_AS03I}, + {"GS03H", DEVICE_GS03H}, + {"GS05A", DEVICE_GS05A}, + {"GS05B", DEVICE_GS05B}, + {"GS05F", DEVICE_GS05F}, + {"GS05I", DEVICE_GS05I}, + {"GS05H", DEVICE_GS05H}, + {"GM06E", DEVICE_GM06E}, + {"GS10", DEVICE_GS10}, +}; + +static GM_ERRCODE config_service_transfer_status(u8 new_status); +static void config_service_init_proc(void); +static void config_service_connecting_proc(void); +static void config_service_work_proc(void); +static void config_service_finish_proc(void); +static void config_service_send_request_failed(void); +static void config_srevice_create_other_services(void); +static void config_service_close(void); +static GM_ERRCODE config_msg_upload(u8 cmd, const u8 *msg, u16 len); +static void config_msg_request(void); +static void config_msg_response(void); +static void config_msg_receive(SocketType *socket); +static void config_msg_content_parse(u8 *pdata, u16 len); +static u16 config_msg_get_item(const ConfigParamDataType data_type, u8 *pOut, const u8 *pSrc, u8 *len); +static void config_msg_param_set(u16 index, u8 *pMsg, u8 len); +static void config_service_device_type(u16 index, u8 *pMsg, u8 len); +static void config_service_set_range_word(u16 index, u8 *pMsg, u8 len, u32 min, u32 max); +static void config_service_set_protocol(u16 index, u8 *pMsg, u8 len); +static void config_service_set_app_protocol(u16 index, u8 *pMsg, u8 len); +static void config_service_set_addr(u16 index, u8 *pMsg, u8 len); +static void config_service_heart_protocol(u16 index, u8 *pMsg, u8 len); +static void config_service_gsensor_set_float(u16 index, u8 *pMsg, u8 len, float min, float max); +static void config_service_finish(u32 wait); +static void config_service_retry_config(void); + +static GM_ERRCODE config_service_transfer_status(u8 new_status) +{ + u8 old_status = (u8)s_config_socket.status; + GM_ERRCODE ret = GM_PARAM_ERROR; + switch(s_config_socket.status) + { + case SOCKET_STATUS_INIT: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_GET_HOST: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + break; + case SOCKET_STATUS_CONNECTING: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_CONNECTING: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_WORK: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_DATA_FINISH: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_ERROR: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + default: + break; + } + + + if(GM_SUCCESS == ret) + { + s_config_socket.status = new_status; + s_config_socket.status_fail_count = 0; + LOG(INFO,"clock(%d) config_service_transfer_status from %s to %s success", util_clock(), + gm_socket_status_string((SocketStatus)old_status), gm_socket_status_string((SocketStatus)new_status)); + } + else + { + LOG(INFO,"clock(%d) config_service_transfer_status from %s to %s failed", util_clock(), + gm_socket_status_string((SocketStatus)old_status), gm_socket_status_string((SocketStatus)new_status)); + } + + return ret; + +} + +/* +// have ip, use ip to connect +// no ip, call gm_socket_get_host_by_name +*/ +static void config_service_init_proc(void) +{ + u8 IP[4]; + gm_socket_get_host_by_name_trigger(&s_config_socket); + system_state_get_ip_cache(SOCKET_INDEX_CONFIG, IP); + if(GM_SUCCESS == gm_is_valid_ip(IP)) + { + GM_memcpy( s_config_socket.ip , IP, sizeof(IP)); + config_service_transfer_status(SOCKET_STATUS_CONNECTING); + if(GM_SUCCESS == gm_socket_connect(&s_config_socket)) + { + } + // else do nothing . connecting_proc will deal. + } + else if((!s_config_socket.excuted_get_host) && (GM_SUCCESS == gm_is_valid_ip(s_config_socket.ip))) + { + config_service_transfer_status(SOCKET_STATUS_CONNECTING); + if(GM_SUCCESS == gm_socket_connect(&s_config_socket)) + { + } + // else do nothing . connecting_proc will deal. + } +} + + +static void config_service_connecting_proc(void) +{ + u32 current_time = util_clock(); + + if((current_time - s_config_socket.send_time) > CONNECT_TIME_OUT) + { + s_config_socket.status_fail_count ++; + config_service_connection_failed(); + + if(s_config_socket.status == SOCKET_STATUS_CONNECTING && + s_config_socket.status_fail_count < MAX_CONNECT_REPEAT) + { + if(GM_SUCCESS == gm_socket_connect(&s_config_socket)) + { + //do nothing. wait callback + } + } + } +} + + +static GM_ERRCODE config_msg_upload(u8 cmd, const u8 *msg, u16 len) +{ + u16 k, msglen; + u8 csm=0; + u8 buff[50]; + u8 imei[GM_IMEI_LEN + 1]; + GM_ERRCODE ret; + + GM_memset(buff, 0x00, sizeof(buff)); + + buff[0] = 0x66; + buff[1] = 0x66; + buff[2] = cmd; + buff[3] = 0x00; + buff[4] = 0x08; + + msglen = 5; + + if(GM_SUCCESS != (ret = gsm_get_imei(imei))) + { + LOG(INFO,"clock(%d) config_msg_upload can not get imei, ret:%d.", util_clock(), ret); + return ret; + } + + buff[msglen++] = util_chr(imei[0]); + buff[msglen++] = MERGEBCD(util_chr(imei[1]), util_chr(imei[2])); + buff[msglen++] = MERGEBCD(util_chr(imei[3]), util_chr(imei[4])); + buff[msglen++] = MERGEBCD(util_chr(imei[5]), util_chr(imei[6])); + buff[msglen++] = MERGEBCD(util_chr(imei[7]), util_chr(imei[8])); + buff[msglen++] = MERGEBCD(util_chr(imei[9]), util_chr(imei[10])); + buff[msglen++] = MERGEBCD(util_chr(imei[11]), util_chr(imei[12])); + buff[msglen++] = MERGEBCD(util_chr(imei[13]), util_chr(imei[14])); + + if ((len > 0) && (NULL != msg)) + { + GM_memcpy(&buff[msglen], msg, len); + msglen += len; + } + + buff[3] = UPPER_BYTE(len + 8); + buff[4] = LOWER_BYTE(len + 8); + + for (k=0; kstatus) + { + return; + } + + //get head then body + if(GM_SUCCESS != fifo_peek(&socket->fifo, head, msg_len)) + { + return; + } + + msg_len = MKWORD(head[3], head[4]); + msg_len = msg_len + CONFIG_MSG_HEAD_LEN + CONFIG_MSG_TAIL_LEN; + + if(msg_len > MAX_GPRS_MESSAGE_LEN) + { + LOG(WARN,"clock(%d) config_msg_receive assert(msg_len(%d)) failed.",util_clock(), msg_len); + //clear fifo and restart socket. + fifo_reset(&socket->fifo); + gm_socket_close_for_reconnect(socket); + return; + } + + pdata = GM_MemoryAlloc(msg_len); + if(pdata == NULL) + { + LOG(WARN,"clock(%d) config_msg_receive assert(GM_MemoryAlloc(%d)) failed.",util_clock(), msg_len); + + //clear fifo and restart socket. + fifo_reset(&socket->fifo); + gm_socket_close_for_reconnect(socket); + return; + } + + if(GM_SUCCESS != fifo_peek(&socket->fifo, pdata, msg_len)) + { + GM_MemoryFree(pdata); + + if(packet_error_start == 0) + { + LOG(DEBUG,"clock(%d) config_msg_receive get msg failed. len:%d", util_clock(), msg_len); + log_service_print_hex((const char*)head, sizeof(head)); + packet_error_start = util_clock(); + } + else + { + if((util_clock() - packet_error_start) > MAX_GPRS_PART_MESSAGE_TIMEOUT) + { + LOG(WARN,"clock(%d) config_msg_receive MAX_GPRS_PART_MESSAGE_TIMEOUT.",util_clock()); + //clear fifo and restart socket. + fifo_reset(&socket->fifo); + gm_socket_close_for_reconnect(socket); + packet_error_start = 0; + } + } + return; + } + + fifo_pop_len(&socket->fifo, msg_len); + + LOG(DEBUG,"clock(%d) config_msg_receive msg fifo(%p) len(%d)", + util_clock(), &socket->fifo, msg_len); + + if(GM_SUCCESS != (ret = gsm_get_imei(imei))) + { + LOG(INFO,"clock(%d) config_msg_receive can not get imei, ret:%d.", util_clock(), ret); + GM_MemoryFree(pdata); + return; + } + + for (index=0; index> 4) & 0x0F, 'x'); + resp_imei[idx+1] = util_asc(pdata[index+jval] & 0x0F, 'x'); + } + + if (0 != GM_memcmp(resp_imei, imei, GM_strlen((const char *)imei))) + { + LOG(INFO,"clock(%d) config_msg_receive imei err. %s != %s", util_clock(), resp_imei, imei); + break; + } + + index += 8; + if (0x00 != pdata[index]) + { + config_msg_content_parse(&pdata[index+1], msg_len - index-2); + config_service_save_to_local(); + } + + config_msg_response(); + config_service_finish(CONFIG_PING_TIME); + break; + + default: + break; + } + + GM_MemoryFree(pdata); +} + + +/* + get msg from fifo +*/ +static void config_service_work_proc(void) +{ + u32 current_time = util_clock(); + + if((current_time - s_config_socket.send_time) > MESSAGE_TIME_OUT) + { + s_config_socket.status_fail_count ++; + config_service_send_request_failed(); + + if(s_config_socket.status == SOCKET_STATUS_WORK && + s_config_socket.status_fail_count < MAX_CONNECT_REPEAT) + { + config_msg_request(); + } + } + + config_msg_receive(&s_config_socket); +} + + +static void config_service_retry_config(void) +{ + u32 current_time = util_clock(); + + if((current_time - s_config_socket_extend.last_ok_time) > s_config_socket_extend.wait) + { + LOG(DEBUG,"clock(%d) config_service_finish_proc cur(%d) - lastok(%d) > wait(%d).", + util_clock(), current_time, s_config_socket_extend.last_ok_time,s_config_socket_extend.wait); + s_config_socket_extend.last_ok_time = 0; + s_config_socket_extend.wait = CONFIG_PING_TIME; + config_service_transfer_status(SOCKET_STATUS_INIT); + } + +} + + + +static void config_service_finish_proc(void) +{ + if(!gprs_is_ok()) + { + return; + } + + config_srevice_create_other_services(); + + config_service_retry_config(); +} + + + +void config_service_connection_ok(void) +{ + config_service_transfer_status(SOCKET_STATUS_WORK); + config_msg_request(); +} + +void config_service_close_for_reconnect(void) +{ + config_service_destroy(); +} + + +void config_service_connection_failed(void) +{ + config_service_close(); + + if(s_config_socket.status_fail_count >= MAX_CONNECT_REPEAT) + { + // if excuted get_host transfer to error statu, else get_host. + if(s_config_socket.excuted_get_host || (s_config_socket.addr[0] == 0)) + { + config_service_finish(CONFIG_PING_TIME); + } + else + { + config_service_transfer_status(SOCKET_STATUS_INIT); + } + } + // else do nothing . wait connecting proc to deal. +} + + +static void config_service_send_request_failed(void) +{ + if(s_config_socket.status_fail_count >= MAX_CONNECT_REPEAT) + { + LOG(INFO,"clock(%d) config_service_send_request_failed s_config_socket.status_fail_count(%d) > %d.", + util_clock(), s_config_socket.status_fail_count,MAX_CONNECT_REPEAT); + config_service_finish(CONFIG_PING_TIME); + GM_memset(s_config_socket.ip,0,sizeof(s_config_socket.ip)); + } + // else do nothing . +} + +GM_ERRCODE config_service_create(void) +{ + u8 addr[2*GOOME_DNS_MAX_LENTH+1]; + u8 IP[4]; + u32 port = 0; + u8 idx = 0; + + s_config_socket.access_id = SOCKET_INDEX_CONFIG; + gm_socket_init(&s_config_socket); + + GM_memset(addr, 0x00, sizeof(addr)); + idx = GM_sscanf((const char*)config_service_get_pointer(CFG_CFGSERVERADDR), "%[^:]:%d", addr, &port); + if (idx != 2) + { + LOG(WARN,"clock(%d) config_service_create assert(idx ==2) failed.", util_clock()); + return GM_PARAM_ERROR; + } + + if(GM_SUCCESS != GM_ConvertIpAddr(addr, IP)) + { + if(util_is_valid_dns(addr, GM_strlen((const char *)addr))) + { + gm_socket_set_addr(&s_config_socket, addr, GM_strlen((const char*)addr), port, STREAM_TYPE_DGRAM); + system_state_get_ip_cache(SOCKET_INDEX_CONFIG, IP); + gm_socket_set_ip_port(&s_config_socket, IP, port, STREAM_TYPE_DGRAM); + } + else + { + LOG(WARN,"clock(%d) config_service_create assert(dns(%s)) failed.", util_clock(), addr); + return GM_PARAM_ERROR; + } + } + else + { + gm_socket_set_ip_port(&s_config_socket, IP, port, STREAM_TYPE_DGRAM); + } + + s_config_socket_extend.last_ok_time = 0; + s_config_socket_extend.wait = CONFIG_PING_TIME; + + LOG(WARN,"clock(%d) config_service_create access_id(%d) fifo(%p).", util_clock(), s_config_socket.access_id, &s_config_socket.fifo); + return GM_SUCCESS; +} + + +static void config_service_finish(u32 wait) +{ + config_service_close(); + + s_config_socket_extend.last_ok_time=util_clock(); + s_config_socket_extend.wait=wait; + + config_service_transfer_status(SOCKET_STATUS_DATA_FINISH); +} + +GM_ERRCODE config_service_destroy(void) +{ + if(SOCKET_STATUS_ERROR == s_config_socket.status) + { + return GM_SUCCESS; + } + + config_service_close(); + + if(s_config_socket.status < SOCKET_STATUS_DATA_FINISH) + { + // 配置正在获取过程中断了网, 重建连接 + config_service_transfer_status(SOCKET_STATUS_INIT); + return GM_SUCCESS; + } + + //config_service是在gprs_create中创建, 后面 重建连接, 所以保留fifo + + s_config_socket_extend.last_ok_time=util_clock(); + s_config_socket_extend.wait=CONFIG_PING_TIME; + + config_service_transfer_status(SOCKET_STATUS_ERROR); + return GM_SUCCESS; +} + +static void config_service_close(void) +{ + if(s_config_socket.id >=0) + { + GM_SocketClose(s_config_socket.id); + s_config_socket.id=-1; + } +} + + + +GM_ERRCODE config_service_timer_proc(void) +{ + if(!s_config_socket.fifo.base_addr) + { + return GM_SUCCESS; + } + + switch(s_config_socket.status) + { + case SOCKET_STATUS_INIT: + config_service_init_proc(); + break; + case SOCKET_STATUS_CONNECTING: + config_service_connecting_proc(); + break; + case SOCKET_STATUS_WORK: + config_service_work_proc(); + break; + case SOCKET_STATUS_DATA_FINISH: + config_service_finish_proc(); + break; + case SOCKET_STATUS_ERROR: + config_service_finish_proc(); + break; + default: + LOG(WARN,"clock(%d) config_service_timer_proc assert(s_config_socket.status(%d)) unknown.", util_clock(), s_config_socket.status); + return GM_ERROR_STATUS; + } + + return GM_SUCCESS; +} + +void config_service_set(ConfigParamEnum id, ConfigParamDataType type, const void* buf, u16 len) +{ + + s_configs[id].type = type; + + switch(s_configs[id].type) + { + case TYPE_STRING: + s_configs[id].len = len; + GM_MemoryFree(s_configs[id].data.str); + s_configs[id].data.str = GM_MemoryAlloc(len + 1); + GM_memcpy(s_configs[id].data.str, buf, len); + s_configs[id].data.str[len] = 0; + break; + case TYPE_INT: + s_configs[id].len = 4; + GM_memcpy(&s_configs[id].data.i, buf, s_configs[id].len); + break; + case TYPE_SHORT: + s_configs[id].len = 2; + GM_memcpy(&s_configs[id].data.s, buf, s_configs[id].len); + break; + case TYPE_BYTE: + s_configs[id].len = 1; + s_configs[id].data.b = *((u8 *)buf); + break; + case TYPE_BOOL: + s_configs[id].len = 1; + s_configs[id].data.b = *((u8 *)buf); + break; + case TYPE_FLOAT: + s_configs[id].len = 4; + GM_memcpy(&s_configs[id].data.s, buf, s_configs[id].len); + break; + default: + LOG(WARN,"clock(%d) config_service_set assert(s_configs[%d].type(%d)) unknown.", util_clock(),id,s_configs[id].type); + return; + } + + if(len != s_configs[id].len) + { + LOG(WARN,"clock(%d) config_service_set assert(len == s_configs[id].len) failed,s_configs[%d].len=%d", util_clock(),id,s_configs[id].len); + } +} + + + + +/*获取指定id对应的配置 */ +GM_ERRCODE config_service_get(ConfigParamEnum id, ConfigParamDataType type, void* buf, u16 len) +{ + if(type != s_configs[id].type) + { + LOG(WARN,"clock(%d) config_service_get assert(s_configs[%d].type(%d)== %d) failed.", util_clock(),id,s_configs[id].type, type); + return GM_PARAM_ERROR; + } + + switch(s_configs[id].type) + { + case TYPE_STRING: + if(len < s_configs[id].len) + { + LOG(WARN,"clock(%d) config_service_get assert(s_configs[%d].type(%d)) len:%d < %d.", util_clock(),id,s_configs[id].type,len,s_configs[id].len); + return GM_PARAM_ERROR; + } + if(s_configs[id].data.str) + { + GM_memcpy(buf, s_configs[id].data.str, s_configs[id].len); + } + else + { + GM_memcpy(buf, "", 1); + } + if(len > s_configs[id].len) + { + ((u8 *)buf)[s_configs[id].len] = 0; + } + else + { + ((u8 *)buf)[len -1] = 0; + } + break; + case TYPE_INT: + if(s_configs[id].len != len) + { + LOG(WARN,"clock(%d) config_service_get assert(s_configs[%d].type(%d)) len:%d != %d.", util_clock(),id,s_configs[id].type,len,s_configs[id].len); + return GM_PARAM_ERROR; + } + GM_memcpy(buf, &s_configs[id].data.i, s_configs[id].len); + break; + case TYPE_SHORT: + if(s_configs[id].len != len) + { + LOG(WARN,"clock(%d) config_service_get assert(s_configs[%d].type(%d)) len:%d != %d.", util_clock(),id,s_configs[id].type,len,s_configs[id].len); + return GM_PARAM_ERROR; + } + GM_memcpy(buf, &s_configs[id].data.s, s_configs[id].len); + break; + case TYPE_BYTE: + if(s_configs[id].len != len) + { + LOG(WARN,"clock(%d) config_service_get assert(s_configs[%d].type(%d)) len:%d != %d.", util_clock(),id,s_configs[id].type,len,s_configs[id].len); + return GM_PARAM_ERROR; + } + *((u8 *)buf) = s_configs[id].data.b; + break; + case TYPE_BOOL: + if(s_configs[id].len != len) + { + LOG(WARN,"clock(%d) config_service_get assert(s_configs[%d].type(%d)) len:%d != %d.", util_clock(),id,s_configs[id].type,len,s_configs[id].len); + return GM_PARAM_ERROR; + } + *((u8 *)buf) = s_configs[id].data.b; + break; + case TYPE_FLOAT: + if(s_configs[id].len != len) + { + LOG(WARN,"clock(%d) config_service_get assert(s_configs[%d].type(%d)) len:%d != %d.", util_clock(),id,s_configs[id].type,len,s_configs[id].len); + return GM_PARAM_ERROR; + } + GM_memcpy(buf, &s_configs[id].data.f, s_configs[id].len); + break; + default: + LOG(WARN,"clock(%d) config_service_get assert(s_configs[%d].type(%d)) unknown.", util_clock(),id,s_configs[id].type); + return GM_PARAM_ERROR; + } + return GM_SUCCESS; +} + + +u16 config_service_get_length(ConfigParamEnum id, ConfigParamDataType type) +{ + if(id >= CFG_PARAM_MAX ) + { + LOG(WARN,"clock(%d) config_service_get assert(id(%d)) failed.", util_clock(),id); + return 0; + } + + return s_configs[id].len; +} + + +void* config_service_get_pointer(ConfigParamEnum id) +{ + static u8 empty_string[1] = ""; + + switch(s_configs[id].type) + { + case TYPE_STRING: + if(s_configs[id].data.str) + { + return s_configs[id].data.str; + } + else + { + return empty_string; + } + case TYPE_INT: + return &s_configs[id].data.i; + case TYPE_SHORT: + return &s_configs[id].data.s; + case TYPE_BYTE: + return &s_configs[id].data.b; + case TYPE_BOOL: + return &s_configs[id].data.b; + case TYPE_FLOAT: + return &s_configs[id].data.f; + default: + LOG(WARN,"clock(%d) config_service_get_pointer assert(s_configs[%d].type(%d)) unknown.", util_clock(),id,s_configs[id].type); + return NULL; + } +} + + + +void config_msg_content_parse(u8 *pdata, u16 len) +{ + ConfigParamDataType data_type = TYPE_NONE; + u8 *psrc = pdata; + u8 index = 0; + u16 parse_len = 0; + u8 cmd_string[CONFIG_CMD_MAX_LEN+1] = {0}; + u8 msg_buff[CONFIG_STRING_MAX_LEN+1] = {0}; + u8 msg_len = 0; + bool has_config = false; + + JsonObject* p_json_log = json_create(); + json_add_string(p_json_log, "event", "config"); + + while(parse_len <= (len-12)) + { + data_type = (ConfigParamDataType)(psrc[parse_len]); + parse_len++; + + + GM_memcpy(cmd_string, &psrc[parse_len], CONFIG_CMD_MAX_LEN); + cmd_string[CONFIG_CMD_MAX_LEN] = 0; + parse_len += CONFIG_CMD_MAX_LEN; + + GM_memset(msg_buff,0,sizeof(msg_buff)); + parse_len += config_msg_get_item(data_type, msg_buff, &psrc[parse_len], &msg_len); + + switch (data_type) + { + case 1: + json_add_int(p_json_log, (const char*)cmd_string, MKDWORD(msg_buff[0], msg_buff[1], msg_buff[2], msg_buff[3])); + break; + case 2: + json_add_int(p_json_log, (const char*)cmd_string, MKDWORD(msg_buff[0], msg_buff[1], msg_buff[2], msg_buff[3])/1000.0); + break; + case 3: + json_add_string(p_json_log, (const char*)cmd_string, (const char*)msg_buff); + break; + case 4: + json_add_int(p_json_log, (const char*)cmd_string, msg_buff[0]); + break; + default: + json_add_string(p_json_log, (const char*)cmd_string, "unknown config name"); + break; + } + + + util_remove_char(cmd_string, GM_strlen((const char*)cmd_string),' '); + util_string_upper(cmd_string, GM_strlen((const char*)cmd_string)); + + + //特殊配置,进行校准修复 + if (0 == GM_strcmp((const char*)cmd_string, "REPAIRRAMP") && msg_buff[0]) + { + auto_test_repair_ramp(); + has_config = true; + } + + for (index=0; index< (sizeof(s_config_param)/sizeof(ConfigParamStruct)); index++) + { + if (0 == GM_strcmp((const char*)cmd_string, (const char*)s_config_param[index].cmd_string)) + { + config_msg_param_set(s_config_param[index].index, msg_buff, msg_len); + has_config = true; + break; + } + } + }; + + if (has_config) + { + config_service_save_to_local(); + gps_service_change_config(); + log_service_upload(INFO, p_json_log); + } + else + { + json_destroy(p_json_log); + p_json_log = NULL; + } + + return; +} + +static void config_service_set_addr(u16 index, u8 *pMsg, u8 len) +{ + u8 addr[100]; + u8 IP[4]; + u32 port = 0; + u8 idx = 0; + + GM_memset(addr, 0x00, sizeof(addr)); + idx = GM_sscanf((const char*)pMsg, "%[^:]:%d", addr, &port); + if (idx != 2) + { + LOG(INFO,"clock(%d) config_service_set_addr assert(2 fields(%s)) failed.", util_clock(), pMsg); + return; + } + + if(GM_SUCCESS != GM_ConvertIpAddr(addr, IP)) + { + if(util_is_valid_dns(addr, GM_strlen((const char *)addr))) + { + LOG(INFO,"clock(%d) config_service_set_addr(%s) success.", util_clock(), pMsg); + config_service_set((ConfigParamEnum)index, TYPE_STRING, pMsg, len); + } + else + { + LOG(WARN,"clock(%d) config_service_set_addr assert(dns(%s)) failed.", util_clock(), addr); + return; + } + } + else + { + LOG(INFO,"clock(%d) config_service_set_addr(%s) success.", util_clock(), pMsg); + config_service_set((ConfigParamEnum)index, TYPE_STRING, pMsg, len); + } +} + +static void config_service_set_byte(u16 index, u8 *pMsg, u8 len) +{ + if (NULL == pMsg || len < sizeof(U32)) + { + LOG(INFO,"clock(%d) config_service_set_range_word index(%d) len %d failed.", util_clock(),index,len); + return; + } + config_service_set((ConfigParamEnum)index, TYPE_BYTE, pMsg, sizeof(U8)); + LOG(INFO,"clock(%d) config_service_set_byte index(%d) value %d.", util_clock(),index,pMsg[0]); +} + + +static void config_service_set_range_word(u16 index, u8 *pMsg, u8 len, u32 min, u32 max) +{ + U32 dword_value = 0; + if (NULL == pMsg || len < sizeof(U32)) + { + LOG(INFO,"clock(%d) config_service_set_range_word index(%d) len %d failed.", util_clock(),index,len); + return; + } + dword_value = MKDWORD(pMsg[0], pMsg[1],pMsg[2], pMsg[3]); + if (dword_value >= min && dword_value <= max) + { + config_service_set((ConfigParamEnum)index, TYPE_SHORT, &dword_value, sizeof(U16)); + LOG(INFO,"clock(%d) config_service_set_range_word index(%d) value %d.", util_clock(),index,dword_value); + } + else + { + LOG(WARN,"clock(%d) config_service_set_range_word index(%d) value %d failed.", util_clock(),index,dword_value); + } +} + +static void config_service_set_protocol(u16 index, u8 *pMsg, u8 len) +{ + u32 dword_value; + u8 byte_value; + + if(len < 4) + { + LOG(INFO,"clock(%d) config_service_set_protocol index(%d) len %d failed.", util_clock(),index,len); + } + dword_value = MKDWORD(pMsg[0], pMsg[1], pMsg[2], pMsg[3]); + byte_value = dword_value; + if (byte_value >= PROTOCOL_GOOME && byte_value <= PROTOCOL_BSJ) + { + config_service_set(CFG_PROTOCOL, TYPE_BYTE, &byte_value, sizeof(byte_value)); + LOG(INFO,"clock(%d) config_service_set_protocol CFG_PROTOCOL value %d.", util_clock(),byte_value); + } + else + { + LOG(INFO,"clock(%d) config_service_set_protocol CFG_PROTOCOL value %d failed.", util_clock(),byte_value); + } +} + + +static void config_service_set_app_protocol(u16 index, u8 *pMsg, u8 len) +{ + u32 dword_value; + u8 byte_value; + + if(len < 4) + { + LOG(INFO,"clock(%d) config_service_set_app_protocol index(%d) len %d failed.", util_clock(),index,len); + } + dword_value = MKDWORD(pMsg[0], pMsg[1], pMsg[2], pMsg[3]); + byte_value = dword_value; + if (byte_value >= PROTOCOL_VER_GT02 && byte_value <= PROTOCOL_VER_GT06) + { + config_service_set(CFG_PROTOCOL_VER, TYPE_BYTE, &byte_value, sizeof(byte_value)); + LOG(INFO,"clock(%d) config_service_set_protocol CFG_PROTOCOL_VER value %d.", util_clock(),byte_value); + } + else + { + LOG(INFO,"clock(%d) config_service_set_app_protocol CFG_PROTOCOL_VER value %d failed.", util_clock(),byte_value); + } +} + + +static void config_service_heart_protocol(u16 index, u8 *pMsg, u8 len) +{ + u32 dword_value; + u8 heart_mode; + + if(len < 4) + { + LOG(INFO,"clock(%d) config_service_gsensor_range index(%d) len %d failed.", util_clock(),index,len); + } + dword_value = MKDWORD(pMsg[0], pMsg[1], pMsg[2], pMsg[3]); + switch(dword_value) + { + case 3: + dword_value = HEART_NORMAL; + break; + case 7: + dword_value = HEART_EXPAND; + break; + case 0: + dword_value = HEART_SMART; + break; + default: + LOG(INFO,"clock(%d) config_service_heart_protocol (%d) failed.", util_clock(),dword_value); + return; + } + + heart_mode = (u8)dword_value; + config_service_set((ConfigParamEnum)index, TYPE_BYTE, &heart_mode, sizeof(heart_mode)); + LOG(INFO,"clock(%d) config_service_heart_protocol index(%d) value %d.", util_clock(),index,heart_mode); +} + + +static void config_service_gsensor_set_float(u16 index, u8 *pMsg, u8 len, float min, float max) +{ + u32 dword_value; + float float_value; + if(len < 4) + { + LOG(INFO,"clock(%d) config_service_gsensor_set_float index(%d) len %d failed.", util_clock(),index,len); + } + dword_value = MKDWORD(pMsg[0], pMsg[1], pMsg[2], pMsg[3]); + float_value = dword_value / 1000.0f; + if (float_value >= min && float_value <= max) + { + config_service_set((ConfigParamEnum)index, TYPE_FLOAT, &float_value, sizeof(float_value)); + LOG(INFO,"clock(%d) config_service_gsensor_set_float index(%d) value %f.", util_clock(),index,float_value); + } + else + { + LOG(ERROR,"clock(%d) config_service_gsensor_set_float CFG_ACCTHR[%f] failed.", util_clock(),float_value); + } + +} + + +static void config_service_device_type(u16 index, u8 *pMsg, u8 len) +{ + u16 idx; + + for (idx=0; idx= DEVICE_MAX) + { + LOG(INFO,"clock(%d) config_service_get_device_type assert(device_type(%d)) failed.", util_clock(),index); + return NULL; + } + return s_config_device[index].device_str; +} + +ConfigDeviceTypeEnum config_service_get_device_type_id(const char* dev_type) +{ + U8 index = 0; + for (index = 0; index < DEVICE_MAX; ++index) + { + if(!GM_strcmp(s_config_device[index].device_str,dev_type)) + { + return (ConfigDeviceTypeEnum)s_config_device[index].idx; + } + } + return DEVICE_MAX; +} + +static void config_msg_param_set(u16 index, u8 *pMsg, u8 len) +{ + u8 value_u8; + switch(index) + { + case CFG_DEVICETYPE: + config_service_device_type(index, pMsg, len); + break; + + case CFG_SERVERADDR: + config_service_set_addr(index, pMsg, len); + break; + + case CFG_SERVERLOCK: + config_service_set_byte(index, pMsg, sizeof(U32)); + break; + + case CFG_PROTOCOL: + config_service_set_protocol(index, pMsg, len); + break; + + case CFG_PROTOCOL_VER: + config_service_set_app_protocol(index, pMsg, len); + break; + + case CFG_HBPROTOCOL: + config_service_heart_protocol(index, pMsg, len); + break; + + case CFG_UPLOADTIME: + config_service_set_range_word((ConfigParamEnum)index, pMsg, sizeof(U32),CONFIG_UPLOAD_TIME_MIN,CONFIG_UPLOAD_TIME_MAX); + break; + + case CFG_HEART_INTERVAL: + config_service_set_range_word((ConfigParamEnum)index, pMsg, sizeof(U32),GOOME_HEARTBEAT_MIN,GOOME_HEARTBEAT_MAX); + break; + + case CFG_SLEEP_TIME: + config_service_set_range_word((ConfigParamEnum)index, pMsg, sizeof(U32),GOOME_SLEEPTIME_MIN,GOOME_SLEEPTIME_MAX); + break; + + case CFG_IS_LBS_ENABLE: + config_service_set((ConfigParamEnum)index, TYPE_BOOL, pMsg, sizeof(bool)); + break; + + case CFG_SEN_ANGLE_SHOW_TIME: + config_service_set_byte(index, &pMsg[3], sizeof(U32)); + break; + + case CFG_IS_MOVEALARM_ENABLE: + config_service_set((ConfigParamEnum)index, TYPE_BOOL, pMsg, sizeof(u8)); + break; + + case CFG_SMOOTH_TRACK: + config_service_set((ConfigParamEnum)index, TYPE_BOOL, pMsg, sizeof(u8)); + break; + + case CFG_BATTUPLOAD_DISABLE: + value_u8 = *pMsg; + value_u8 = value_u8?0:1; + config_service_set((ConfigParamEnum)index, TYPE_BYTE, &value_u8, sizeof(u8)); + break; + + case CFG_CUTOFFALM_DISABLE: + { + //后台配置1是打开0是关闭;设备中存储0是打开1是关闭 + U8 cut_off_alm_disable = pMsg[0] ? 0 : 1; + config_service_set((ConfigParamEnum)index, TYPE_BYTE, &cut_off_alm_disable, sizeof(cut_off_alm_disable)); + } + break; + + case CFG_LOWBATTALM_DISABLE: + { + //后台配置1是打开0是关闭;设备中存储0是打开1是关闭 + U8 low_batt_alm_disable = pMsg[0] ? 0 : 1; + config_service_set((ConfigParamEnum)index, TYPE_BYTE, &low_batt_alm_disable, sizeof(low_batt_alm_disable)); + } + break; + + case CFG_SPEEDTHR: + config_service_set_byte(index, &pMsg[3], sizeof(U32)); + break; + + case CFG_IS_ACLRALARM_ENABLE: + config_service_set((ConfigParamEnum)index, TYPE_BOOL, pMsg, sizeof(u8)); + break; + + case CFG_IS_SHAKE_ALARM_ENABLE: + config_service_set((ConfigParamEnum)index, TYPE_BOOL, pMsg, sizeof(u8)); + break; + + case CFG_SHAKE_COUNT: + config_service_set_byte(index, &pMsg[3], sizeof(U32)); + break; + + case CFG_SHAKE_CHECK_TIME: + config_service_set_byte(index, &pMsg[3], sizeof(U32)); + break; + + case CFG_IS_MANUAL_DEFENCE: + config_service_set((ConfigParamEnum)index, TYPE_BOOL, pMsg, sizeof(u8)); + break; + + case CFG_AUTO_DEFENCE_DELAY: + config_service_set_range_word((ConfigParamEnum)index, pMsg, sizeof(U32),CONFIG_AUTODEFDELAY_MIN,CONFIG_AUTODEFDELAY_MAX); + break; + + case CFG_SHAKE_ALARM_DELAY: + config_service_set_range_word((ConfigParamEnum)index, pMsg, sizeof(U32),CONFIG_SHAKEALARMDELAY_MIN,CONFIG_SHAKEALARMDELAY_MAX); + break; + + case CFG_SHAKE_ALARM_INTERVAL: + config_service_set_range_word((ConfigParamEnum)index, pMsg, sizeof(U32),CONFIG_SHAKEALARMINTERVAL_MIN,CONFIG_SHAKEALARMINTERVAL_MAX); + break; + + case CFG_LANGUAGE: + config_service_set_range_word((ConfigParamEnum)index, pMsg, sizeof(U32),0,1); + break; + + case CFG_TIME_ZONE: + config_service_set_byte(index, &pMsg[3], sizeof(U32)); + break; + + case CFG_SEN_RAPID_ACLR: + config_service_gsensor_set_float(index, pMsg, len, CONFIG_ACCTHR_MIN, CONFIG_ACCTHR_MAX); + break; + + case CFG_SEN_SUDDEN_TURN: + config_service_gsensor_set_float(index, pMsg, len, CONFIG_TURNTHR_MIN, CONFIG_TURNTHR_MAX); + break; + + case CFG_SEN_EMERGENCY_BRAKE: + config_service_gsensor_set_float(index, pMsg, len, CONFIG_BRAKETHR_MIN, CONFIG_BRAKETHR_MAX); + break; + + case CFG_SEN_SLIGHT_COLLISION: + config_service_gsensor_set_float(index, pMsg, len, CONFIG_CRASHLTHR_MIN, CONFIG_CRASHLTHR_MAX); + break; + + case CFG_SEN_NORMAL_COLLISION: + config_service_gsensor_set_float(index, pMsg, len, CONFIG_CRASHMTHR_MIN, CONFIG_CRASHMTHR_MAX); + break; + + case CFG_SEN_SERIOUS_COLLISION: + config_service_gsensor_set_float(index, pMsg, len, CONFIG_CRASHHTHR_MIN, CONFIG_CRASHHTHR_MAX); + break; + + case CFG_MIN_SNR: + config_service_set_byte(index, &pMsg[3], sizeof(U32)); + break; + + default: + break; + } + + return; +} + + + +static u16 config_msg_get_item(const ConfigParamDataType data_type, u8 *pOut, const u8 *pSrc, u8 *len) +{ + u16 msg_len = 4; + u8 seek = 0; + + *len = msg_len; + if ((NULL == pOut) || (NULL == pSrc)) + { + return 0; + } + + if (TYPE_STRING == data_type) + { + //第一字节是长度 + msg_len = *pSrc; + *len = (msg_len > CONFIG_STRING_MAX_LEN) ? CONFIG_STRING_MAX_LEN : msg_len; + seek = 1; + pSrc++; + if(*len) + { + GM_memcpy(pOut, pSrc, *len); + pOut[*len] = 0; + } + else + { + pOut[0] = 0; + } + } + else if (TYPE_BOOL == data_type) + { + *len = msg_len = 1; + GM_memcpy(pOut, pSrc, *len); + } + else + { + //*len = msg_len = 4; + GM_memcpy(pOut, pSrc, *len); + } + return msg_len + seek; +} + +static void config_srevice_create_other_services(void) +{ + static bool first_create = false; // already created at gprs_init + gps_service_create(first_create); + + if(first_create) + { + // after first create, all later create is not first create. + first_create = false; + } +} + +ConfigProtocolEnum config_service_get_app_protocol() +{ + u8 byte_value; + config_service_get(CFG_PROTOCOL, TYPE_BYTE, &byte_value, sizeof(byte_value)); + switch (byte_value) + { + case PROTOCOL_GOOME: + return PROTOCOL_GOOME; + case PROTOCOL_CONCOX: + return PROTOCOL_CONCOX; + case PROTOCOL_JT808: + return PROTOCOL_JT808; + case PROTOCOL_BSJ: + return PROTOCOL_BSJ; + default: + LOG(DEBUG,"config_service_get_app_protocol (CFG_PROTOCOL(PROTOCOL_NONE)."); + return PROTOCOL_NONE; + } +} + +ConfigHearUploadEnum config_service_get_heartbeat_protocol(void) +{ + u8 byte_value; + config_service_get(CFG_HBPROTOCOL, TYPE_BYTE, &byte_value, sizeof(byte_value)); + switch (byte_value) + { + case HEART_SMART: + if(config_service_is_main_server_goome() && (PROTOCOL_GOOME== config_service_get_app_protocol())) + { + return HEART_EXPAND; + } + else + { + return HEART_NORMAL; + } + case HEART_NORMAL: + return HEART_NORMAL; + case HEART_EXPAND: + return HEART_EXPAND; + default: + LOG(WARN,"clock(%d) config_service_get_heartbeat_protocol assert(heart_protocol(%d)) failed.", util_clock(),byte_value); + return HEART_NORMAL; + } +} + + +S8 config_service_get_zone(void) +{ + GM_ERRCODE ret; + s8 time_zone = 0; + + //获取本地时间 + ret = config_service_get(CFG_TIME_ZONE, TYPE_BYTE, &time_zone, sizeof(time_zone)); + if (GM_SUCCESS != ret) + { + LOG(INFO,"clock(%d) config_service_get_zone failed,ret=%d", util_clock(),ret); + } + return time_zone; +} + +bool config_service_is_main_server_goome(void) +{ + char *addr; + addr = config_service_get_pointer(CFG_SERVERADDR); + if (GM_strstr(addr, GOOME_GPSOO_DNS) > 0) + { + return true; + } + + if (GM_strstr(addr, GOOME_LITEDEV_DNS) > 0) + { + return true; + } + + return false; +} + +bool config_service_is_alarm_sms_to_one(void) +{ + u8 value_u8; + config_service_get(CFG_ALARM_SMS_ONE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + return (value_u8 != 0); +} + + +u8 config_service_get_sos_number(u8 index, u8 *buf, u16 len) +{ + GM_ERRCODE ret; + + if(index > 3) + { + LOG(WARN,"clock(%d) config_service_get_sos_number assert(index(%d)) failed.", util_clock(),index); + return 0; + } + + index = index + CFG_USER1_NUMBER; + ret = config_service_get((ConfigParamEnum)index, TYPE_STRING, buf, len); + if (GM_SUCCESS != ret) + { + LOG(INFO,"clock(%d) config_service_get_sos_number failed,ret=%d", util_clock(),ret); + return 0; + } + + len = config_service_get_length((ConfigParamEnum)index, TYPE_STRING); + if (len > 15) + { + len = 15; + } + + return len; +} + + +bool config_service_is_agps(void) +{ + u8 value_u8; + config_service_get(CFG_OPEN_APGS, TYPE_BOOL, &value_u8, sizeof(value_u8)); + return (value_u8 != 0); +} + + + +GPSChipType config_service_get_gps_type(void) +{ + GM_ERRCODE ret; + GPSChipType gps_chip_type = GM_GPS_TYPE_UNKNOWN; + + ret = config_service_get(CFG_GPS_TYPE, TYPE_BYTE, &gps_chip_type, sizeof(gps_chip_type)); + if (GM_SUCCESS != ret) + { + LOG(INFO,"clock(%d) config_service_get_gps_type failed,ret=%d", util_clock(),ret); + } + + if(gps_chip_type > (u32)GM_GPS_TYPE_AT_AGPS) + { + LOG(INFO,"clock(%d) config_service_get_gps_type assert(gps_chip_type(%d) failed.", util_clock(),gps_chip_type); + gps_chip_type = GM_GPS_TYPE_UNKNOWN; + } + + return (GPSChipType)gps_chip_type; +} + + +void config_service_change_ip(ConfigParamEnum idx, u8 *buf, u16 len) +{ + u8 dns_str[GOOME_DNS_MAX_LENTH]; + u8 value_str[CONFIG_STRING_MAX_LEN]; + u8 IP[4]; + u32 value_u32; + s32 index; + + if(len >= GOOME_DNS_MAX_LENTH) + { + LOG(WARN,"clock(%d) config_service_change_ip assert(len(%d) of CFG_SERVERADDR failed.", util_clock(),len); + return; + } + + GM_memset(value_str, 0, sizeof(value_str)); + GM_memcpy(value_str, buf, len); + if(GM_SUCCESS != GM_ConvertIpAddr(value_str, IP)) + { + if(!util_is_valid_dns(value_str, len)) + { + LOG(WARN,"clock(%d) config_service_change_ip assert(valid dns(%s) failed.", util_clock(), value_str); + return; + } + } + + GM_memset(dns_str, 0x00, sizeof(dns_str)); + index = GM_sscanf((const char*)config_service_get_pointer(idx), "%[^:]:%d", dns_str, &value_u32); + if ((index != 2) || (GM_strlen((const char*)dns_str) >= GOOME_DNS_MAX_LENTH) || (value_u32>65535)) + { + LOG(WARN,"clock(%d) config_service_change_ip assert(idx ==2) of CFG_SERVERADDR failed.", util_clock()); + return; + } + + GM_strcpy((char *)dns_str,(char *)value_str); + GM_snprintf((char *)value_str, sizeof(value_str),"%s:%d", dns_str, value_u32); + config_service_set(idx, TYPE_STRING, value_str, GM_strlen((const char*)value_str)); +} + + +void config_service_change_port(ConfigParamEnum idx, u16 port) +{ + u8 dns_str[GOOME_DNS_MAX_LENTH]; + u8 value_str[CONFIG_STRING_MAX_LEN]; + u32 value_u32; + s32 index; + + GM_memset(dns_str, 0x00, sizeof(dns_str)); + index = GM_sscanf((const char*)config_service_get_pointer(idx), "%[^:]:%d", dns_str, &value_u32); + if ((index != 2) || (GM_strlen((const char*)dns_str) >= GOOME_DNS_MAX_LENTH) || (value_u32>65535)) + { + LOG(WARN,"clock(%d) config_service_change_port assert(idx ==2) of CFG_SERVERADDR failed.", util_clock()); + return; + } + + GM_snprintf((char *)value_str, sizeof(value_str),"%s:%d", dns_str, port); + config_service_set(idx, TYPE_STRING, value_str, GM_strlen((const char*)value_str)); +} + + +StreamType config_service_update_socket_type(void) +{ + return STREAM_TYPE_DGRAM; + //return STREAM_TYPE_STREAM; +} + diff --git a/src/fifo.c b/src/fifo.c new file mode 100644 index 0000000..c5b3f40 --- /dev/null +++ b/src/fifo.c @@ -0,0 +1,375 @@ + +#include +#include "fifo.h" +#include "utility.h" +#include "gm_stdlib.h" +#include "gm_memory.h" +#include "log_service.h" + +/************************************************************************ + Function : + Description : Init the fifo structure. + fifo : reference to fifo struct. + size : size of the fifo. + Change history: + Note: + Author: + Date: +************************************************************************/ +GM_ERRCODE fifo_init(FifoType* fifo, u32 size) +{ + if (fifo == NULL || size == 0) + { + return GM_PARAM_ERROR; + } + + /* allocate fifo space. */ + fifo->base_addr = (u8 *) GM_MemoryAlloc(size * sizeof(u8)); + if (fifo->base_addr == NULL) + { + return GM_MEM_NOT_ENOUGH; + } + + GM_memset((u8 *)fifo->base_addr, 0x00, sizeof(u8) * size); + + fifo->read_idx = 0; + fifo->write_idx = 0; + fifo->size = size; + + return GM_SUCCESS; +} + + + +/************************************************************************ + Function : + Description : Reset the fifo structure. + fifo : reference to fifo struct. + Change history: + Note: + Author: + Date: +************************************************************************/ +GM_ERRCODE fifo_reset(FifoType * fifo) +{ + if (fifo == NULL || fifo->base_addr == NULL) + { + return GM_PARAM_ERROR; + } + + /* optional (clear memory region) */ + GM_memset((u8 *)fifo->base_addr, 0x00, fifo->size); + + fifo->read_idx = 0; + fifo->write_idx = 0; + return GM_SUCCESS; +} + +/************************************************************************ + Function : + Description : delete the fifo structure. + fifo : reference to fifo struct. + Change history: + Note: + Author: + Date: +************************************************************************/ +GM_ERRCODE fifo_delete(FifoType * fifo) +{ + if (fifo == NULL) + { + return GM_PARAM_ERROR; + } + + /* delete fifo space. */ + if (fifo->base_addr == NULL) + { + return GM_SUCCESS; + } + + GM_MemoryFree(fifo->base_addr); + fifo->base_addr = 0; + fifo->read_idx = 0; + fifo->write_idx = 0; + fifo->size = 0; + return GM_SUCCESS; +} + + + +/************************************************************************ + Function : + Description : returns msg count in the fifo + fifo : reference to fifo struct. + Change history: + Note: + Author: + Date: +************************************************************************/ +u32 fifo_get_msg_length(FifoType * fifo) +{ + int read_point = 0; + int write_point = 0; + int left_data_size = 0; + + if (fifo == NULL) + { + return 0; + } + + read_point = fifo->read_idx; + write_point = fifo->write_idx; + + left_data_size = write_point - read_point; + if(left_data_size < 0) + { + left_data_size += fifo->size; + } + + return left_data_size; +} + + + + + + +/************************************************************************ + Function : + Description : Insert msg to the fifo. + fifo : reference to fifo struct. + data : reference to msg buffer. + len : msg length. + Change history: + Note: + Author: + Date: +************************************************************************/ +GM_ERRCODE fifo_insert(FifoType * fifo, u8 *data, u32 len) +{ + int read_point; + int write_point; + int left_size; + int to_end; + + if(len > MAX_FIFO_MSG_LEN) + { + return GM_PARAM_ERROR; + } + + read_point = fifo->read_idx; + write_point = fifo->write_idx; + + left_size = read_point - write_point; + if(left_size <= 0) + { + left_size += fifo->size; + } + + if((u32)left_size <= (len)) + { + return GM_MEM_NOT_ENOUGH; + } + + to_end = fifo->size - write_point; + if((u32)to_end >= len) + { + GM_memcpy(fifo->base_addr + write_point,data,len); + write_point += len; + write_point %= fifo->size; + } + else + { + GM_memcpy(fifo->base_addr + write_point,data,to_end); + GM_memcpy(fifo->base_addr,data + to_end,len -to_end); + write_point = len -to_end; + } + + fifo->write_idx = write_point; + return GM_SUCCESS; +} + + +/************************************************************************ + Function : + Description : Retrieve one msg from the fifo. + fifo : reference to fifo struct. + data : reference to msg data buffer. + len : data buffer length. + Change history: + Note: + Author: +************************************************************************/ +GM_ERRCODE fifo_peek(FifoType * fifo, u8 *data, u32 len) +{ + int read_point = 0; + int write_point = 0; + int left_data_size = 0; + int to_end = 0; + + read_point = fifo->read_idx; + write_point = fifo->write_idx; + + left_data_size = write_point - read_point; + if(left_data_size < 0) + { + left_data_size += fifo->size; + } + + if((u32)left_data_size < len) + { + return GM_EMPTY_BUF; + } + + to_end = fifo->size - read_point; + if((u32)to_end >= len) + { + GM_memcpy(data,fifo->base_addr + read_point,len); + read_point += len; + if(read_point >=fifo->size) + { + read_point = 0; + } + } + else + { + GM_memcpy(data,fifo->base_addr + read_point,to_end); + GM_memcpy(data+to_end,fifo->base_addr,len -to_end); + read_point = len - to_end; + } + + return GM_SUCCESS; +} + + +/************************************************************************ + Function : + Description : Retrieve one msg from the fifo. + fifo : reference to fifo struct. + data : reference to msg data buffer. + len : data buffer length. it is input and output varible + Change history: + Note: + Author: +************************************************************************/ +GM_ERRCODE fifo_peek_and_get_len(FifoType * fifo, u8 *data, u32 *len_p) +{ + int read_point = 0; + int write_point = 0; + int left_data_size = 0; + int to_end = 0; + + read_point = fifo->read_idx; + write_point = fifo->write_idx; + + left_data_size = write_point - read_point; + if(left_data_size < 0) + { + left_data_size += fifo->size; + } + + if((u32)left_data_size < (*len_p)) + { + (*len_p) = (u32)left_data_size; + } + + to_end = fifo->size - read_point; + if((u32)to_end >= (*len_p)) + { + GM_memcpy(data,fifo->base_addr + read_point,(*len_p)); + read_point += (*len_p); + if(read_point >=fifo->size) + { + read_point = 0; + } + } + else + { + GM_memcpy(data,fifo->base_addr + read_point,to_end); + GM_memcpy(data+to_end,fifo->base_addr,(*len_p) -to_end); + read_point = (*len_p) - to_end; + } + + return GM_SUCCESS; +} + + + +GM_ERRCODE fifo_pop_len(FifoType * fifo, u32 len) +{ + int read_point = 0; + int write_point = 0; + int left_data_size = 0; + + read_point = fifo->read_idx; + write_point = fifo->write_idx; + left_data_size = write_point - read_point; + + if(left_data_size < 0) + { + left_data_size += fifo->size; + } + + if((u32)left_data_size < len) + { + return GM_PARAM_ERROR; + } + read_point += len; + if(read_point >= fifo->size) + { + read_point -= fifo->size; + } + + fifo->read_idx = read_point; + + return GM_SUCCESS; +} + +GM_ERRCODE fifo_peek_until(FifoType* fifo, u8* data, u16* len_p, const u8 until_char) +{ + U32 read_point = fifo->read_idx; + U32 write_point = fifo->write_idx; + S32 data_size = write_point - read_point; + U32 index = 0; + bool has_until_char = false; + + if (NULL == fifo || NULL == data || NULL == len_p) + { + return GM_PARAM_ERROR; + } + + if(data_size < 0) + { + data_size += fifo->size; + } + + //取分隔符前面的所有字符 + for (index = 0; index < data_size && (fifo->base_addr[read_point] != until_char) && index < *len_p - 1; index++) + { + data[index] = fifo->base_addr[read_point]; + read_point++; + read_point %= fifo->size; + } + + //取分隔符后面的所有分隔符,包括'\r' + for (; index < data_size && index < *len_p - 1 && ((fifo->base_addr[read_point] == until_char) || (fifo->base_addr[read_point] == '\r')); index++) + { + data[index] = fifo->base_addr[read_point]; + read_point++; + read_point %= fifo->size; + has_until_char = true; + } + + *len_p = index; + data[index] = '\0'; + if (has_until_char) + { + return GM_SUCCESS; + } + else + { + return GM_EMPTY_BUF; + } +} + + diff --git a/src/g_sensor.c b/src/g_sensor.c new file mode 100644 index 0000000..0fe2152 --- /dev/null +++ b/src/g_sensor.c @@ -0,0 +1,1554 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: g_sensor.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-01 + * Description: 运动传感器数据处理,控制GPS休眠与唤醒、判断运动状态(用于控制GPS是否产生数据)、相关报警 + * Others: + * Function List: + 1. 创建g_sensor模块 + 2. 销毁g_sensor模块 + 3. g_sensor模块定时处理入口 + 4. 获取g_sensor阈值 + 5. 设置g_sensor阈值 + 6. 获取g-sensor状态 + * History: + 1. Date: 2019-03-01 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + */ + +#include +#include +#include +#include +#include +#include +#include +#include "g_sensor.h" +#include "applied_math.h" +#include "circular_queue.h" +#include "gps.h" +#include "log_service.h" +#include "config_service.h" +#include "system_state.h" +#include "led.h" +#include "gps_service.h" +#include "utility.h" +#include "main.h" +#include "hard_ware.h" +#include "uart.h" + +//写控制bit +#define I2C_WR 0 + +//读控制bit +#define I2C_RD 1 + +#define I2C_SCL 43 +#define I2C_SDA 44 + +#define HW_I2C 1 +#define SW_I2C 0 + + +#define GSEN_PIN GM_GPIO52 + +#define GSEN_EINT GM_EINT23 + +//SC7A20、BMA253适用 +#define GOOME_I2C_ADDR 0x30 + +//DA213适用 +#define DA213_I2C_ADDR 0x4E + +#define SC7A20_REG_ADDR 0x0F + +#define BMA253_REG_ADDR 0x00 +#define BMA253_X_AXIS_LSB_REG 0x02 +#define BMA253_X_AXIS_MSB_REG 0x03 +#define BMA253_Y_AXIS_LSB_REG 0x04 +#define BMA253_Y_AXIS_MSB_REG 0x05 +#define BMA253_Z_AXIS_LSB_REG 0x06 +#define BMA253_Z_AXIS_MSB_REG 0x07 +#define BMA253_STATUS1_REG 0x09 +#define BMA253_STATUS2_REG 0x0A +#define BMA253_STATUS_TAP_SLOPE_REG 0x0B +#define BMA253_STATUS_ORIENT_HIGH_REG 0x0C +#define BMA253_STATUS_FIFO_REG 0x0E //ADDED +#define BMA253_RANGE_SEL_REG 0x0F +#define BMA253_BW_SEL_REG 0x10 +#define BMA253_MODE_CTRL_REG 0x11 +#define BMA253_LOW_NOISE_CTRL_REG 0x12 +#define BMA253_DATA_CTRL_REG 0x13 +#define BMA253_RESET_REG 0x14 // only write 0xB6 will reset +#define BMA253_INT_ENABLE1_REG 0x16 //选择中断使能,0x07 为X,Y,Z向量使能 +#define BMA253_INT_ENABLE2_REG 0x17 +#define BMA253_INT_SLO_NO_MOT_REG 0x18 //ADDED +#define BMA253_INT1_PAD_SEL_REG 0x19 // 选择INT1产生中断方式,默认无,0x04 为 向量方式 +#define BMA253_INT_DATA_SEL_REG 0x1A +#define BMA253_INT2_PAD_SEL_REG 0x1B +#define BMA253_INT_SRC_REG 0x1E //中断数据源是否经过过滤,默认为0,为经过过滤 +#define BMA253_INT_SET_REG 0x20 //设置中断输出方式,默认为INT1,INT2产生中断时输出高电平 +#define BMA253_INT_CTRL_REG 0x21 +#define BMA253_LOW_DURN_REG 0x22 +#define BMA253_LOW_THRES_REG 0x23 +#define BMA253_LOW_HIGH_HYST_REG 0x24 //设置高中断滞后值,bit7-6 x * 125mg +#define BMA253_HIGH_DURN_REG 0x25 //设置高中断持续时间,bit7-0 x * 2ms +#define BMA253_HIGH_THRES_REG 0x26 //设置高中断震动阈值,bit7-0 x * 7.81mg(2g) +#define BMA253_SLOPE_DURN_REG 0x27 //向量 震动持续时间,bit7-0 x * 3.91mg(2g) +#define BMA253_SLOPE_THRES_REG 0x28 //向量 震动阈值,bit7-0 x * 3.91mg(2g) +#define BMA253_SLO_NO_MOT_THRES_REG 0x29 //ADDED +#define BMA253_TAP_PARAM_REG 0x2A +#define BMA253_TAP_THRES_REG 0x2B +#define BMA253_ORIENT_PARAM_REG 0x2C +#define BMA253_THETA_BLOCK_REG 0x2D +#define BMA253_THETA_FLAT_REG 0x2E +#define BMA253_FLAT_HOLD_TIME_REG 0x2F +#define BMA253_FIFO_WML_TRIG 0x30 //ADDED +#define BMA253_SELF_TEST_REG 0x32 +#define BMA253_EEPROM_CTRL_REG 0x33 +#define BMA253_SERIAL_CTRL_REG 0x34 +#define BMA253_OFFSET_CTRL_REG 0x36 +#define BMA253_OFFSET_PARAMS_REG 0x37 +#define BMA253_OFFSET_X_AXIS_REG 0x38 +#define BMA253_OFFSET_Y_AXIS_REG 0x39 +#define BMA253_OFFSET_Z_AXIS_REG 0x3A + +#define DA213_REG_ADDR 0x01 +#define DA213_X_AXIS_LSB_ADDR 0x02 +#define DA213_AXIS_NEW_DATA_ADDR 0x0A +#define DA213_RANGE_SELECT_ADDR 0x0F +#define DA213_BW_SELECT_ADDR 0x10 +#define DA213_POWERMODE_BW_ADDR 0x11 +#define DA213_INTR_SET_ADDR 0x20 +#define DA213_INTR_CTRL_ADDR 0x21 +#define DA213_INTR_ENABLE1_ADDR 0x16 +#define DA213_INTMAP1_ADDR 0x19 +#define DA213_SLOPE_DURN_ADDR 0x27 +#define DA213_SLOPE_THRES_ADDR 0x28 +#define DA213_ANY_ACTIVE_ADDR 0x0B +#define DA213_MOTION_FLAG_ADDR 0x09 +#define DA213_RESET_REG 0x00 + + +typedef struct +{ + S16 x; + S16 y; + S16 z; +} Aclr, *pAclr; + +typedef struct +{ + U8 shake_level; + U32 shake_threshold; + float static_thr; // 静止阈值 + float run_thr; // 运动阈值 + float brake_thr; // 急刹车阈值 + float rapid_aclr_thr;// 急加速阈值 + float sudden_turn_thr; // 急转弯阈值 + float slight_crash_thr; // 轻微碰撞阈值 + float normal_crash_thr; // 一般碰撞阈值 + float serious_crash_thr; // 严重碰撞阈值 +}GSensorThreshold; + + + + + + +typedef struct +{ + GSensorType type; + + //启动时间(毫秒) + U64 start_time; + + //无振动时间毫秒 + U32 no_shake_time_ms; + + //唤醒时间(毫秒) + U32 awake_time; + + //休眠时间(毫秒) + U32 sleep_time; + + U32 rw_error_count; + U32 read_data_count; + + //震动事件队列(存储的是震动时间) + CircularQueue shake_event_time_queue_when_read; + CircularQueue shake_event_time_queue_when_eint; + U32 last_report_shake_alarm_time; + U32 last_report_turnover_alarm_time; + U32 last_report_remove_alarm_time; + + //存20秒传感器数据 + CircularQueue aclr_x_queue; + CircularQueue aclr_y_queue; + CircularQueue aclr_z_queue; + + CircularQueue sensor_angle_queue; + + Vector3D gravity; + unsigned int cal_gravity_avg_len; + Vector3D static_gravity; + Vector2D vehicle_head_vector; + + //传感器加速度的滑动平均值,含重力加速度在内 + Vector3D senor_aclr_moving_avg; + U32 cal_senor_aclr_avg_len; + U32 cal_senor_aclr_avg_len_short_period; + U64 study_aclr_count; + U64 static_low_aclr_count; + U64 super_low_aclr_count; + + COLLISION_LEVEL collision_level; + U32 collision_aclr_count; + GPSData last_collision_gps_info; + Aclr last_collision_aclr; + + GSensorThreshold threshold; +}GSensor; + +static GSensor s_gsensor; + +static void reset_sensor_data(void); +static GM_ERRCODE get_config(void); +static void init_gsensor_chip(void); +static void check_awake_sleep(void); +static bool is_known_type(const GSensorType type); +static void g_sensor_eint_callback(void* v_arg); +static void read_data_from_chip(void); +static void check_shake_event(Aclr current_aclr); +static void check_shake_alarm(void); +static void report_shake_alarm(void); +static void check_acc_and_report_shake_alarm(void); +static U8 get_data_addr(const GSensorType type); +static void write_config_to_chip(const GSensorType type); +static void check_vehicle_state(Aclr a); +static void check_collision(Vector3D sensor_aclr); +static bool check_emergency_brake(float vehicle_horizontal_aclr_magnitude); +static void report_emergency_brake_alarm(void); +static bool check_rapid_acceleration(float vehicle_horizontal_aclr_magnitude); +static void report_rapid_aclr_alarm(void); +static bool check_sudden_turn_acceleration(float vehicle_horizontal_aclr_magnitude); +static void report_sudden_turn_alarm(void); +static void study_gravity(Aclr a); +static GM_ERRCODE get_vehicle_acceleration(Vector3D g, Vector3D sensor_aclr, Vector3D *vehicle_horizontal_aclr, Vector3D *vehicle_vertical_aclr); +static void calculate_moving_avg(Vector3D sensor_aclr, int num, PVector3D p_aclr_moving_avg, unsigned int *p_len); +static void check_static_or_run(float vehicle_horizontal_aclr_magnitude); +static void calc_sensor_angle(void); +static void check_angle_alarm(void); + + +/** + * Function: 创建g_sensor模块 + * Description:创建g_sensor模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE g_sensor_create(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + s_gsensor.type = GSENSOR_TYPE_UNKNOWN; + s_gsensor.start_time = 0; + s_gsensor.no_shake_time_ms = 0; + s_gsensor.awake_time = 0; + s_gsensor.sleep_time = 0; + s_gsensor.rw_error_count = 0; + s_gsensor.read_data_count = 0; + s_gsensor.last_report_shake_alarm_time = 0; + s_gsensor.last_report_turnover_alarm_time = 0; + s_gsensor.last_report_remove_alarm_time = 0; + + + reset_sensor_data(); + + ret = get_config(); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to get_config()!"); + return ret; + } + + ret = circular_queue_create(&s_gsensor.shake_event_time_queue_when_read,G_SHAKE_BUF_LEN,GM_QUEUE_TYPE_INT); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to circular_queue_create()!"); + return ret; + } + + ret = circular_queue_create(&s_gsensor.shake_event_time_queue_when_eint,G_SHAKE_BUF_LEN,GM_QUEUE_TYPE_INT); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to circular_queue_create()!"); + return ret; + } + + ret = circular_queue_create(&s_gsensor.aclr_x_queue,G_SENSOR_BUF_LEN,GM_QUEUE_TYPE_INT); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to circular_queue_create()!"); + return ret; + } + + ret = circular_queue_create(&s_gsensor.aclr_y_queue,G_SENSOR_BUF_LEN,GM_QUEUE_TYPE_INT); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to circular_queue_create()!"); + return ret; + } + + ret = circular_queue_create(&s_gsensor.aclr_z_queue,G_SENSOR_BUF_LEN,GM_QUEUE_TYPE_INT); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to circular_queue_create()!"); + return ret; + } + + ret = circular_queue_create(&s_gsensor.sensor_angle_queue, ANGLE_RECORD_NUM,GM_QUEUE_TYPE_INT); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to circular_queue_create()!"); + return ret; + } + return ret; +} + +static void reset_sensor_data(void) +{ + s_gsensor.gravity.x = 0; + s_gsensor.gravity.y = 0; + s_gsensor.gravity.z = 0; + s_gsensor.cal_gravity_avg_len = 0; + s_gsensor.cal_senor_aclr_avg_len = 0; + s_gsensor.cal_senor_aclr_avg_len_short_period = 0; + s_gsensor.static_gravity.x = 0; + s_gsensor.static_gravity.y = 0; + s_gsensor.static_gravity.z = 0; + s_gsensor.vehicle_head_vector.x = 0; + s_gsensor.vehicle_head_vector.y = 0; + s_gsensor.study_aclr_count = 0; + s_gsensor.static_low_aclr_count = 0; + s_gsensor.super_low_aclr_count = 0; +} + +static GM_ERRCODE get_config(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + ret = config_service_get(CFG_SHAKE_LEVEL, TYPE_BYTE, &s_gsensor.threshold.shake_level, sizeof(s_gsensor.threshold.shake_level)); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to config_service_get(CFG_SHAKE_LEVEL),ret=%d", ret); + } + + ret = config_service_get(CFG_SHAKE_THRESHOLD, TYPE_INT, &s_gsensor.threshold.shake_threshold, sizeof(s_gsensor.threshold.shake_threshold)); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to config_service_get(CFG_SHAKE_THRESHOLD),ret=%d", ret); + } + + ret = config_service_get(CFG_SEN_STATIC, TYPE_FLOAT, &s_gsensor.threshold.static_thr, sizeof(s_gsensor.threshold.static_thr)); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to config_service_get(CFG_SEN_STATIC),ret=%d", ret); + } + + ret = config_service_get(CFG_SEN_RUN, TYPE_FLOAT, &s_gsensor.threshold.run_thr, sizeof(s_gsensor.threshold.run_thr)); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to config_service_get(CFG_SEN_RUN),ret=%d", ret); + } + + ret = config_service_get(CFG_SEN_EMERGENCY_BRAKE, TYPE_FLOAT, &s_gsensor.threshold.brake_thr, sizeof(s_gsensor.threshold.brake_thr)); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to config_service_get(CFG_SEN_EMERGENCY_BRAKE),ret=%d", ret); + } + + ret = config_service_get(CFG_SEN_RAPID_ACLR, TYPE_FLOAT, &s_gsensor.threshold.rapid_aclr_thr, sizeof(s_gsensor.threshold.rapid_aclr_thr)); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to config_service_get(CFG_SEN_RAPID_ACLR),ret=%d", ret); + } + + ret = config_service_get(CFG_SEN_SUDDEN_TURN, TYPE_FLOAT, &s_gsensor.threshold.sudden_turn_thr, sizeof(s_gsensor.threshold.sudden_turn_thr)); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to config_service_get(CFG_SEN_SUDDEN_TURN),ret=%d", ret); + } + + ret = config_service_get(CFG_SEN_SLIGHT_COLLISION, TYPE_FLOAT, &s_gsensor.threshold.slight_crash_thr, sizeof(s_gsensor.threshold.slight_crash_thr)); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to config_service_get(CFG_SEN_SLIGHT_COLLISION),ret=%d", ret); + } + + ret = config_service_get(CFG_SEN_NORMAL_COLLISION, TYPE_FLOAT, &s_gsensor.threshold.normal_crash_thr, sizeof(s_gsensor.threshold.normal_crash_thr)); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to config_service_get(CFG_SEN_NORMAL_COLLISION),ret=%d", ret); + } + + ret = config_service_get(CFG_SEN_SERIOUS_COLLISION, TYPE_FLOAT, &s_gsensor.threshold.serious_crash_thr, sizeof(s_gsensor.threshold.serious_crash_thr)); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to config_service_get(CFG_SEN_SERIOUS_COLLISION),ret=%d", ret); + } + + + return GM_SUCCESS; +} + +/** + * Function: 销毁g_sensor模块 + * Description:销毁g_sensor模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE g_sensor_destroy(void) +{ + circular_queue_destroy(&s_gsensor.shake_event_time_queue_when_read,GM_QUEUE_TYPE_INT); + + circular_queue_destroy(&s_gsensor.shake_event_time_queue_when_eint,GM_QUEUE_TYPE_INT); + + circular_queue_destroy(&s_gsensor.aclr_x_queue,GM_QUEUE_TYPE_INT); + + circular_queue_destroy(&s_gsensor.aclr_y_queue,GM_QUEUE_TYPE_INT); + + circular_queue_destroy(&s_gsensor.aclr_z_queue,GM_QUEUE_TYPE_INT); + + circular_queue_destroy(&s_gsensor.sensor_angle_queue,GM_QUEUE_TYPE_INT); + + return GM_SUCCESS; +} + +void g_sensor_reset_noshake_time(void) +{ + s_gsensor.no_shake_time_ms = 0; +} + +void g_sensor_timer_proc(void) +{ + if (!is_known_type(s_gsensor.type)) + { + init_gsensor_chip(); + return; + } + if (GM_SYSTEM_STATE_WORK == system_state_get_work_state()) + { + s_gsensor.start_time += TIM_GEN_10MS; + } + else + { + s_gsensor.start_time += TIM_GEN_1SECOND; + } + + get_config(); + read_data_from_chip(); +} + +U8 g_sensor_get_angle(void) +{ + S32 last_angle = 0; + if(false == circular_queue_get_tail_i(&(s_gsensor.sensor_angle_queue),&last_angle)) + { + return 0; + } + return (U8)last_angle; +} + +#define SC7A20_STR "SC7A20" +#define BMA253_STR "BMA253" +#define DA213_STR "DA213" +#define UNKNOWN_STR "unknown" + +GM_ERRCODE g_sensor_get_typestr(GSensorType type,char* p_type_str,const U8 max_len) +{ + if (GSENSOR_TYPE_SC7A20 == type) + { + GM_strncpy(p_type_str, SC7A20_STR, GM_strlen(SC7A20_STR)); + return GM_SUCCESS; + } + else if (GSENSOR_TYPE_BMA253 == type) + { + GM_strncpy(p_type_str, BMA253_STR, GM_strlen(BMA253_STR)); + return GM_SUCCESS; + } + else if (GSENSOR_TYPE_DA213 == type) + { + GM_strncpy(p_type_str, DA213_STR, GM_strlen(DA213_STR)); + return GM_SUCCESS; + } + else + { + GM_strncpy(p_type_str, UNKNOWN_STR, GM_strlen(UNKNOWN_STR)); + return GM_HARD_WARE_ERROR; + } +} + +U32 g_sensor_get_error_count(void) +{ + return s_gsensor.rw_error_count; +} + +U8 g_sensor_get_shake_event_count_when_read(void) +{ + return circular_queue_get_len(&s_gsensor.shake_event_time_queue_when_read); +} + +U8 g_sensor_get_shake_event_count_when_eint(void) +{ + return circular_queue_get_len(&s_gsensor.shake_event_time_queue_when_eint); +} +static void check_awake_sleep(void) +{ + U32 now = util_clock(); + U8 index = 0; + U32 shake_time = 0; + U8 shake_count_when_read_data = 0; + U8 shake_count_when_eint = 0; + U16 sleep_time_minute_threshold = 0; + U8 shake_time_threshold = 0; + U8 shake_count_threshold = 0; + + config_service_get(CFG_SLEEP_TIME, TYPE_SHORT, &sleep_time_minute_threshold, sizeof(sleep_time_minute_threshold)); + config_service_get(CFG_AWAKE_CHECK_TIME, TYPE_BYTE, &shake_time_threshold, sizeof(shake_time_threshold)); + config_service_get(CFG_AWAKE_COUNT, TYPE_BYTE, &shake_count_threshold, sizeof(shake_count_threshold)); + if (shake_count_threshold > G_SHAKE_BUF_LEN) + { + shake_count_threshold = G_SHAKE_BUF_LEN; + } + + for (index = 0; index < shake_count_threshold; ++index) + { + if(!circular_queue_get_by_index_i(&s_gsensor.shake_event_time_queue_when_read, index, (S32*)&shake_time)) + { + break; + } + + if ((now - shake_time) <= shake_time_threshold) + { + shake_count_when_read_data++; + } + } + + for (index = 0; index < shake_count_threshold; ++index) + { + if(!circular_queue_get_by_index_i(&s_gsensor.shake_event_time_queue_when_eint, index, (S32*)&shake_time)) + { + break; + } + + if ((now - shake_time) <= shake_time_threshold) + { + shake_count_when_eint++; + } + } + + if (shake_count_when_read_data >= shake_count_threshold || shake_count_when_eint >= shake_count_threshold) + { + s_gsensor.no_shake_time_ms = 0; + if(GM_SYSTEM_STATE_SLEEP == system_state_get_work_state()) + { + if(GM_SUCCESS == gps_power_on(true)) + { + system_state_set_work_state(GM_SYSTEM_STATE_WORK); + led_set_gsm_state(GM_LED_FLASH); + + GM_StartTimer(GM_TIMER_10MS_MAIN, TIM_GEN_10MS, timer_10ms_proc); + GM_StartTimer(GM_TIMER_1S_MAIN, TIM_GEN_1SECOND, timer_1s_proc); + LOG(INFO,"awake,shake_count_when_read_data=%d",shake_count_when_read_data); + } + } + } + else + { + if (GM_SYSTEM_STATE_SLEEP == system_state_get_work_state()) + { + s_gsensor.no_shake_time_ms += TIM_GEN_1SECOND; + } + else + { + s_gsensor.no_shake_time_ms += TIM_GEN_10MS; + } + + } + + //sleep_time_minute_threshold为0不休眠 + if (s_gsensor.no_shake_time_ms >= sleep_time_minute_threshold * SECONDS_PER_MIN * MSEC_PER_SECONDS && 0 != sleep_time_minute_threshold) + { + if(GM_SYSTEM_STATE_WORK == system_state_get_work_state()) + { + if(GM_SUCCESS == gps_power_off()) + { + system_state_set_work_state(GM_SYSTEM_STATE_SLEEP); + led_set_gsm_state(GM_LED_OFF); + + } + s_gsensor.sleep_time = s_gsensor.no_shake_time_ms; + } + } + + if (GM_SYSTEM_STATE_SLEEP == system_state_get_work_state()) + { + s_gsensor.sleep_time += TIM_GEN_1SECOND; + s_gsensor.awake_time = 0; + } + else + { + s_gsensor.awake_time += TIM_GEN_10MS; + s_gsensor.sleep_time = 0; + } +} + +// 震动报警和恢复,两次报警之间间隔30分钟 +// 1、有震动:10秒内5次以上传感器中断(用震动时间队列解决) +// 2、自动设防(GS03,ACC OFF 5分钟后设防): 有震动就延迟5秒后检查ACC状态再报 +// 3、手动设防(GS05):有震动并且已设防就立即报警 +// 修改了上一个版本的默认参数 +static void check_shake_alarm(void) +{ + + U8 index = 0; + U32 shake_time = 0; + U8 shake_count_when_read = 0; + U8 shake_check_interval = 10; + U8 shake_count_threshold = 5; + bool is_defence_by_hand = false; + U16 shake_alarm_delay = 30; + U32 now = util_clock(); + + config_service_get(CFG_SHAKE_CHECK_TIME, TYPE_BYTE, &shake_check_interval, sizeof(shake_check_interval)); + config_service_get(CFG_SHAKE_COUNT, TYPE_BYTE, &shake_count_threshold, sizeof(shake_count_threshold)); + config_service_get(CFG_IS_MANUAL_DEFENCE,TYPE_BOOL, &is_defence_by_hand, sizeof(is_defence_by_hand)); + config_service_get(CFG_SHAKE_ALARM_DELAY, TYPE_SHORT, &shake_alarm_delay, sizeof(shake_alarm_delay)); + if (shake_count_threshold > G_SHAKE_BUF_LEN) + { + shake_count_threshold = G_SHAKE_BUF_LEN; + } + + config_service_get(CFG_IS_MANUAL_DEFENCE,TYPE_BOOL, &is_defence_by_hand, sizeof(is_defence_by_hand)); + + + for (index = 0; index < shake_count_threshold; ++index) + { + circular_queue_get_by_index_i(&s_gsensor.shake_event_time_queue_when_read, index, (S32*)&shake_time); + + if ((now - shake_time) <= shake_check_interval) + { + shake_count_when_read++; + } + } + + //没有震动 + if (shake_count_when_read < shake_count_threshold) + { + return; + } + //没设防 + if (!system_state_get_defence()) + { + return; + } + + //手动设防,立即上报 + if (is_defence_by_hand) + { + report_shake_alarm(); + } + else + { + //自动设防模式,延迟30秒后检查ACC状态后再报,如果ACC状态为OFF就不报了 + GM_StartTimer(GM_TIMER_GSENSOR_CHECK_ACC_AFTER_SHAKE, shake_alarm_delay*TIM_GEN_1SECOND, check_acc_and_report_shake_alarm); + LOG(INFO,"After %d seconds check_acc_and_report_shake_alarm",shake_alarm_delay); + } + + +} + +static void report_shake_alarm(void) +{ + U32 now = util_clock(); + U16 shake_alarm_interval = 30 * SECONDS_PER_MIN; + AlarmInfo alarm_info; + + config_service_get(CFG_SHAKE_ALARM_INTERVAL,TYPE_SHORT, &shake_alarm_interval, sizeof(shake_alarm_interval)); + + //刚刚启动不报震动报警 + if(now <= 10) + { + return; + } + + if ((now - s_gsensor.last_report_shake_alarm_time >= shake_alarm_interval) || 0 == s_gsensor.last_report_shake_alarm_time) + { + alarm_info.type = ALARM_SHOCK; + gps_service_push_alarm(&alarm_info); + system_state_set_shake_alarm(true); + s_gsensor.last_report_shake_alarm_time = now; + LOG(INFO,"report_shake_alarm now(clock:%d)",now); + } + else + { + LOG(DEBUG,"do not report_shake_alarm,last_report_shake_alarm_time=%d",s_gsensor.last_report_shake_alarm_time); + } +} + +static void check_acc_and_report_shake_alarm(void) +{ + bool acc_is_on = false; + if (hard_ware_get_acc_line_level(&acc_is_on)) + { + return; + } + if(acc_is_on) + { + return; + } + report_shake_alarm(); +} + +static bool is_known_type(const GSensorType type) +{ + if (GSENSOR_TYPE_SC7A20 == type || GSENSOR_TYPE_BMA253 == type || GSENSOR_TYPE_DA213 == type) + { + return true; + } + else + { + return false; + } +} + +static void g_sensor_eint_callback(void* v_arg) +{ + U32 now = util_clock(); + bool shake_alarm_enable = false; + + U32 last_shake_time = 0; + circular_queue_get_tail_i(&s_gsensor.shake_event_time_queue_when_eint, (S32*)&last_shake_time); + //不是同一秒的才入对列 + if (now > last_shake_time) + { + circular_queue_en_queue_i(&s_gsensor.shake_event_time_queue_when_eint, now); + LOG(INFO, "Shake once in EINT(now=%d)",now); + } + + if(config_service_get(CFG_IS_SHAKE_ALARM_ENABLE, TYPE_BOOL, &shake_alarm_enable, sizeof(shake_alarm_enable))) + { + return; + } + + if (shake_alarm_enable) + { + check_shake_alarm(); + } +} +static void init_gsensor_chip(void) +{ + // GSEN_PIN 中断脚 拉高(KAL_TRUE)就触发g_sensor_eint_callback + // EDGE_SENSITIVE true:边缘触发 fase:电平触发 + GM_EintPinInit(GSEN_PIN); + GM_GpioSetPullSelection(GSEN_PIN, PINPULLSEL_PULLUP); + GM_EintSetPolarity(GSEN_EINT, KAL_TRUE); + GM_EintRegister(GSEN_EINT, g_sensor_eint_callback, KAL_TRUE, EDGE_SENSITIVE); + + GM_I2cInit(HW_I2C, GOOME_I2C_ADDR|I2C_RD, GOOME_I2C_ADDR|I2C_WR, I2C_SCL, I2C_SDA); + GM_I2cConfig(GOOME_I2C_ADDR, G_SENSOR_SAMPLE_FREQ); + GM_I2cSetMode(HW_I2C); + + GM_I2cReadBytes(SC7A20_REG_ADDR, &s_gsensor.type, 1); + if (GSENSOR_TYPE_SC7A20 == s_gsensor.type) + { + LOG(INFO, "gsensor type SC7A20"); + system_state_set_gsensor_type(s_gsensor.type); + write_config_to_chip(GSENSOR_TYPE_SC7A20); + return; + } + + //BMA253 + GM_I2cReadBytes(BMA253_REG_ADDR, &s_gsensor.type, 1); + if (GSENSOR_TYPE_BMA253 == s_gsensor.type) + { + LOG(INFO, "gsensor type BMA253"); + system_state_set_gsensor_type(s_gsensor.type); + write_config_to_chip(GSENSOR_TYPE_BMA253); + return; + } + + //DA213与其他2种芯片初始化不同 + GM_I2cInit(HW_I2C, DA213_I2C_ADDR|I2C_RD, DA213_I2C_ADDR|I2C_WR, I2C_SCL, I2C_SDA); + GM_I2cConfig(GOOME_I2C_ADDR, G_SENSOR_SAMPLE_FREQ); + + GM_I2cReadBytes(DA213_REG_ADDR, &s_gsensor.type, 1); + if (GSENSOR_TYPE_DA213 == s_gsensor.type) + { + LOG(INFO, "gsensor type DA213"); + system_state_set_gsensor_type(s_gsensor.type); + write_config_to_chip(GSENSOR_TYPE_DA213); + return; + } + + //走到这里的时候一定是出错了 + LOG(INFO, "gsensor init error!"); + s_gsensor.rw_error_count++; + +} + +static void read_data_from_chip(void) +{ + Aclr aclr = {0}; + if(!GM_I2cReadBytes(get_data_addr(s_gsensor.type), (U8*)&aclr, sizeof(aclr))) + { + LOG(WARN, "Failed to read data from gsensor!"); + s_gsensor.rw_error_count++; + return; + } + s_gsensor.rw_error_count = 0; + aclr.x = aclr.x >> 4; + aclr.y = aclr.y >> 4; + aclr.z = aclr.z >> 4; + + s_gsensor.read_data_count++; + check_shake_event(aclr); + check_awake_sleep(); + + if(GM_SYSTEM_STATE_WORK == system_state_get_work_state()) + { + check_vehicle_state(aclr); + } + +} + +static void check_shake_event(Aclr current_aclr) +{ + static Aclr last_aclr = {0,0,0}; + U32 now = util_clock(); + + float x_diff = abs(last_aclr.x - current_aclr.x) * G_SENSOR_RANGE / G_SENSOR_MAX_VALUE * 1000; + float y_diff = abs(last_aclr.y - current_aclr.y) * G_SENSOR_RANGE / G_SENSOR_MAX_VALUE * 1000; + float z_diff = abs(last_aclr.z - current_aclr.z) * G_SENSOR_RANGE / G_SENSOR_MAX_VALUE * 1000; + if (x_diff >= s_gsensor.threshold.shake_threshold || y_diff >= s_gsensor.threshold.shake_threshold || z_diff >= s_gsensor.threshold.shake_threshold) + { + U32 last_shake_time = 0; + circular_queue_get_tail_i(&s_gsensor.shake_event_time_queue_when_read, (S32*)&last_shake_time); + //不是同一秒的才入对列 + if (now > last_shake_time) + { + circular_queue_en_queue_i(&s_gsensor.shake_event_time_queue_when_read, now); + LOG(INFO, "Shake once(%f,%f,%f,now=%d)",x_diff,y_diff,z_diff,now); + } + } + last_aclr.x = current_aclr.x; + last_aclr.y = current_aclr.y; + last_aclr.z = current_aclr.z; +} + + +static U8 get_data_addr(const GSensorType type) +{ + U8 reg_addr = 0; + switch(type) + { + case GSENSOR_TYPE_SC7A20: + { + reg_addr = 0xA8; + } + break; + + case GSENSOR_TYPE_BMA253: + { + reg_addr = BMA253_X_AXIS_LSB_REG; + } + break; + + case GSENSOR_TYPE_DA213: + { + reg_addr = DA213_AXIS_NEW_DATA_ADDR; + } + break; + + default: + reg_addr = 0; + break; + } + return reg_addr; +} + +static void write_config_to_chip(const GSensorType type) +{ + switch(type) + { + case GSENSOR_TYPE_SC7A20: + { + // 100HZ,0x67=103 + GM_I2cWriteByte(0x20, 0x67); + + // 高精度模式 //2G + GM_I2cWriteByte(0x23, 0x88); + + // 高精度模式 + GM_I2cWriteByte(0x21, 0x31); + GM_I2cWriteByte(0x22, 0x40); + GM_I2cWriteByte(0x25, 0x00); + GM_I2cWriteByte(0x24, 0x00); + GM_I2cWriteByte(0x30, 0x2A); + if (s_gsensor.threshold.shake_level >= 2) + { + GM_I2cWriteByte(0x32, s_gsensor.threshold.shake_level - 1); + } + else + { + GM_I2cWriteByte(0x32, 1); + } + + GM_I2cWriteByte(0x33, 0x00); //持续时间 + } + break; + + case GSENSOR_TYPE_BMA253: + { + //0x0B 62.5 hz + //0x0C 125hz + GM_I2cWriteByte(BMA253_BW_SEL_REG, 0x0C); + + //+- 2g + GM_I2cWriteByte(BMA253_RANGE_SEL_REG, 0x03); + + GM_I2cWriteByte(BMA253_INT_CTRL_REG, 0x88); + GM_I2cWriteByte(BMA253_INT_ENABLE1_REG, 0x07); + GM_I2cWriteByte(BMA253_INT1_PAD_SEL_REG, 0x04); + GM_I2cWriteByte(BMA253_INT_SRC_REG, 0x00); + GM_I2cWriteByte(BMA253_INT_CTRL_REG, 0x80); + GM_I2cWriteByte(BMA253_SLOPE_DURN_REG, 0x00); + GM_I2cWriteByte(BMA253_SLOPE_THRES_REG, s_gsensor.threshold.shake_level); + } + break; + + case GSENSOR_TYPE_DA213: + { + GM_I2cWriteByte(DA213_POWERMODE_BW_ADDR, 0x90); + GM_I2cWriteByte(DA213_MOTION_FLAG_ADDR, 0x04); //使能中断 + GM_I2cWriteByte(DA213_ANY_ACTIVE_ADDR, 0x07); //使能XYZ中断 + GM_I2cWriteByte(DA213_RANGE_SELECT_ADDR, 0x03); // 高精度模式 //14bit 2G + GM_I2cWriteByte(DA213_BW_SELECT_ADDR, 0x07); //125hz + GM_I2cWriteByte(DA213_INTR_ENABLE1_ADDR, 0x07); + GM_I2cWriteByte(DA213_INTMAP1_ADDR, 0x04); + GM_I2cWriteByte(DA213_INTR_SET_ADDR, 0x01); + GM_I2cWriteByte(DA213_INTR_CTRL_ADDR, 0x00); + GM_I2cWriteByte(DA213_SLOPE_DURN_ADDR, 0x00); //持续时间 + GM_I2cWriteByte(DA213_SLOPE_THRES_ADDR, s_gsensor.threshold.shake_level - 1); + GM_I2cWriteByte(DA213_POWERMODE_BW_ADDR, 0x10); + } + + break; + + default: + break; + } +} + +//每10ms调用一次 +void check_vehicle_state(Aclr a) +{ + //实时加速度(含重力) + Vector3D sensor_aclr = {0, 0, 0}; + //水平方向加速度(不含重力) + Vector3D vehicle_horizontal_aclr = {0, 0, 0}; + //垂直方向加速度(不含重力) + Vector3D vehicle_vertical_aclr = {0, 0, 0}; + float vehicle_horizontal_aclr_magnitude = 0; + float vehicle_vertical_aclr_magnitude = 0; + bool aclr_alarm_enable = false; + + + circular_queue_en_queue_i(&(s_gsensor.aclr_x_queue), a.x); + circular_queue_en_queue_i(&(s_gsensor.aclr_y_queue), a.y); + circular_queue_en_queue_i(&(s_gsensor.aclr_z_queue), a.z); + + sensor_aclr.x = a.x; + sensor_aclr.y = a.y; + sensor_aclr.z = a.z; + + config_service_get(CFG_IS_ACLRALARM_ENABLE, TYPE_BOOL, &aclr_alarm_enable, sizeof(aclr_alarm_enable)); + + if (aclr_alarm_enable) + { + check_collision(sensor_aclr); + } + calculate_moving_avg(sensor_aclr, G_SENSOR_SAMPLE_FREQ, &(s_gsensor.senor_aclr_moving_avg), &(s_gsensor.cal_senor_aclr_avg_len)); + + //还没学好 + if (s_gsensor.study_aclr_count < MIN_STUDY_GRAVITY_TIMES) + { + //保持不变 + //system_state_set_vehicle_state(VEHICLE_STATE_RUN); + } + //学习完毕 + else + { + get_vehicle_acceleration(s_gsensor.gravity, s_gsensor.senor_aclr_moving_avg, &vehicle_horizontal_aclr, &vehicle_vertical_aclr); + + //检测是否由静止转为运动 + vehicle_horizontal_aclr_magnitude = applied_math_get_magnitude_3d(vehicle_horizontal_aclr) * G_SENSOR_RANGE / G_SENSOR_MAX_VALUE; + check_static_or_run(vehicle_horizontal_aclr_magnitude); + + if (aclr_alarm_enable) + { + check_rapid_acceleration(vehicle_horizontal_aclr_magnitude); + + check_emergency_brake(vehicle_horizontal_aclr_magnitude); + + check_sudden_turn_acceleration(vehicle_vertical_aclr_magnitude); + } + } + + study_gravity(a); + + if (s_gsensor.start_time % TIM_GEN_1SECOND == 0) + { + calc_sensor_angle(); + if (aclr_alarm_enable) + { + check_angle_alarm(); + } + } +} + +static void calc_sensor_angle(void) +{ + U8 sensor_angle = 0; + Vector3D z_axis = {0, 0, -1}; + sensor_angle = applied_math_get_angle_3d(s_gsensor.senor_aclr_moving_avg, z_axis); + circular_queue_en_queue_i(&s_gsensor.sensor_angle_queue, sensor_angle); +} + +/** + * Function: 检查角度变化引起的报警(翻车报警、拆动报警) + * Description:1、默认关闭,由固件管理平台配置 + * 2、启动2分钟内不报警(包括重启) + * 3、保存最近1分钟角度记录(每秒1条,共60条) + * 4、当前角度与历史记录差大于TURN_OVER_ANGLE并且当前状态为静止,判定为翻车报警 + * 5、当前角度与历史记录差大于REMOVE_ANGLE并且当前状态为运动,判定为拆动报警 + * 6、以上两种报警在1分钟记录内只报一条(通过限定上报间隔大于ANGLE_RECORD_NUM实现),防止一次大的动作上报多次报警 + * Input: 无 + * Output: 无 + * Return: 无 + * 测试方法: 1、拆动:启动2分钟后,将定位器变换超过30°(由于误差存在,操作时角度要大于判断角度20°以上),要触发拆动报警 + * 2、翻车:启动2分钟后,将定位器变换超过45°(由于误差存在,操作时角度要大于判断角度20°以上),然后保持完全静止1分钟以上,要触发翻车报警 + * 3、不误报: + * 1)无论什么安装角度,启动后不动不能报警 + * 2)水平晃动和垂直震动不能报警(车辆行驶) + * 3)激烈驾驶(急加速、急减速)不能报警 + */ + +static void check_angle_alarm(void) +{ + U8 index = 0; + S32 new_angle = 0; + S32 last_angle = 0; + U8 angle_diff = 0; + U8 max_diff = 0; + AlarmInfo alarm_info; + U32 now = util_clock(); + + //启动4分钟内角度不准确不检查角度报警 + if (now < 2*ANGLE_RECORD_NUM) + { + return; + } + + if(false == circular_queue_get_tail_i(&(s_gsensor.sensor_angle_queue),&new_angle)) + { + return; + } + + LOG(DEBUG,"now(%d) angle:%d",util_clock(),new_angle); + + for(index = 1;index < ANGLE_RECORD_NUM;index++) + { + //如果找不到历史记录退出循环 + if(false == circular_queue_get_by_index_i(&(s_gsensor.sensor_angle_queue),index,&last_angle)) + { + break; + } + angle_diff = applied_math_get_angle_diff(new_angle,last_angle); + if(angle_diff > max_diff) + { + max_diff = angle_diff; + } + } + + if (max_diff > TURN_OVER_ANGLE && VEHICLE_STATE_STATIC == system_state_get_vehicle_state() + && (now - s_gsensor.last_report_turnover_alarm_time) > ANGLE_RECORD_NUM) + { + LOG(FATAL,"TURN_OVER_ANGLE:%d",max_diff); + alarm_info.type = ALARM_TURN_OVER; + alarm_info.info = max_diff; + gps_service_push_alarm(&alarm_info); + system_state_set_turn_over_alarm(true); + s_gsensor.last_report_turnover_alarm_time = now; + } + else if(max_diff > REMOVE_ANGLE && VEHICLE_STATE_RUN == system_state_get_vehicle_state() + && (now - s_gsensor.last_report_remove_alarm_time) > ANGLE_RECORD_NUM) + { + LOG(FATAL,"ALARM_REMOVE:%d",max_diff); + alarm_info.type = ALARM_REMOVE; + alarm_info.info = max_diff; + gps_service_push_alarm(&alarm_info); + system_state_set_remove_alarm(true); + s_gsensor.last_report_remove_alarm_time = now; + } + else + { + } + +} +static void check_collision(Vector3D sensor_aclr) +{ + GM_ERRCODE ret = GM_SUCCESS; + AlarmInfo alarm_info; + float sensor_alcr_mag = applied_math_get_magnitude_3d(sensor_aclr) * G_SENSOR_RANGE / G_SENSOR_MAX_VALUE; + COLLISION_LEVEL level = NO_COLLISION; + if (sensor_alcr_mag >= s_gsensor.threshold.serious_crash_thr) + { + s_gsensor.collision_aclr_count++; + level = SERIOUS_COLLISION; + } + else if(sensor_alcr_mag >= s_gsensor.threshold.normal_crash_thr) + { + s_gsensor.collision_aclr_count++; + level = NORMAL_COLLISION; + } + else if(sensor_alcr_mag >= s_gsensor.threshold.slight_crash_thr) + { + s_gsensor.collision_aclr_count++; + level = SLIGHT_COLLISION; + } + else + { + s_gsensor.collision_aclr_count = 0; + level = NO_COLLISION; + } + + //记录最严重的一次碰撞 + if(level >= s_gsensor.collision_level) + { + s_gsensor.collision_level = level; + gps_get_last_data(&(s_gsensor.last_collision_gps_info)); + s_gsensor.last_collision_aclr.x = sensor_aclr.x; + s_gsensor.last_collision_aclr.y = sensor_aclr.y; + s_gsensor.last_collision_aclr.z = sensor_aclr.z; + } + + //3次(30ms)以上的高加速度才算碰撞,防止传感器突发错误数据误报 + if(s_gsensor.collision_aclr_count >= 3) + { + alarm_info.type = ALARM_COLLISION; + alarm_info.info = s_gsensor.collision_level; + s_gsensor.collision_level = NO_COLLISION; + s_gsensor.collision_aclr_count = 0; + ret = gps_service_push_alarm(&alarm_info); + system_state_set_collision_alarm(true); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to gps_service_push_alarm(ALARM_COLLISION),ret=%d", ret); + } + } +} + +static bool check_emergency_brake(float vehicle_horizontal_aclr_magnitude) +{ + if (vehicle_horizontal_aclr_magnitude >= s_gsensor.threshold.brake_thr) + { + GM_StartTimer(GM_TIMER_GSENSOR_CHECK_SPEED_AFTER_EMERGENCY_BRAKE, GM_TICKS_1_SEC * 5, report_emergency_brake_alarm); + return true; + } + else + { + return false; + } +} + +//上报急刹车报警 +static void report_emergency_brake_alarm(void) +{ + GPSData new_gpsinfo = {0}; + GPSData last_five_second_gpsinfo = {0}; + AlarmInfo alarm_info; + GM_ERRCODE ret = GM_SUCCESS; + + if(!gps_get_last_data(&new_gpsinfo)) + { + return; + } + if(!gps_get_last_n_senconds_data(5,&last_five_second_gpsinfo)) + { + return; + } + + //是急转弯,角度变化大于2倍MIN_ANGLE_RANGE + if (last_five_second_gpsinfo.speed > MIN_CRUISE_SPEED && applied_math_get_angle_diff(new_gpsinfo.course,last_five_second_gpsinfo.course) > 2 * MIN_ANGLE_RANGE) + { + return; + } + + //最近1秒的速度比5秒前的速度低20km/h以上,才判定为急减速 + if(new_gpsinfo.speed - last_five_second_gpsinfo.speed < -20) + { + alarm_info.type = ALARM_SPEED_DOWN; + ret = gps_service_push_alarm(&alarm_info); + system_state_set_speed_down_alarm(true); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to gps_service_push_alarm(ALARM_SPEED_DOWN),ret=%d", ret); + } + } +} + + +static bool check_rapid_acceleration(float vehicle_horizontal_aclr_magnitude) +{ + if (vehicle_horizontal_aclr_magnitude >= s_gsensor.threshold.rapid_aclr_thr) + { + GM_StartTimer(GM_TIMER_GSENSOR_CHECK_SPEED_AFTER_RAPID_ACCERATION, GM_TICKS_1_SEC * 5, report_rapid_aclr_alarm); + return true; + } + else + { + return false; + } +} + + +//获取急加速记录 +static void report_rapid_aclr_alarm(void) +{ + GPSData new_gpsinfo = {0}; + GPSData last_five_second_gpsinfo = {0}; + AlarmInfo alarm_info; + GM_ERRCODE ret = GM_SUCCESS; + + if(!gps_get_last_data(&new_gpsinfo)) + { + return; + } + if(!gps_get_last_n_senconds_data(5,&last_five_second_gpsinfo)) + { + return; + } + + //是急转弯,角度变化大于2倍MIN_ANGLE_RANGE + if (last_five_second_gpsinfo.speed > MIN_CRUISE_SPEED && applied_math_get_angle_diff(new_gpsinfo.course,last_five_second_gpsinfo.course) > 2*MIN_ANGLE_RANGE) + { + return; + } + + //最近1秒的速度比5秒前的速度大10km/h以上,才判定为急加速 + if(new_gpsinfo.speed - last_five_second_gpsinfo.speed > 10) + { + alarm_info.type = ALARM_SPEED_UP; + ret = gps_service_push_alarm(&alarm_info); + system_state_set_speed_up_alarm(true); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to gps_service_push_alarm(ALARM_SPEED_UP),ret=%d", ret); + } + } +} + +static bool check_sudden_turn_acceleration(float vehicle_horizontal_aclr_magnitude) +{ + if (vehicle_horizontal_aclr_magnitude >= s_gsensor.threshold.sudden_turn_thr) + { + GM_StartTimer(GM_TIMER_GSENSOR_CHECK_ANGLE_AFTER_SUDDEN_TURN, GM_TICKS_1_SEC * 5, report_sudden_turn_alarm); + return true; + } + else + { + return false; + } +} + +static void report_sudden_turn_alarm(void) +{ + GPSData new_gpsinfo = {0}; + GPSData last_five_second_gpsinfo = {0}; + unsigned int index = 1; + unsigned int direction_diff = 0; + AlarmInfo alarm_info; + GM_ERRCODE ret = GM_SUCCESS; + + if(!gps_get_last_data(&new_gpsinfo)) + { + return; + } + + for(index = 1;index <= 5;index++) + { + if (!gps_get_last_n_senconds_data(index, &last_five_second_gpsinfo)) + { + return; + } + direction_diff = applied_math_get_angle_diff(new_gpsinfo.course,last_five_second_gpsinfo.course); + //角度变化是在转弯的时候发生,本来加速度就会加大,角度变化超过10度/秒 + if (last_five_second_gpsinfo.speed > MIN_CRUISE_SPEED && direction_diff > MIN_ANGLE_RANGE/3.0 * index) + { + alarm_info.type = ALARM_SHARP_TURN; + ret = gps_service_push_alarm(&alarm_info); + system_state_set_sharp_turn_alarm(true); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to gps_service_push_alarm(ALARM_SHARP_TURN),ret=%d", ret); + } + break; + } + else + { + continue; + } + } +} + + +static void study_gravity(Aclr a) +{ + Vector3D sensor_aclr = {0,0,0}; + sensor_aclr.x = a.x; + sensor_aclr.y = a.y; + sensor_aclr.z = a.z; + //1、首次执行 + //2、运行1年以上(计算滑动平均值有累积误差) + if (s_gsensor.study_aclr_count == 0 || s_gsensor.study_aclr_count % ((U64)G_SENSOR_SAMPLE_FREQ * (U64)SECONDS_PER_YEAR) == 0) + { + //重置各项参数 + reset_sensor_data(); + //重置重力加速度初值 + s_gsensor.gravity.x = a.x; + s_gsensor.gravity.y = a.y; + s_gsensor.gravity.z = a.z; + s_gsensor.senor_aclr_moving_avg.x = a.x; + s_gsensor.senor_aclr_moving_avg.y = a.y; + s_gsensor.senor_aclr_moving_avg.z = a.z; + + //清空计算滑动平均值的队列 + circular_queue_empty(&(s_gsensor.aclr_x_queue)); + circular_queue_empty(&(s_gsensor.aclr_y_queue)); + circular_queue_empty(&(s_gsensor.aclr_z_queue)); + + //最新的加速度值入队列 + circular_queue_en_queue_i(&(s_gsensor.aclr_x_queue), a.x); + circular_queue_en_queue_i(&(s_gsensor.aclr_y_queue), a.y); + circular_queue_en_queue_i(&(s_gsensor.aclr_z_queue), a.z); + } + else + { + //长距离滑动平均得到重力和固定误差 + calculate_moving_avg(sensor_aclr, G_SENSOR_BUF_LEN - 1, &(s_gsensor.gravity), &(s_gsensor.cal_gravity_avg_len)); + if (VEHICLE_STATE_STATIC == system_state_get_vehicle_state()) + { + s_gsensor.static_gravity = s_gsensor.gravity; + } + } + s_gsensor.study_aclr_count++; +} + + +/***************************************************************** +功能:分解加速度到竖直方向和水平方向(传感器坐标系) +输入参数:g——滤波后重力加速度 +输入参数:sensor_aclr——滤波后传感器加速度 +输出参数:vehicle_horizontal_aclr——指向汽车水平方向加速度的指针 +输出参数:vehicle_vertical_aclr——指向汽车垂直方向加速度的指针 +返回值:0——成功;其它值错误 +*****************************************************************/ +static GM_ERRCODE get_vehicle_acceleration(Vector3D g, Vector3D sensor_aclr, Vector3D *vehicle_horizontal_aclr, Vector3D *vehicle_vertical_aclr) +{ + Vector3D B1 = {0, 0, 0}; + Vector3D B2 = {0, 0, 0}; + Vector3D B3 = {0, 0, 0}; + + Vector3D B11 = {0, 0, 0}; + Vector3D B12 = {0, 0, 0}; + Vector3D B21 = {0, 0, 0}; + Vector3D B22 = {0, 0, 0}; + Vector3D B31 = {0, 0, 0}; + Vector3D B32 = {0, 0, 0}; + + float s = 0; + float t = 0; + + //判断参数合法性 + if (NULL == vehicle_horizontal_aclr || NULL == vehicle_vertical_aclr) + { + return GM_PARAM_ERROR; + } + //传感器加速度减去重力和固有误差 + sensor_aclr.x -= g.x; + sensor_aclr.y -= g.y; + sensor_aclr.z -= g.z; + + //传感器加速度x分量在水平面的投影 + s = g.x * g.x + g.y * g.y + g.z * g.z; + t = (g.x * sensor_aclr.x) / s; + B11.x = sensor_aclr.x - g.x * t; + B11.y = 0 - g.y * t; + B11.z = 0 - g.z * t; + B12.x = B1.x - B11.x; + B12.y = B1.y - B11.y; + B12.z = B1.z - B11.z; + + //传感器加速度y分量在水平面的投影 + t = (g.y * sensor_aclr.y) / s; + B21.x = 0 - g.x * t; + B21.y = sensor_aclr.y - g.y * t; + B21.z = 0 - g.z * t; + B22.x = B2.x - B21.x; + B22.y = B2.y - B21.y; + B22.z = B2.z - B21.z; + + //传感器加速度z分量在水平面的投影 + t = (g.z * sensor_aclr.z) / s; + B31.x = 0 - g.x * t; + B31.y = 0 - g.y * t; + B31.z = sensor_aclr.z - g.z * t; + B32.x = B3.x - B31.x; + B32.y = B3.y - B31.y; + B32.z = B3.z - B31.z; + + //车辆加速度的水平分量 + vehicle_horizontal_aclr->x = B11.x + B21.x + B31.x; + vehicle_horizontal_aclr->y = B11.y + B21.y + B31.y; + vehicle_horizontal_aclr->z = B11.z + B21.z + B31.z; + + //车辆加速度的垂直分量 + vehicle_vertical_aclr->x = B12.x + B22.x + B32.x; + vehicle_vertical_aclr->y = B12.y + B22.y + B32.y; + vehicle_vertical_aclr->z = B12.z + B22.z + B32.z; + + return GM_SUCCESS; +} + + +//滑动平均 +static void calculate_moving_avg(Vector3D sensor_aclr, int num, PVector3D p_aclr_moving_avg, unsigned int *p_len) +{ + int head_x = 0; + int head_y = 0; + int head_z = 0; + int len = circular_queue_get_len(&(s_gsensor.aclr_x_queue)); + if (NULL == p_aclr_moving_avg || NULL == p_len || num <= 0 || num > circular_queue_get_capacity(&(s_gsensor.aclr_x_queue))) + { + return; + } + if (circular_queue_is_empty(&(s_gsensor.aclr_x_queue))) + { + *p_aclr_moving_avg = sensor_aclr; + *p_len = 1; + } + //不满 + else if (num >= len) + { + p_aclr_moving_avg->x = (sensor_aclr.x + (len - 1) * p_aclr_moving_avg->x) / (len); + p_aclr_moving_avg->y = (sensor_aclr.y + (len - 1) * p_aclr_moving_avg->y) / (len); + p_aclr_moving_avg->z = (sensor_aclr.z + (len - 1) * p_aclr_moving_avg->z) / (len); + *p_len = len; + //printf("len = %d,x = %f,y=%f,z=%f\n",*p_len,p_aclr_moving_avg->x,p_aclr_moving_avg->y,p_aclr_moving_avg->z); + } + //满了 + else if (num < len) + { + circular_queue_get_by_index_i(&(s_gsensor.aclr_x_queue), num, &head_x); + circular_queue_get_by_index_i(&(s_gsensor.aclr_y_queue), num, &head_y); + circular_queue_get_by_index_i(&(s_gsensor.aclr_z_queue), num, &head_z); + p_aclr_moving_avg->x = (sensor_aclr.x + (*p_len) * p_aclr_moving_avg->x - head_x) / num; + p_aclr_moving_avg->y = (sensor_aclr.y + (*p_len) * p_aclr_moving_avg->y - head_y) / num; + p_aclr_moving_avg->z = (sensor_aclr.z + (*p_len) * p_aclr_moving_avg->z - head_z) / num; + *p_len = num; + //printf("len = %d, head.x = %f, head.y = %f, head.z = %f,x = %f,y=%f,z=%f\n",*p_len,head_x,head_y,head_z,p_aclr_moving_avg->x,p_aclr_moving_avg->y,p_aclr_moving_avg->z); + } + else + { + //不存在这种情况 + } +} + + +static void check_static_or_run(float vehicle_horizontal_aclr_magnitude) +{ + + //1、正常行驶:加速度(传感器)超过阈值 + if (vehicle_horizontal_aclr_magnitude >= s_gsensor.threshold.run_thr) + { + s_gsensor.static_low_aclr_count = 0; + s_gsensor.super_low_aclr_count = 0; + if (VEHICLE_STATE_STATIC == system_state_get_vehicle_state()) + { + bool move_alarm_enable = false; + config_service_get(CFG_IS_MOVEALARM_ENABLE, TYPE_BOOL, &move_alarm_enable, sizeof(move_alarm_enable)); + //自从休眠唤醒以后还没有上报过移动报警 + if (move_alarm_enable && !system_state_get_move_alarm()) + { + AlarmInfo alarm_info; + alarm_info.type = ALARM_MOVE; + gps_service_push_alarm(&alarm_info); + system_state_set_move_alarm(true); + LOG(WARN,"MOVE ALARM"); + } + system_state_set_vehicle_state(VEHICLE_STATE_RUN); + } + LOG(INFO,"RUN:aclr=%f,thr=%f",vehicle_horizontal_aclr_magnitude,s_gsensor.threshold.run_thr); + } + //2、运动转为静止 + else if (vehicle_horizontal_aclr_magnitude <= s_gsensor.threshold.static_thr) + { + s_gsensor.static_low_aclr_count++; + //MIN_LOW_ACLR_NUM次加速度小于阈值才判定为静止了 + if (s_gsensor.static_low_aclr_count >= MIN_LOW_ACLR_NUM) + { + system_state_set_vehicle_state(VEHICLE_STATE_STATIC); + } + //如果加速度特别低,连续10秒就变静止 + if (vehicle_horizontal_aclr_magnitude <= (s_gsensor.threshold.static_thr / 5)) + { + s_gsensor.super_low_aclr_count++; + if (s_gsensor.super_low_aclr_count >= MIN_LOW_ACLR_NUM / 2) + { + system_state_set_vehicle_state(VEHICLE_STATE_STATIC); + } + } + else + { + s_gsensor.super_low_aclr_count = 0; + } + } + //3、中间态 + else + { + } + + //4、匀速行驶:速度超过阈值,并且加速度(通过速度计算)小 + if ((gps_get_constant_speed_time() >= MIN_CRUISE_SPEED_TIME && gps_get_aclr() < s_gsensor.threshold.rapid_aclr_thr * GRAVITY_CONSTANT)) + { + s_gsensor.static_low_aclr_count = 0; + s_gsensor.super_low_aclr_count = 0; + if (VEHICLE_STATE_STATIC == system_state_get_vehicle_state()) + { + LOG(INFO,"RUN because of speed,time:%d,gps aclr:%f",gps_get_constant_speed_time(),gps_get_aclr()); + system_state_set_vehicle_state(VEHICLE_STATE_RUN); + } + } +} + + diff --git a/src/gprs.c b/src/gprs.c new file mode 100644 index 0000000..b9b2c6f --- /dev/null +++ b/src/gprs.c @@ -0,0 +1,532 @@ +#include "gm_type.h" +#include "stdio.h" +#include "gm_stdlib.h" +#include "gm_gprs.h" +#include "socket.h" +#include "gm_memory.h" +#include "gm_network.h" +#include "config_service.h" +#include "gps_service.h" +#include "log_service.h" +#include "agps_service.h" +#include "update_service.h" +#include "update_file.h" +#include "utility.h" +#include "gm_system.h" +#include "gprs.h" +#include "socket.h" +#include "hard_ware.h" +#include "gsm.h" +#include "led.h" + + +typedef enum +{ + CURRENT_GPRS_INIT = 0, + CURRENT_GPRS_CALL_OK = 1, // 语音ok, 可以注册apn了 + CURRENT_GPRS_ACTIVATED = 2, // 网络准备好了,可以建socket了 + CURRENT_GPRS_TIME_PROC = 3, //after create services + CURRENT_GPRS_FAILED = 4, + CURRENT_GPRS_STATUS_MAX, +}CurrentGetGprsConnectStatusEnum; + + +typedef struct +{ + u8 status; /* current status */ + u32 failed_time; //故障, 准备重新开始注册时间 + u32 start_apn_time; //开始注册apn时间 + u32 last_good_time; // 上次网络正常的时间 + u32 call_ok_count; //CURRENT_GPRS_INIT->CURRENT_GPRS_CALL_OK 次数 +}GprsType; +static GprsType s_gprs; + +#define GPRS_REREGIST_INTERVALL 5 +#define GPRS_REREGIST_NEED_TIME_MAX 90 +#define GPRS_STATUS_STRING_MAX_LEN 32 +#define GPRS_REBOOT_HEART_FAILEDTIMES 7 + +const char s_gprs_status_string[CURRENT_GPRS_STATUS_MAX][GPRS_STATUS_STRING_MAX_LEN] = +{ + "CURRENT_GPRS_INIT", + "CURRENT_GPRS_CALL_OK", + "CURRENT_GPRS_ACTIVATED", + "CURRENT_GPRS_TIME_PROC", + "CURRENT_GPRS_FAILED", +}; + +static GM_ERRCODE gprs_transfer_status(u8 new_status); +static void gprs_init_proc(void); +static void gprs_call_ok_proc(void); +static void gprs_failed_proc(void); +static void gprs_config_apn(void); + +const char * gprs_status_string(u8 statu) +{ + return s_gprs_status_string[statu]; +} + +static void gprs_config_apn(void) +{ + int account_id = -1; + ST_GprsConfig apnConfig; + goome_auto_apn_struct auto_apn; + gm_cell_info_struct cell_info; + u8 imsi[GM_IMSI_LEN + 1]; + u8 auto_check_apn = false; + + GM_memset(&auto_apn, 0 , sizeof(auto_apn)); + GM_memset(&apnConfig, 0 , sizeof(apnConfig)); + config_service_get(CFG_APN_CHECK, TYPE_BOOL, &auto_check_apn, sizeof(auto_check_apn)); + + if(auto_check_apn) + { + // 从sim卡中读出imsi + // 第一次启动一定拿不到IMSI,所以这里一定是失败的,会先用默认的CMNET,如果CMNET失败了再重新初始化的时候就可以拿到IMSI了 + if((GM_SUCCESS == gsm_get_imsi(imsi)) && (GM_SUCCESS == gsm_get_cell_info(&cell_info))) + { + GM_memset(&auto_apn, 0x00, sizeof(goome_auto_apn_struct)); + auto_apn.mcc = cell_info.serv_info.mcc; + if (cell_info.serv_info.mnc > 100) + { + auto_apn.mnc = util_chr(imsi[3]) * 100 + util_chr(imsi[4]) * 10 + util_chr(imsi[5]); + } + else + { + auto_apn.mnc = util_chr(imsi[3]) * 10 + util_chr(imsi[4]); + } + + //自动检测apn + if (0 == GM_AutoApnCheck(&auto_apn)) + { + GM_strncpy((char*)apnConfig.apnName, (const char*)auto_apn.apn, sizeof(apnConfig.apnName)); + GM_strncpy((char*)apnConfig.apnUserId, (const char*)auto_apn.usrname, sizeof(apnConfig.apnUserId)); + GM_strncpy((char*)apnConfig.apnPasswd, (const char*)auto_apn.usrpass, sizeof(apnConfig.apnPasswd)); + LOG(INFO,"config_service_apn auto config(%s).",apnConfig.apnName); + } + else + { + LOG(ERROR,"config_service_apn assert(GM_AutoApnCheck) failed."); + GM_strcpy((char*)apnConfig.apnName,"CMNET"); + } + } + else + { + LOG(WARN,"config_service_apn assert(gsm_get_imsi) failed."); + GM_strcpy((char*)apnConfig.apnName,"CMNET"); + } + } + + //手工设置apn + if(0 == GM_strlen((char*)auto_apn.usrname)) + { + GM_strncpy((char*)apnConfig.apnName, (const char*)config_service_get_pointer(CFG_APN_NAME), sizeof(apnConfig.apnName)); + GM_strncpy((char*)apnConfig.apnUserId, (const char*)config_service_get_pointer(CFG_APN_USER), sizeof(apnConfig.apnUserId)); + GM_strncpy((char*)apnConfig.apnPasswd, (const char*)config_service_get_pointer(CFG_APN_PWD), sizeof(apnConfig.apnPasswd)); + } + + //注册apn后, 就可以通过 GM_GetBearerStatus 检测网络状态 + GM_ApnConfig(&apnConfig, &account_id); + LOG(INFO,"config_service_apn get account_id(%d). name(%s),user(%s),pwd(%s),auth(%d)", account_id, + apnConfig.apnName, apnConfig.apnUserId, apnConfig.apnPasswd, apnConfig.authtype); + + gm_socket_set_account_id(account_id); +} + +static GM_ERRCODE gprs_transfer_status(u8 new_status) +{ + u8 old_status = (u8)s_gprs.status; + GM_ERRCODE ret = GM_PARAM_ERROR; + switch(s_gprs.status) + { + case CURRENT_GPRS_INIT: + switch(new_status) + { + case CURRENT_GPRS_INIT: + break; + case CURRENT_GPRS_CALL_OK: + s_gprs.call_ok_count ++; + ret = GM_SUCCESS; + break; + case CURRENT_GPRS_ACTIVATED: + break; + case CURRENT_GPRS_TIME_PROC: + break; + case CURRENT_GPRS_FAILED: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case CURRENT_GPRS_CALL_OK: + switch(new_status) + { + case CURRENT_GPRS_INIT: + break; + case CURRENT_GPRS_CALL_OK: + break; + case CURRENT_GPRS_ACTIVATED: + ret = GM_SUCCESS; + break; + case CURRENT_GPRS_TIME_PROC: + break; + case CURRENT_GPRS_FAILED: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case CURRENT_GPRS_ACTIVATED: + switch(new_status) + { + case CURRENT_GPRS_INIT: + break; + case CURRENT_GPRS_ACTIVATED: + break; + case CURRENT_GPRS_TIME_PROC: + ret = GM_SUCCESS; + break; + case CURRENT_GPRS_FAILED: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case CURRENT_GPRS_TIME_PROC: + switch(new_status) + { + case CURRENT_GPRS_INIT: + break; + case CURRENT_GPRS_ACTIVATED: + break; + case CURRENT_GPRS_TIME_PROC: + break; + case CURRENT_GPRS_FAILED: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case CURRENT_GPRS_FAILED: + switch(new_status) + { + case CURRENT_GPRS_INIT: + ret = GM_SUCCESS; + break; + case CURRENT_GPRS_ACTIVATED: + break; + case CURRENT_GPRS_TIME_PROC: + break; + case CURRENT_GPRS_FAILED: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + default: + break; + } + + + if(GM_SUCCESS == ret) + { + s_gprs.status = new_status; + LOG(INFO,"clock(%d) gprs_transfer_status from %s to %s success", util_clock(), gprs_status_string(old_status),gprs_status_string(new_status)); + } + else + { + LOG(WARN,"clock(%d) gprs_transfer_status assert(from %s to %s) failed", util_clock(), gprs_status_string(old_status),gprs_status_string(new_status)); + } + + return ret; + +} + + +void gprs_socket_notify(void* msg_ptr) +{ + SocketType * socket; + gm_soc_notify_ind_struct *msg = (gm_soc_notify_ind_struct *)msg_ptr; + + socket = get_socket_by_id(msg->socket_id); + if(!socket) + { + LOG(ERROR,"clock(%d) gprs_socket_notify assert(socket_id(%d)) failed.", util_clock(), msg->socket_id); + GM_SocketClose(msg->socket_id); + return; + } + else + { + LOG(DEBUG,"clock(%d) gprs_socket_notify socket->access_id(%d) id(%d) result(%d) event(%d).", + util_clock(), socket->access_id, socket->id, msg->result, msg->event_type); + } + + if (msg->result) + { + switch (msg->event_type) + { + case GM_SOC_READ: + gm_socket_recv(socket); + break; + + case GM_SOC_WRITE: + LOG(DEBUG,"clock(%d) gprs_socket_notify GM_SOC_WRITE(%d).", util_clock(), msg->socket_id); + break; + + case GM_SOC_ACCEPT: + LOG(DEBUG,"clock(%d) gprs_socket_notify GM_SOC_ACCEPT(%d).", util_clock(), msg->socket_id); + break; + + case GM_SOC_CONNECT: + { + LOG(INFO,"clock(%d) gm_socket_connect tcp(%d.%d.%d.%d:%d) id(%d) access_id(%d) success.", + util_clock(), socket->ip[0], socket->ip[1], socket->ip[2], socket->ip[3], socket->port, socket->id, socket->access_id); + gm_socket_connect_ok(socket); + break; + } + + case GM_SOC_CLOSE: + { + LOG(INFO,"clock(%d) gprs_socket_notify id(%d) close. error_cause(%d)", util_clock(), msg->socket_id,msg->error_cause); + break; + } + default: + { + LOG(DEBUG,"clock(%d) gprs_socket_notify id(%d) unknown. error_cause(%d).", util_clock(), msg->socket_id,msg->error_cause); + break; + } + } + } + else + { + char reason[30]; + snprintf(reason,sizeof(reason),"s(%d) err(%d)", socket->access_id, msg->error_cause); + reason[sizeof(reason) - 1] = 0; + system_state_set_gpss_reboot_reason(reason); + + LOG(DEBUG,"clock(%d) gprs_socket_notify socket_id(%d) error_cause(%d).", util_clock(), msg->socket_id,msg->error_cause); + if (GM_CheckSimValid() == 0) + { + LOG(INFO,"clock(%d) gprs_socket_notify GM_CheckSimValid failed.", util_clock()); + } + + if(socket->access_id == SOCKET_INDEX_MAIN) + { + gprs_destroy(); + } + else + { + gm_socket_destroy(socket); + } + } +} + + +GM_ERRCODE gprs_create(void) +{ + s_gprs.status = CURRENT_GPRS_INIT; + + // 在gprs_init_proc中需要检测 + s_gprs.last_good_time = s_gprs.failed_time = util_clock(); + s_gprs.call_ok_count = 0; + + gm_socket_global_init(); + agps_service_create(true); + config_service_create(); + gps_service_create(true); + update_service_create(true); + log_service_create(); + GM_DnsParserCallback(socket_get_host_by_name_callback); + + + return GM_SUCCESS; +} + +static void gprs_init_proc(void) +{ + u32 current_time = 0; + + if (GM_GetServiceAvailability()) + { + // 注网成功(包括cg 与creg) + U8 iccid[30] = {0}; + JsonObject* p_log_root = json_create(); + + gsm_get_iccid(iccid); + json_add_string(p_log_root, "event", "GPRS call ok"); + json_add_string(p_log_root, "iccid", (char*)iccid); + json_add_int(p_log_root, "csq", gsm_get_csq()); + + gprs_config_apn(); + s_gprs.start_apn_time = util_clock(); + gprs_transfer_status(CURRENT_GPRS_CALL_OK); + + GM_SocketRegisterCallBack(gprs_socket_notify); + + log_service_upload(INFO,p_log_root); + + } + else + { + led_set_gsm_state(GM_LED_OFF); + current_time = util_clock(); + if((current_time - s_gprs.failed_time) > GPRS_REREGIST_NEED_TIME_MAX) + { + LOG(DEBUG,"clock(%d) gprs_init_proc exceed(%d)",util_clock(),GPRS_REREGIST_NEED_TIME_MAX); + //system_state_set_gpss_reboot_reason("gprs_init_proc"); + gprs_destroy(); + } + // else recheck. + } +} + + +static void gprs_call_ok_proc(void) +{ + u32 current_time = 0; + s32 bear_status = 0; + GM_GetBearerStatus(&bear_status); + + if (4 == bear_status) + { + JsonObject* p_log_root = json_create(); + //此时网络可用了 + led_set_gsm_state(GM_LED_FLASH); + gprs_transfer_status(CURRENT_GPRS_ACTIVATED); + + + // 网络可用了 + json_add_string(p_log_root, "event", "GPRS net ok"); + json_add_int(p_log_root, "csq", gsm_get_csq()); + log_service_upload(INFO,p_log_root); + } + else + { + current_time = util_clock(); + if((current_time - s_gprs.start_apn_time) > GPRS_REREGIST_NEED_TIME_MAX) + { + /*char reason[30]; + snprintf(reason,sizeof(reason),"bear_status(%d)", bear_status); + reason[sizeof(reason) - 1] = 0; + system_state_set_gpss_reboot_reason(reason); + */ + LOG(INFO,"clock(%d) gprs_call_ok_proc gprs_destroy because bear_status(%d)",util_clock(),bear_status); + gprs_destroy(); + } + } +} + +GM_ERRCODE gprs_destroy(void) +{ + //上传日志 + JsonObject* p_log_root = json_create(); + char ip_str[16] = {0}; + U8 iccid[30] = {0}; + + U8* ip = gps_service_get_current_ip(); + + gsm_get_iccid(iccid); + GM_snprintf(ip_str, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + json_add_string(p_log_root, "event", "GPRS Failed"); + json_add_string(p_log_root, "addr", config_service_get_pointer(CFG_SERVERADDR)); + json_add_string(p_log_root, "ip", ip_str); + json_add_string(p_log_root, "iccid", (char*)iccid); + json_add_int(p_log_root, "csq", gsm_get_csq()); + log_service_upload(INFO,p_log_root); + + gm_socket_global_destroy(); + + //关闭gprs网络等待重新注册成功 + GM_AccountIdClose(); + led_set_gsm_state(GM_LED_FLASH); + + s_gprs.failed_time = util_clock(); + gprs_transfer_status(CURRENT_GPRS_FAILED); + GM_SocketRegisterCallBack(NULL); + return GM_SUCCESS; +} + +static void gprs_failed_proc(void) +{ + u32 current_time = util_clock(); + + //卡失效时,要进入飞行模式再退出才可用。但飞行模式用得少,还是重启靠谱 + if(gprs_check_need_reboot(s_gprs.last_good_time)) + { + return; + } + + if((current_time - s_gprs.failed_time) >= GPRS_REREGIST_INTERVALL) + { + gprs_transfer_status(CURRENT_GPRS_INIT); + } + +} + +GM_ERRCODE gprs_timer_proc(void) +{ + switch(s_gprs.status) + { + case CURRENT_GPRS_INIT: + gprs_init_proc(); + break; + case CURRENT_GPRS_CALL_OK: + gprs_call_ok_proc(); + break; + case CURRENT_GPRS_ACTIVATED: + //本意是在此创建各service, 但目前用不上 + gprs_transfer_status(CURRENT_GPRS_TIME_PROC); + break; + case CURRENT_GPRS_TIME_PROC: + s_gprs.last_good_time = util_clock(); + gm_socket_get_host_timer_proc(); + agps_service_timer_proc(); + config_service_timer_proc(); + + // config_service 放前面, 确保第一次能创建service + update_service_timer_proc(); + gps_service_timer_proc(); + log_service_timer_proc(); + break; + case CURRENT_GPRS_FAILED: + gprs_failed_proc(); + break; + } + return GM_SUCCESS; +} + +bool gprs_is_ok(void) +{ + return (CURRENT_GPRS_TIME_PROC == s_gprs.status); +} + + +bool gprs_check_need_reboot(u32 check_time) +{ + //保命手段 , 网络一直不好, 重启 + U16 value_u16 = 0xFFFF; + config_service_get(CFG_HEART_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + //7次心跳失败重启,考虑时间误差再加5秒 + if((util_clock() - check_time) > (GPRS_REBOOT_HEART_FAILEDTIMES*value_u16 + 5)) + { + hard_ware_reboot(GM_REBOOT_GPRS,1); + return true; + } + return false; +} + +u32 gprs_get_last_good_time(void) +{ + return s_gprs.last_good_time; +} + +u32 gprs_get_call_ok_count(void) +{ + return s_gprs.call_ok_count; +} + diff --git a/src/gps.c b/src/gps.c new file mode 100644 index 0000000..00b39a6 --- /dev/null +++ b/src/gps.c @@ -0,0 +1,2163 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: gps.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-19 + * Description: 使用agps_service、epo_service、config_service + * Others: + * Function List: + 1. 创建gps模块 + 2. 销毁gps模块 + 3. 模块定时处理入口 + 4. 打开GPS模块 + 5. 关闭GPS模块 + 6. 获取最新GPS数据 + * History: + 1. Date: 2019-03-19 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include +#include +#include +#include +#include +#include +#include "gps.h" +#include "applied_math.h" +#include "nmea_protocol.h" +#include "log_service.h" +#include "config_service.h" +#include "agps_service.h" +#include "uart.h" +#include "hard_ware.h" +#include "circular_queue.h" +#include "gps_service.h" +#include "g_sensor.h" +#include "system_state.h" +#include "led.h" +#include "gsm.h" +#include "utility.h" + + +#define GPS_BUFF_LEN 50 + + +typedef enum +{ //未初始化 + GM_GPS_STATE_NONE = 0, + + //初始化OK + GM_GPS_STATE_INITED, + + //发送了版本号查询,等待版本号响应 + GM_GPS_STATE_WAIT_VERSION, + + //发送了AGPS时间请求,等待AGPS时间响应 + GM_GPS_STATE_WAIT_APGS_TIME, + + //发送了AGPS数据请求,等待AGPS数据响应 + GM_GPS_STATE_WAIT_APGS_DATA, + + //工作中 + GM_GPS_STATE_WORKING, + +}GPSInternalState; + +typedef struct +{ + //使用的波特率 + U32 baud_rate; + + //GPS芯片型号 + GPSChipType gpsdev_type; + + //内部状态 + GPSInternalState internal_state; + + //整体状态 + GPSState state; + + //定位状态时间记录 + StateRecord state_record; + + //存放定位数据的环形队列 + CircularQueue gps_time_queue; + CircularQueue gps_lat_queue; + CircularQueue gps_lng_queue; + CircularQueue gps_speed_queue; + CircularQueue gps_course_queue; + + //启动时间 + time_t power_on_time; + + time_t last_rcv_time; + + bool push_data_enbale; + + //AGPS完成注入时间 + U16 agps_time; + + //定位时间 + time_t fix_time; + + //内存中保存时间(每秒一条) + time_t save_time; + + //上报平台时间 + time_t report_time; + + time_t sleep_time; + + //从上次上报点到当前点的距离(曲线距离) + float distance_since_last_report; + + //是否已打开VTG语句(泰斗芯片需要打开VTG语句) + bool has_opened_td_vtg; + + NMEASentenceVER frame_ver; + NMEASentenceRMC frame_rmc; + NMEASentenceGGA frame_gga; + NMEASentenceGSA frame_gsa; + NMEASentenceGST frame_gst; + NMEASentenceGSV frame_gsv; + NMEASentenceVTG frame_vtg; + NMEASentenceZDA frame_zda; + NMEASentenceGLL frame_gll; + + //辅助定位经纬度 + float ref_lng; + float ref_lat; + + //定位状态 + //GPSState的第0位表示是否定位定位,0——未定位;1——已定位 + bool is_fix; + + //GPSState的第1位表示2D/3D定位,0——2D;1——3D + bool is_3d; + + //GPSState的第2位表示是否差分定位定位,0——非差分定位;1——差分定位 + bool is_diff; + + //信号强度等级(0-100,100最高) + U8 signal_intensity_grade; + + //水平方向定位精度[0.5,99.9] + float precision; + + //可见卫星数 + U8 satellites_tracked; + + //天线高度(相对于平均海平面,单位米) + float altitude; + + //最大信噪比(1分钟更新一次) + U8 max_snr; + + //信号最好的5颗星 + SNRInfo snr_array[SNR_INFO_NUM]; + + //可见卫星数(1秒更新一次) + U8 satellites_inview; + + //snr大于35的卫星数,即我们认为可用的卫星数(1秒更新一次) + U8 satellites_good; + + float aclr_avg_calculate_by_speed; + U32 constant_speed_time; + U32 static_speed_time; + StateRecord over_speed_alarm_state; +}Gps,*PGps; + +static Gps s_gps; + +//GPS串口超过多少秒没有接收到数据关闭重新打开 +#define GM_REOPEN_GPS_PORT_TIME 30 + +static void clear_data(void); + +static void check_has_received_data(void); + +static void set_device_type(const GPSChipType dev_type); + +//查询MTK版本号 +static void query_mtk_version(void); + +//知道9600波特率能收到数据,查询泰斗和中科微版本号 +static void query_td_and_at_version(void); + +static void query_td_version(void); + +static void query_at_version(void); + +static GM_ERRCODE write_mtk_epo_time(const ST_Time utc_time); + +static void write_mtk_epo_pos(void); + +static void write_mtk_full_cold_start(void); +static void write_mtk_cold_start(void); + +//static void write_mtk_high_accuracy(bool enable); +//static void write_set_min_snr(const U8 min_snr); + +static void open_td_vtg(void); + +static GM_ERRCODE write_td_agps_time(const ST_Time utc_time,const U8 leap_sencond); + +static void write_td_agps_pos(void); + +static GM_ERRCODE write_at_agps_info(const ST_Time utc_time,const U8 leap_sencond,const float ref_lat,const float ref_lng); + +static void on_received_gga(const NMEASentenceGGA gga); + +static void on_received_gsa(const NMEASentenceGSA gsa); + +static on_received_gsv(const NMEASentenceGSV gsv); + +static void on_received_rmc(const NMEASentenceRMC rmc); + +static bool is_turn_point(const GPSData current_gps_data); + +static GpsDataModeEnum upload_mode(const GPSData current_gps_data); + +static void upload_gps_data(const GPSData current_gps_data); + +static void check_fix_state(void); + +static void check_fix_state_change(void); + +static void calc_alcr_by_speed(GPSData gps_info); + +static void check_over_speed_alarm(float speed); + + + +GM_ERRCODE gps_create(void) +{ + clear_data(); + s_gps.sleep_time = 0; + circular_queue_create(&s_gps.gps_time_queue, GPS_BUFF_LEN, GM_QUEUE_TYPE_INT); + circular_queue_create(&s_gps.gps_lat_queue, GPS_BUFF_LEN, GM_QUEUE_TYPE_FLOAT); + circular_queue_create(&s_gps.gps_lng_queue, GPS_BUFF_LEN, GM_QUEUE_TYPE_FLOAT); + circular_queue_create(&s_gps.gps_speed_queue, GPS_BUFF_LEN, GM_QUEUE_TYPE_FLOAT); + circular_queue_create(&s_gps.gps_course_queue, GPS_BUFF_LEN, GM_QUEUE_TYPE_FLOAT); + + return GM_SUCCESS; +} + +GM_ERRCODE gps_destroy(void) +{ + circular_queue_destroy(&s_gps.gps_time_queue, GM_QUEUE_TYPE_INT); + circular_queue_destroy(&s_gps.gps_lat_queue, GM_QUEUE_TYPE_FLOAT); + circular_queue_destroy(&s_gps.gps_lng_queue, GM_QUEUE_TYPE_FLOAT); + circular_queue_destroy(&s_gps.gps_speed_queue, GM_QUEUE_TYPE_FLOAT); + circular_queue_destroy(&s_gps.gps_course_queue, GM_QUEUE_TYPE_FLOAT); + return GM_SUCCESS; +} + + +GM_ERRCODE gps_timer_proc(void) +{ + return GM_SUCCESS; +} + +static void clear_data(void) +{ + s_gps.gpsdev_type = GM_GPS_TYPE_UNKNOWN; + s_gps.baud_rate = BAUD_RATE_LOW; + s_gps.internal_state = GM_GPS_STATE_INITED; + s_gps.agps_time = 0; + s_gps.state = GM_GPS_OFF; + s_gps.state_record.state = false; + s_gps.state_record.true_state_hold_seconds = 0; + s_gps.state_record.false_state_hold_seconds = 0; + s_gps.power_on_time = 0; + s_gps.last_rcv_time = 0; + s_gps.push_data_enbale = false; + s_gps.fix_time = 0; + s_gps.save_time = 0; + s_gps.report_time = 0; + s_gps.distance_since_last_report = 0; + s_gps.has_opened_td_vtg = false; + s_gps.ref_lng = 0; + s_gps.ref_lat = 0; + s_gps.is_fix = false; + s_gps.is_3d = false; + s_gps.is_diff = false; + s_gps.signal_intensity_grade = 0; + s_gps.precision = 99.9; + s_gps.satellites_tracked = 0; + s_gps.max_snr = 0; + GM_memset(s_gps.snr_array, 0, sizeof(s_gps.snr_array)); + s_gps.satellites_inview = 0; + s_gps.satellites_good = 0; + s_gps.altitude = 0; + s_gps.aclr_avg_calculate_by_speed = 0; + s_gps.constant_speed_time = 0; + s_gps.static_speed_time = 0; + s_gps.static_speed_time = 0; + s_gps.over_speed_alarm_state.state = system_state_get_overspeed_alarm(); + s_gps.over_speed_alarm_state.true_state_hold_seconds = 0; + s_gps.over_speed_alarm_state.false_state_hold_seconds = 0; + + GM_memset(&s_gps.frame_ver, 0, sizeof(NMEASentenceRMC)); + GM_memset(&s_gps.frame_rmc, 0, sizeof(NMEASentenceRMC)); + GM_memset(&s_gps.frame_gga, 0, sizeof(NMEASentenceGGA)); + GM_memset(&s_gps.frame_gst, 0, sizeof(NMEASentenceGST)); + GM_memset(&s_gps.frame_gsv, 0, sizeof(NMEASentenceGSV)); + GM_memset(&s_gps.frame_vtg, 0, sizeof(NMEASentenceVTG)); + GM_memset(&s_gps.frame_zda, 0, sizeof(NMEASentenceZDA)); + +} + +GM_ERRCODE gps_power_on(bool push_data_enbale) +{ + GM_ERRCODE ret = GM_SUCCESS; + bool gps_close = false; + + config_service_get(CFG_GPS_CLOSE, TYPE_BOOL, &gps_close, sizeof(gps_close)); + + if (gps_close) + { + return GM_SUCCESS; + } + + + if (GM_GPS_OFF != s_gps.state) + { + hard_ware_open_gps(); + return GM_SUCCESS; + } + else + { + clear_data(); + } + + s_gps.push_data_enbale = push_data_enbale; + + //先打开调试串口 + uart_open_port(GM_UART_DEBUG,BAUD_RATE_HIGH,0); + GM_SysMsdelay(10); + + s_gps.state = GM_GPS_FIX_NONE; + led_set_gps_state(GM_LED_FLASH); + s_gps.power_on_time = util_clock(); + + s_gps.gpsdev_type = config_service_get_gps_type(); + + switch (s_gps.gpsdev_type) + { + + //型号未知,先用9600波特率打开,1秒后检查,如果不成功再以115200波特率打开 + case GM_GPS_TYPE_UNKNOWN: + { + s_gps.baud_rate = BAUD_RATE_LOW; + ret = uart_open_port(GM_UART_GPS, s_gps.baud_rate, GM_REOPEN_GPS_PORT_TIME); + if(GM_SUCCESS != ret) + { + LOG(FATAL,"Failed to open GPS uart,ret=%d", ret); + } + + GM_StartTimer(GM_TIMER_GPS_QUERY_TD_AT_VERSION, TIM_GEN_1SECOND, query_td_and_at_version); + s_gps.internal_state = GM_GPS_STATE_WAIT_VERSION; + } + break; + + //MTK内置GPS,115200波特率 + case GM_GPS_TYPE_MTK_EPO: + { + s_gps.baud_rate = BAUD_RATE_HIGH; + ret = uart_open_port(GM_UART_GPS, s_gps.baud_rate, GM_REOPEN_GPS_PORT_TIME); + if (GM_SUCCESS != ret) + { + LOG(FATAL,"Failed to open GPS uart,ret=%d", ret); + } + + GM_StartTimer(GM_TIMER_GPS_QUERY_MTK_VERSION, TIM_GEN_1SECOND, query_mtk_version); + s_gps.internal_state = GM_GPS_STATE_WAIT_VERSION; + } + break; + + //泰斗,9600波特率 + case GM_GPS_TYPE_TD_AGPS: + { + s_gps.baud_rate = BAUD_RATE_LOW; + ret = uart_open_port(GM_UART_GPS, s_gps.baud_rate, GM_REOPEN_GPS_PORT_TIME); + if (GM_SUCCESS != ret) + { + LOG(FATAL,"Failed to open GPS uart,ret=%d", ret); + } + + GM_StartTimer(GM_TIMER_GPS_QUERY_TD_VERSION, TIM_GEN_1SECOND, query_td_version); + s_gps.internal_state = GM_GPS_STATE_WAIT_VERSION; + } + break; + + //中科微,9600波特率 + case GM_GPS_TYPE_AT_AGPS: + { + s_gps.baud_rate = BAUD_RATE_LOW; + ret = uart_open_port(GM_UART_GPS, s_gps.baud_rate, GM_REOPEN_GPS_PORT_TIME); + if (GM_SUCCESS != ret) + { + LOG(FATAL,"Failed to open GPS uart,ret=%d", ret); + } + + GM_StartTimer(GM_TIMER_GPS_QUERY_AT_VERSION, TIM_GEN_1SECOND, query_at_version); + s_gps.internal_state = GM_GPS_STATE_WAIT_VERSION; + } + break; + + default: + { + + } + break; + + } + + hard_ware_awake(); + + GM_StartTimer(GM_TIMER_GPS_CHECK_RECEIVED, TIM_GEN_1SECOND*5, check_has_received_data); + GM_StartTimer(GM_TIMER_GPS_CHECK_STATE, TIM_GEN_1SECOND*60, check_fix_state); + return hard_ware_open_gps(); +} + +static void check_fix_state(void) +{ + JsonObject* p_log_root = NULL; + char snr_str[128] = {0}; + if (s_gps.state < GM_GPS_FIX_3D) + { + if (false == system_state_has_reported_lbs_since_boot()) + { + gps_service_push_lbs(); + system_state_set_has_reported_lbs_since_boot(true); + } + p_log_root = json_create(); + json_add_string(p_log_root, "event", "unfixed"); + json_add_int(p_log_root, "AGPS time", s_gps.agps_time); + json_add_int(p_log_root, "satellites_in_view", s_gps.satellites_inview); + json_add_int(p_log_root, "satellites_good", s_gps.satellites_good); + json_add_int(p_log_root, "satellites_tracked", s_gps.satellites_tracked); + + GM_snprintf(snr_str,128,"%03d:%02d,%03d:%02d,%03d:%02d,%03d:%02d,%03d:%02d,", + s_gps.snr_array[0].prn,s_gps.snr_array[0].snr, + s_gps.snr_array[1].prn,s_gps.snr_array[1].snr, + s_gps.snr_array[2].prn,s_gps.snr_array[2].snr, + s_gps.snr_array[3].prn,s_gps.snr_array[3].snr, + s_gps.snr_array[4].prn,s_gps.snr_array[4].snr); + + json_add_string(p_log_root, "snr", snr_str); + json_add_int(p_log_root, "csq", gsm_get_csq()); + + //泰斗可能会出现AGPS数据无效的情况,导致发送几个数据包以后收不到芯片确认,需要重新下载AGPS数据 + if (GM_GPS_TYPE_TD_AGPS == s_gps.gpsdev_type && 0 == s_gps.agps_time && GM_GPS_STATE_WAIT_APGS_DATA == s_gps.internal_state) + { + //s_gps.internal_state = GM_GPS_STATE_WAIT_APGS_DATA; + //agps_service_require_to_gps(AGPS_TO_GPS_DATA,true); + json_add_string(p_log_root, "AGPS data", "invalid"); + } + log_service_upload(INFO,p_log_root); + } + +} + +GM_ERRCODE gps_write_agps_info(const float lng,const float lat,const U8 leap_sencond) +{ + ST_Time utc_time; + GM_ERRCODE ret = GM_SUCCESS; + U8 reopen_gps_time = 0; + + LOG(INFO,"gps_write_agps_info,current state=%d,dev_type=%d",s_gps.internal_state,s_gps.gpsdev_type); + if (s_gps.internal_state != GM_GPS_STATE_WAIT_APGS_TIME || GM_GPS_TYPE_UNKNOWN == s_gps.gpsdev_type) + { + return GM_ERROR_STATUS; + } + + //如果GPS芯片启动超过30秒了,AGPS才准备好,那么需要重启GPS芯片AGPS才有用 + config_service_get(CFG_REOPEN_GSP_TIME, TYPE_BYTE, &reopen_gps_time, sizeof(reopen_gps_time)); + //如果读取的配置值很小,恢复默认值 + if(reopen_gps_time < 5 ) + { + reopen_gps_time = 30; + config_service_set(CFG_REOPEN_GSP_TIME, TYPE_BYTE, &reopen_gps_time, sizeof(reopen_gps_time)); + } + if((util_clock() - s_gps.power_on_time) > reopen_gps_time && GM_GPS_OFF != s_gps.state) + { + bool push_data_enbale = s_gps.push_data_enbale; + JsonObject* p_log_root = json_create();; + json_add_string(p_log_root, "event", ("AGPS late")); + json_add_int(p_log_root, "AGPS time", util_clock() - s_gps.power_on_time); + log_service_upload(INFO,p_log_root); + + hard_ware_close_gps(); + clear_data(); + s_gps.push_data_enbale = push_data_enbale; + GM_SysMsdelay(100); + hard_ware_open_gps(); + s_gps.power_on_time = util_clock(); + GM_StartTimer(GM_TIMER_GPS_CHECK_RECEIVED, TIM_GEN_1SECOND*5, check_has_received_data); + GM_StartTimer(GM_TIMER_GPS_CHECK_STATE, TIM_GEN_1SECOND*60, check_fix_state); + return GM_ERROR_STATUS; + } + else + { + LOG(INFO,"clock=%d,power_on_time=%d,reopen_gps_time=%d,state=%d",util_clock(),s_gps.power_on_time,reopen_gps_time,s_gps.state); + } + + //获取UTC时间 + GM_GetLocalTime(&utc_time, 0); + + //经纬度先保存,MTK和TD要等会再用 + s_gps.ref_lng = lng; + s_gps.ref_lat = lat; + + switch (s_gps.gpsdev_type) + { + case GM_GPS_TYPE_MTK_EPO: + { + LOG(INFO,"gps_write_agps_info,write_mtk_epo_time"); + ret = write_mtk_epo_time(utc_time); + } + break; + case GM_GPS_TYPE_TD_AGPS: + { + LOG(INFO,"gps_write_agps_info,write_td_agps_time"); + ret = write_td_agps_time(utc_time, leap_sencond); + } + break; + case GM_GPS_TYPE_AT_AGPS: + { + LOG(INFO,"gps_write_agps_info,write_at_agps_info"); + ret = write_at_agps_info(utc_time, leap_sencond, lat, lng); + } + break; + default: + { + LOG(ERROR,"gps_write_agps_info,dev_type=%d,",s_gps.gpsdev_type); + return GM_ERROR_STATUS; + } + } + if (GM_SUCCESS) + { + LOG(ERROR,"Failed to write_agps_info,ret=%d",ret); + } + return ret; +} + +/** + * Function: 写入agps(epo)数据 + * Description: + * Input: seg_index:分片ID;p_data:数据指针;len:数据长度 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE gps_write_agps_data(const U16 seg_index, const U8* p_data, const U16 len) +{ + GM_ERRCODE ret = GM_SUCCESS; + if (s_gps.internal_state != GM_GPS_STATE_WAIT_APGS_DATA) + { + LOG(ERROR,"Could not write APGS data,current state=%d",s_gps.internal_state); + return GM_ERROR_STATUS; + } + else + { + LOG(INFO,"gps_write_agps_data,seg_index=%d,len=%d",seg_index,len); + } + + switch (s_gps.gpsdev_type) + { + case GM_GPS_TYPE_MTK_EPO: + { + U8 epo_sentence[300] = {0}; + U16 sentence_len = 300; + + nmea_creat_mtk_epo_sentence(seg_index,p_data,len,epo_sentence,&sentence_len); + ret = uart_write(GM_UART_GPS, epo_sentence, sentence_len); + //LOG(INFO,(char*)epo_sentence); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to write EPO data,ret=%d", ret); + } + } + break; + + case GM_GPS_TYPE_TD_AGPS: + { + ret = uart_write(GM_UART_GPS, p_data, len); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to write AGPS data,ret=%d,len=%d", ret,len); + } + } + break; + + case GM_GPS_TYPE_AT_AGPS: + { + ret = uart_write(GM_UART_GPS, p_data, len); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to write AGPS data,ret=%d,len=%d", ret,len); + } + } + break; + + default: + { + LOG(ERROR, "Unknown device type!"); + } + } + return GM_SUCCESS; +} + +GM_ERRCODE gps_power_off(void) +{ + s_gps.state = GM_GPS_OFF; + GM_StopTimer(GM_TIMER_GPS_CHECK_STATE); + GM_StopTimer(GM_TIMER_GPS_CHECK_RECEIVED); + uart_close_port(GM_UART_GPS); + led_set_gps_state(GM_LED_OFF); + + uart_close_port(GM_UART_DEBUG); + hard_ware_close_gps(); + hard_ware_sleep(); + s_gps.sleep_time = util_clock(); + return GM_SUCCESS; +} + +GPSState gps_get_state(void) +{ + return s_gps.state; +} + +bool gps_is_fixed(void) +{ + if (GM_GPS_FIX_3D > gps_get_state() || GM_GPS_OFF == gps_get_state()) + { + return false; + } + else + { + return true; + } +} + +U16 gps_get_fix_time(void) +{ + return s_gps.fix_time; +} + +U8 gps_get_max_snr(void) +{ + return s_gps.max_snr; +} + +U8 gps_get_satellites_tracked(void) +{ + return s_gps.satellites_tracked; +} + +U8 gps_get_satellites_inview(void) +{ + return s_gps.satellites_inview; +} + +U8 gps_get_satellites_good(void) +{ + return s_gps.satellites_good; +} +const SNRInfo* gps_get_snr_array(void) +{ + return s_gps.snr_array; +} + +bool gps_get_last_data(GPSData* p_data) +{ + return gps_get_last_n_senconds_data(0,p_data); +} + +/** + * Function: 获取最近n秒的GPS数据 + * Description: + * Input: seconds:第几秒,从0开始 + * Output: p_data:指向定位数据的指针 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +bool gps_get_last_n_senconds_data(U8 seconds,GPSData* p_data) +{ + if (NULL == p_data) + { + return false; + } + else + { + if(!circular_queue_get_by_index_i(&s_gps.gps_time_queue, seconds, (S32 *)&p_data->gps_time)) + { + return false; + } + if(!circular_queue_get_by_index_f(&s_gps.gps_lat_queue, seconds, &p_data->lat)) + { + return false; + } + if(!circular_queue_get_by_index_f(&s_gps.gps_lng_queue, seconds, &p_data->lng)) + { + return false; + } + if(!circular_queue_get_by_index_f(&s_gps.gps_speed_queue, seconds, &p_data->speed)) + { + return false; + } + if(!circular_queue_get_by_index_f(&s_gps.gps_course_queue, seconds, &p_data->course)) + { + return false; + } + p_data->satellites = s_gps.satellites_tracked; + p_data->precision = s_gps.precision; + p_data->signal_intensity_grade = s_gps.signal_intensity_grade; + return true; + } +} + + +static void check_has_received_data(void) +{ + //如果串口还没收到数据 + if (s_gps.internal_state <= GM_GPS_STATE_WAIT_VERSION) + { + JsonObject* p_log = json_create(); + json_add_string(p_log, "event", "Open GPS failed!"); + json_add_int(p_log, "power_on_time", s_gps.power_on_time); + json_add_int(p_log, "last_rcv_time", s_gps.last_rcv_time); + log_service_upload(ERROR, p_log); + + hard_ware_close_gps(); + uart_close_port(GM_UART_GPS); + GM_SysMsdelay(100); + + //如果型号未知,更换波特率 + if(GM_GPS_TYPE_UNKNOWN == s_gps.gpsdev_type) + { + if (BAUD_RATE_HIGH == s_gps.baud_rate) + { + s_gps.baud_rate = BAUD_RATE_LOW; + } + else + { + s_gps.baud_rate = BAUD_RATE_HIGH; + } + } + + //连续10分钟未收到数据重启,否则重新打开GPS和串口继续检查是否收到数据 + if((util_clock() - s_gps.last_rcv_time) >= 10*SECONDS_PER_MIN && (util_clock() - s_gps.power_on_time) > 10*SECONDS_PER_MIN) + { + hard_ware_reboot(GM_REBOOT_GPS,1); + return; + } + else + { + GM_ERRCODE ret = uart_open_port(GM_UART_GPS, s_gps.baud_rate, GM_REOPEN_GPS_PORT_TIME); + if(GM_SUCCESS != ret) + { + LOG(FATAL,"Failed to open GPS uart,ret=%d", ret); + return; + } + else + { + LOG(INFO,"Reopen UART with %d.",s_gps.baud_rate); + query_mtk_version(); + } + hard_ware_open_gps(); + GM_StartTimer(GM_TIMER_GPS_CHECK_RECEIVED, TIM_GEN_1SECOND*5, check_has_received_data); + } + + } + else + { + LOG(DEBUG,"Internal state:%d",s_gps.internal_state); + } +} + +static void set_device_type(const GPSChipType dev_type) +{ + if (dev_type != s_gps.gpsdev_type) + { + s_gps.gpsdev_type = dev_type; + config_service_set(CFG_GPS_TYPE, TYPE_BYTE, &dev_type, sizeof(U8)); + config_service_save_to_local(); + LOG(INFO,"Save GPS type to local:type=%d",dev_type); + } +} + +void gps_on_rcv_uart_data(char* p_data, const U16 len) +{ + bool has_agps_data_left = false; + s_gps.last_rcv_time = util_clock(); + + switch (nmea_sentence_id(p_data,len, false)) + { + case NMEA_SENTENCE_TXT: + { + + if (nmea_parse_txt(&s_gps.frame_ver, p_data)) + { + LOG(INFO,"AT GPS version:%s",s_gps.frame_ver.ver); + set_device_type(GM_GPS_TYPE_AT_AGPS); + if (s_gps.internal_state < GM_GPS_STATE_WAIT_APGS_TIME) + { + s_gps.internal_state = GM_GPS_STATE_WAIT_APGS_TIME; + agps_service_require_to_gps(AGPS_TO_GPS_LNGLAT_TIME,false); + LOG(DEBUG,"NMEA_SENTENCE_TXT"); + } + } + else + { + //LOG(DEBUG,"$TXT sentence is not parsed:%s",p_data); + } + } + break; + case NMEA_SENTENCE_INF: + { + if (nmea_parse_inf(&s_gps.frame_ver, p_data)) + { + LOG(INFO,"TD GPS version:%s",s_gps.frame_ver.ver); + set_device_type(GM_GPS_TYPE_TD_AGPS); + if (s_gps.internal_state < GM_GPS_STATE_WAIT_APGS_TIME) + { + s_gps.internal_state = GM_GPS_STATE_WAIT_APGS_TIME; + agps_service_require_to_gps(AGPS_TO_GPS_LNGLAT_TIME,false); + LOG(DEBUG,"NMEA_SENTENCE_INF"); + } + } + else + { + //LOG(DEBUG,"$INF sentence is not parsed"); + } + } + break; + + // MTK AGPS ACK,确认包 + case NMEA_SENTENCE_MTK_ACK: + { + NMEASentenceMTKACK mtk_ack; + if (nmea_parse_mtk_ack(&mtk_ack, p_data)) + { + if(MTK_TIME_ACK == mtk_ack.ack_type) + { + write_mtk_epo_pos(); + LOG(INFO,"Received MTK_TIME_ACK"); + } + else if(MTK_POS_ACK == mtk_ack.ack_type) + { + s_gps.internal_state = GM_GPS_STATE_WAIT_APGS_DATA; + agps_service_require_to_gps(AGPS_TO_GPS_DATA,false); + LOG(INFO,"Received MTK_POS_ACK"); + } + else if(MTK_DATA_ACK == mtk_ack.ack_type) + { + LOG(INFO,"Received MTK_DATA_ACK"); + if (GM_GPS_STATE_WAIT_APGS_DATA == s_gps.internal_state) + { + has_agps_data_left = agps_service_require_to_gps(AGPS_TO_GPS_DATA,false); + if (false == has_agps_data_left) + { + s_gps.internal_state = GM_GPS_STATE_WORKING; + s_gps.agps_time = util_clock() - s_gps.power_on_time; + LOG(INFO,"MTK Start working........................."); + } + } + } + else if(MTK_TTFF_ACK == mtk_ack.ack_type) + { + LOG(INFO,"Enable TIFF"); + } + else + { + LOG(INFO,"MTK ack type:%d,%s",mtk_ack.ack_type,p_data); + } + } + else + { + LOG(DEBUG,"sentence is not parsed:%s",p_data); + } + } + break; + + // MTK GPS work OK,可以发送EPO + case NMEA_SENTENCE_MTK_START: + { + if (s_gps.internal_state < GM_GPS_STATE_WAIT_APGS_TIME) + { + U8 min_snr = 0; + config_service_get(CFG_MIN_SNR, TYPE_BYTE, &min_snr, sizeof(min_snr)); + LOG(INFO,"NMEA_SENTENCE_MTK_START,min_snr:%d",min_snr); + if(system_state_is_cold_boot()) + { + write_mtk_full_cold_start(); + system_state_set_cold_boot(false); + } + else if(0) // do no execute + { + GPSData p_data; + if(!gps_get_last_data(&p_data)) + { + write_mtk_cold_start(); + } + } + + //write_mtk_high_accuracy(false); + //write_set_min_snr(min_snr); + set_device_type(GM_GPS_TYPE_MTK_EPO); + s_gps.internal_state = GM_GPS_STATE_WAIT_APGS_TIME; + agps_service_require_to_gps(AGPS_TO_GPS_LNGLAT_TIME,false); + } + } + break; + + // MTK GPS version,版本号 + case NMEA_SENTENCE_MTK_VER: + { + LOG(INFO,"Received MTK version"); + if (s_gps.internal_state < GM_GPS_STATE_WAIT_APGS_TIME) + { + LOG(DEBUG,"NMEA_SENTENCE_MTK_VER"); + set_device_type(GM_GPS_TYPE_MTK_EPO); + s_gps.internal_state = GM_GPS_STATE_WAIT_APGS_TIME; + agps_service_require_to_gps(AGPS_TO_GPS_LNGLAT_TIME,false); + } + } + break; + + case NMEA_SENTENCE_TD_ACK: + { + U16 ack_cmd = 0; + + if (nmea_parse_td_ack(&ack_cmd, p_data,len)) + { + if(TD_AID_TIME_CMD == ack_cmd) + { + write_td_agps_pos(); + } + else if(TD_AID_POS_CMD == ack_cmd) + { + s_gps.internal_state = GM_GPS_STATE_WAIT_APGS_DATA; + agps_service_require_to_gps(AGPS_TO_GPS_DATA,false); + } + else if ( TD_AID_BDSEPH_CMD == ack_cmd || TD_AID_BDSALM_CMD == ack_cmd || TD_AID_GPSEPH_CMD == ack_cmd || TD_AID_GPSALM_CMD == ack_cmd) + { + if (GM_GPS_STATE_WAIT_APGS_DATA == s_gps.internal_state) + { + has_agps_data_left = agps_service_require_to_gps(AGPS_TO_GPS_DATA,false); + if (false == has_agps_data_left) + { + s_gps.internal_state = GM_GPS_STATE_WORKING; + s_gps.agps_time = util_clock() - s_gps.power_on_time; + LOG(DEBUG,"TD Start working........................."); + } + } + } + else if(TD_OPEN_FUNC_CMD == ack_cmd) + { + s_gps.has_opened_td_vtg = true; + } + else + { + LOG(ERROR,"Unknown TD ack type:%d",ack_cmd); + } + } + else + { + LOG(WARN,"sentence is not parsed!"); + } + } + break; + + // TD GPS version,版本号 + case NMEA_SENTENCE_TD_VER: + { + + if (nmea_parse_td_ver(&s_gps.frame_ver, p_data,len)) + { + //LOG(DEBUG,"$TDVER: %s",s_gps.frame_ver.ver); + set_device_type(GM_GPS_TYPE_TD_AGPS); + if (s_gps.internal_state < GM_GPS_STATE_WAIT_APGS_TIME) + { + LOG(DEBUG,"NMEA_SENTENCE_TD_VER"); + s_gps.internal_state = GM_GPS_STATE_WAIT_APGS_TIME; + agps_service_require_to_gps(AGPS_TO_GPS_LNGLAT_TIME,false); + open_td_vtg(); + } + } + else + { + LOG(WARN,"$TDVER sentence is not parsed"); + } + } + break; + + case NMEA_SENTENCE_AT_ACK: + { + U16 ack_cmd = 0; + + if (nmea_parse_at_ack(&ack_cmd, p_data,len)) + { + if(AT_AID_TIMEPOS_CMD == ack_cmd) + { + s_gps.internal_state = GM_GPS_STATE_WAIT_APGS_DATA; + agps_service_require_to_gps(AGPS_TO_GPS_DATA,false); + } + else if(AT_AID_BDSEPH_CMD == ack_cmd || AT_AID_GPSEPH_CMD == ack_cmd || AT_AID_GLNEPH_CMD == ack_cmd) + { + if (GM_GPS_STATE_WAIT_APGS_DATA == s_gps.internal_state) + { + s_gps.internal_state = GM_GPS_STATE_WORKING; + s_gps.agps_time = util_clock() - s_gps.power_on_time; + LOG(DEBUG,"AT Start working........................."); + } + } + else + { + LOG(WARN,"Unknown AT ack cmd:%d",ack_cmd); + } + } + else + { + LOG(WARN,"AT_ACK sentence is not parsed!"); + } + } + break; + case NMEA_SENTENCE_AT_NACK: + { + U16 ack_cmd = 0; + + if (nmea_parse_at_ack(&ack_cmd, p_data,len)) + { + if(AT_AID_TIMEPOS_CMD == ack_cmd) + { + LOG(ERROR,"The time and position packet is wrong!"); + } + else if(AT_AID_BDSEPH_CMD == ack_cmd || AT_AID_GPSEPH_CMD == ack_cmd || AT_AID_GLNEPH_CMD == ack_cmd) + { + LOG(WARN,"The AGPS data packet is wrong!"); + } + else + { + LOG(WARN,"Unknown AT nack cmd:%d",ack_cmd); + } + } + else + { + LOG(WARN,"AT_NACK sentence is not parsed!"); + } + } + break; + + // AT GPS version,版本号 + case NMEA_SENTENCE_AT_VER: + { + if (nmea_parse_at_ver(&s_gps.frame_ver, p_data,len)) + { + set_device_type(GM_GPS_TYPE_AT_AGPS); + if (s_gps.internal_state < GM_GPS_STATE_WAIT_APGS_TIME) + { + LOG(DEBUG,"NMEA_SENTENCE_AT_VER"); + s_gps.internal_state = GM_GPS_STATE_WAIT_APGS_TIME; + agps_service_require_to_gps(AGPS_TO_GPS_LNGLAT_TIME,false); + } + } + else + { + LOG(WARN,"$ATVER sentence is not parsed"); + } + } + break; + + case NMEA_SENTENCE_RMC: + { + + if (nmea_parse_rmc(&s_gps.frame_rmc, p_data)) + { + //LOG(DEBUG,"$RMC: raw coordinates,speed and course: (%d/%d,%d/%d), %d/%d,%d/%d", + //s_gps.frame_rmc.latitude.value, s_gps.frame_rmc.latitude.scale, + //s_gps.frame_rmc.longitude.value, s_gps.frame_rmc.longitude.scale, + //s_gps.frame_rmc.speed.value, s_gps.frame_rmc.speed.scale, + //s_gps.frame_rmc.course.value, s_gps.frame_rmc.course.scale); + + + on_received_rmc(s_gps.frame_rmc); + } + else + { + LOG(WARN,"$RMC sentence is not parsed"); + } + } + break; + + case NMEA_SENTENCE_GSA: + { + + if (nmea_parse_gsa(&s_gps.frame_gsa, p_data)) + { + //LOG(DEBUG,"$GSA: %c,%d,%f,%f,%f", + //s_gps.frame_gsa.mode, + //s_gps.frame_gsa.fix_type, + //nmea_tofloat(&s_gps.frame_gsa.pdop), + //nmea_tofloat(&s_gps.frame_gsa.hdop), + //nmea_tofloat(&s_gps.frame_gsa.vdop)); + on_received_gsa(s_gps.frame_gsa); + } + else + { + LOG(WARN,"$GSA sentence is not parsed"); + } + } + break; + + case NMEA_SENTENCE_GGA: + { + + if (nmea_parse_gga(&s_gps.frame_gga, p_data)) + { + //LOG(DEBUG,"$GGA: fix quality: %d", s_gps.frame_gga.fix_quality); + on_received_gga(s_gps.frame_gga); + } + else + { + LOG(WARN,"$GGA sentence is not parsed"); + } + } + break; + + + case NMEA_SENTENCE_GSV: + { + if (nmea_parse_gsv(&s_gps.frame_gsv, p_data)) + { + on_received_gsv(s_gps.frame_gsv); + } + else + { + LOG(WARN,"$XXGSV sentence is not parsed"); + } + } + break; + /* + case NMEA_SENTENCE_GST: + { + + if (nmea_parse_gst(&s_gps.frame_gst, p_data)) + { + //LOG(DEBUG,"$GST: raw latitude,longitude and altitude error deviation: (%d/%d,%d/%d,%d/%d)", + //s_gps.frame_gst.latitude_error_deviation.value, s_gps.frame_gst.latitude_error_deviation.scale, + //s_gps.frame_gst.longitude_error_deviation.value, s_gps.frame_gst.longitude_error_deviation.scale, + //s_gps.frame_gst.altitude_error_deviation.value, s_gps.frame_gst.altitude_error_deviation.scale); + //LOG(DEBUG,"$GST fixed point latitude,longitude and altitude error deviation scaled to one decimal place: (%d,%d,%d)", + //nmea_rescale(&s_gps.frame_gst.latitude_error_deviation, 10), + //nmea_rescale(&s_gps.frame_gst.longitude_error_deviation, 10), + //nmea_rescale(&s_gps.frame_gst.altitude_error_deviation, 10)); + //LOG(DEBUG,"$GST floating point degree latitude, longitude and altitude error deviation: (%f,%f,%f)", + //nmea_tofloat(&s_gps.frame_gst.latitude_error_deviation), + //nmea_tofloat(&s_gps.frame_gst.longitude_error_deviation), + //nmea_tofloat(&s_gps.frame_gst.altitude_error_deviation)); + } + else + { + LOG(WARN,"$GST sentence is not parsed"); + } + } + break; + + + + case NMEA_SENTENCE_VTG: + { + + if (nmea_parse_vtg(&s_gps.frame_vtg, p_data)) + { + //LOG(DEBUG,"$VTG: true track degrees = %f",nmea_tofloat(&s_gps.frame_vtg.true_track_degrees)); + //LOG(DEBUG,"magnetic track degrees = %f",nmea_tofloat(&s_gps.frame_vtg.magnetic_track_degrees)); + //LOG(DEBUG,"speed knots = %f",nmea_tofloat(&s_gps.frame_vtg.speed_knots)); + //LOG(DEBUG,"speed kph = %f",nmea_tofloat(&s_gps.frame_vtg.speed_kph)); + } + else + { + //LOG(WARN,"$VTG sentence is not parsed"); + } + } + break; + + + case NMEA_SENTENCE_ZDA: + { + + if (nmea_parse_zda(&s_gps.frame_zda, p_data)) + { + //LOG(DEBUG,"$ZDA: %d:%d:%d %02d.%02d.%d UTC%+03d:%02d", + //s_gps.frame_zda.time.hours, + //s_gps.frame_zda.time.minutes, + //s_gps.frame_zda.time.seconds, + //s_gps.frame_zda.date.day, + //s_gps.frame_zda.date.month, + //s_gps.frame_zda.date.year, + //s_gps.frame_zda.hour_offset, + //s_gps.frame_zda.minute_offset); + } + else + { + LOG(WARN,"$ZDA sentence is not parsed"); + } + } + break; + + case NMEA_SENTENCE_GLL: + { + + if (nmea_parse_gll(&s_gps.frame_gll, p_data)) + { + //LOG(DEBUG,"$GLL: %d:%d:%d latitude:%f,longitude:%f,status:%d,mode:%d", + //s_gps.frame_gll.time.hours, + //s_gps.frame_gll.time.minutes, + //s_gps.frame_gll.time.seconds, + //nmea_tofloat(&s_gps.frame_gll.latitude), + //nmea_tofloat(&s_gps.frame_gll.longitude), + //s_gps.frame_gll.status, + //s_gps.frame_gll.mode); + } + else + { + LOG(WARN,"$GLL sentence is not parsed"); + } + } + break; + */ + + case NMEA_INVALID: + { + LOG(WARN,"Sentence is not valid:len=%d",len); + LOG_HEX(p_data,len); + } + break; + + default: + { + //LOG(DEBUG,"Unknown data:%s",p_data); + //LOG_HEX(p_data,len); + } + break; + } +} + +static void on_received_gga(const NMEASentenceGGA gga) +{ + if (gga.fix_quality == 0) + { + s_gps.is_fix = false; + s_gps.is_3d = false; + s_gps.is_diff = false; + } + //中科微的航迹推算为6 + else if(gga.fix_quality == 1 || gga.fix_quality == 6) + { + s_gps.is_fix = true; + s_gps.is_diff = false; + } + else if(gga.fix_quality == 2) + { + s_gps.is_fix = true; + s_gps.is_diff = true; + } + else + { + LOG(ERROR, "Unknown fix quality:%d", gga.fix_quality); + } + + s_gps.satellites_tracked = gga.satellites_tracked; + s_gps.altitude = nmea_tofloat(&gga.altitude); + s_gps.precision = nmea_tofloat(&gga.hdop); + + check_fix_state_change(); + LOG(DEBUG, "fix_state=%d,tracked=%d,precision=%f", s_gps.state,s_gps.satellites_tracked,s_gps.precision); +} + +static void on_received_gsa(const NMEASentenceGSA gsa) +{ + static U8 is_not_3d_seconds = 0; + if (NMEA_GPGSA_FIX_NONE == gsa.fix_type) + { + is_not_3d_seconds++; + if(is_not_3d_seconds >= SECONDS_PER_MIN) + { + s_gps.is_fix = false; + s_gps.is_3d = false; + s_gps.is_diff = false; + } + } + else if (NMEA_GPGSA_FIX_2D == gsa.fix_type) + { + is_not_3d_seconds++; + if(is_not_3d_seconds >= SECONDS_PER_MIN) + { + s_gps.is_fix = true; + s_gps.is_3d = false; + } + } + else if (NMEA_GPGSA_FIX_3D == gsa.fix_type) + { + s_gps.is_fix = true; + s_gps.is_3d = true; + is_not_3d_seconds = 0; + } + else + { + LOG(WARN, "Unknown fix_type:%d", gsa.fix_type); + } + check_fix_state_change(); + s_gps.precision = nmea_tofloat(&gsa.hdop); +} + +static on_received_gsv(const NMEASentenceGSV gsv) +{ + U8 index_sate = 0; + U8 index_snr = 0; + static U8 satellites_good = 0; + static U8 max_snr = 0; + //信号最好的5颗星 + static SNRInfo snr_array[5] = {{0,0},{0,0},{0,0},{0,0},{0,0}}; + s_gps.satellites_inview = gsv.total_satellites; + + for (index_sate = 0; index_sate < 4; index_sate++) + { + //找出最差的那颗星的位置 + U8 min_snr_index = 0; + U8 min_snr = 0xFF; + for(index_snr = 0;index_snr < SNR_INFO_NUM;index_snr++) + { + if (snr_array[index_snr].snr < min_snr) + { + min_snr = snr_array[index_snr].snr; + min_snr_index = index_snr; + } + } + + //LOG(DEBUG,"min_snr:%d,min_snr_index:%d",min_snr,min_snr_index); + + //如果当前这颗星比之前保存的5颗中最差的一个要好,那么替换掉最差的那个 + if (gsv.satellites[index_sate].snr > min_snr) + { + snr_array[min_snr_index].prn = gsv.satellites[index_sate].nr; + snr_array[min_snr_index].snr = gsv.satellites[index_sate].snr; + } + + if (gsv.satellites[index_sate].snr > 35) + { + satellites_good++; + } + + if (gsv.satellites[index_sate].snr > max_snr) + { + max_snr = gsv.satellites[index_sate].snr; + } + } + + //LOG(DEBUG,"msg_number:%d,total_msgs:%d",gsv.msg_number, gsv.total_msgs); + //最后一条消息,更新可用卫星数和最大信噪比等成员变量,中间变量清零 + if (gsv.msg_number == gsv.total_msgs) + { + s_gps.satellites_good = satellites_good; + satellites_good = 0; + + s_gps.max_snr = max_snr; + max_snr = 0; + //LOG(DEBUG,"$GSV: sattelites in view: %d,satellites_good: %d,max_snr %d", gsv.total_satellites,s_gps.satellites_good,s_gps.max_snr); + + //上个版本用的水平精度因子(和卫星分布有关) + s_gps.signal_intensity_grade = s_gps.max_snr/10; + if (s_gps.signal_intensity_grade > 4) + { + s_gps.signal_intensity_grade = 4; + } + GM_memcpy(s_gps.snr_array, snr_array, sizeof(snr_array)); + GM_memset(snr_array, 0, sizeof(snr_array)); + } +} + +static void check_fix_state_change(void) +{ + U8 fix_time_min = (GM_GPS_TYPE_MTK_EPO == s_gps.gpsdev_type ? 2 : 10); + GM_CHANGE_ENUM change = util_check_state_change(s_gps.is_3d,&s_gps.state_record,fix_time_min,20); + + if (GM_CHANGE_TRUE == change) + { + JsonObject* p_log_root = json_create(); + char snr_str[128] = {0}; + + s_gps.internal_state = GM_GPS_STATE_WORKING; + + if(0 == s_gps.fix_time) + { + s_gps.fix_time = util_clock() - s_gps.power_on_time; + json_add_string(p_log_root, "event", "fixed"); + json_add_int(p_log_root, "AGPS time", s_gps.agps_time); + //距离上次休眠到现在超过6小时或者没有休眠过是冷启动,否则是热启动 + if((util_clock() - s_gps.sleep_time) > 6*SECONDS_PER_HOUR || 0 == s_gps.sleep_time) + { + json_add_int(p_log_root, "cold fix_time", s_gps.fix_time); + LOG(INFO,"cold fix_time:%d",s_gps.fix_time); + } + else + { + json_add_int(p_log_root, "hot fix_time", s_gps.fix_time); + LOG(INFO,"hot fix_time:%d",s_gps.fix_time); + } + } + else + { + json_add_string(p_log_root, "event", "become to fixed"); + } + + json_add_int(p_log_root, "satellites_in_view", s_gps.satellites_inview); + json_add_int(p_log_root, "satellites_good", s_gps.satellites_good); + json_add_int(p_log_root, "satellites_tracked", s_gps.satellites_tracked); + + GM_snprintf(snr_str,128,"%03d:%02d,%03d:%02d,%03d:%02d,%03d:%02d,%03d:%02d,", + s_gps.snr_array[0].prn,s_gps.snr_array[0].snr, + s_gps.snr_array[1].prn,s_gps.snr_array[1].snr, + s_gps.snr_array[2].prn,s_gps.snr_array[2].snr, + s_gps.snr_array[3].prn,s_gps.snr_array[3].snr, + s_gps.snr_array[4].prn,s_gps.snr_array[4].snr); + + json_add_string(p_log_root, "snr", snr_str); + json_add_int(p_log_root, "csq", gsm_get_csq()); + log_service_upload(INFO, p_log_root); + + + + led_set_gps_state(GM_LED_ON); + s_gps.state = (GPSState)(s_gps.is_fix << 2 | (s_gps.is_3d << 1) | (s_gps.is_diff)); + } + else if(GM_CHANGE_FALSE == change) + { + JsonObject* p_log_root = json_create(); + char snr_str[128] = {0}; + json_add_string(p_log_root, "event", "become to unfixed"); + json_add_int(p_log_root, "satellites_in_view", s_gps.satellites_inview); + json_add_int(p_log_root, "satellites_good", s_gps.satellites_good); + json_add_int(p_log_root, "satellites_tracked", s_gps.satellites_tracked); + + GM_snprintf(snr_str,128,"%03d:%02d,%03d:%02d,%03d:%02d,%03d:%02d,%03d:%02d,", + s_gps.snr_array[0].prn,s_gps.snr_array[0].snr, + s_gps.snr_array[1].prn,s_gps.snr_array[1].snr, + s_gps.snr_array[2].prn,s_gps.snr_array[2].snr, + s_gps.snr_array[3].prn,s_gps.snr_array[3].snr, + s_gps.snr_array[4].prn,s_gps.snr_array[4].snr); + + json_add_string(p_log_root, "snr", snr_str); + json_add_int(p_log_root, "csq", gsm_get_csq()); + log_service_upload(INFO, p_log_root); + + led_set_gps_state(GM_LED_FLASH); + s_gps.state = (GPSState)(s_gps.is_fix << 2 | (s_gps.is_3d << 1) | (s_gps.is_diff)); + } + else + { + + } + +} +static void on_received_rmc(const NMEASentenceRMC rmc) +{ + GPSData gps_data = {0}; + U8 index = 0; + float lat_avg = 0; + float lng_avg = 0; + float speed_avg = 0; + + time_t seconds_from_reboot = util_clock(); + + if (s_gps.state < GM_GPS_FIX_3D) + { + return; + } + + if (seconds_from_reboot - s_gps.save_time >= 1) + { + bool if_smooth_track = false; + gps_data.gps_time = nmea_get_utc_time(&rmc.date,&rmc.time); + gps_data.lat = nmea_tocoord(&rmc.latitude); + gps_data.lng = nmea_tocoord(&rmc.longitude); + gps_data.speed = util_mile_to_km(nmea_tofloat(&rmc.speed)); + //判断角度是否有效,如果无效取上一个点的角度 + if (0 == rmc.course.value && 0 == rmc.course.scale) + { + GPSData last_gps_data = {0}; + if(gps_get_last_data(&last_gps_data)) + { + gps_data.course = last_gps_data.course; + } + else + { + gps_data.course = 0; + } + } + else + { + gps_data.course = nmea_tofloat(&rmc.course); + } + gps_data.satellites = s_gps.satellites_tracked; + gps_data.precision = s_gps.precision; + gps_data.signal_intensity_grade = s_gps.signal_intensity_grade; + + //检查异常数据 + if (0 == gps_data.gps_time || false == rmc.valid) + { + return; + } + + if (fabs(gps_data.lat) < 0.1 && fabs(gps_data.lng) < 0.1) + { + return; + } + + calc_alcr_by_speed(gps_data); + check_over_speed_alarm(gps_data.speed); + + + s_gps.save_time = seconds_from_reboot; + + circular_queue_en_queue_i(&s_gps.gps_time_queue,gps_data.gps_time); + circular_queue_en_queue_f(&s_gps.gps_lat_queue,gps_data.lat); + circular_queue_en_queue_f(&s_gps.gps_lng_queue, gps_data.lng); + circular_queue_en_queue_f(&s_gps.gps_speed_queue,gps_data.speed); + circular_queue_en_queue_f(&s_gps.gps_course_queue,gps_data.course); + + config_service_get(CFG_SMOOTH_TRACK, TYPE_BOOL, &if_smooth_track, sizeof(if_smooth_track)); + if(if_smooth_track) + { + LOG(DEBUG,"smooth track"); + //取前10秒(包括当前时间点)平均值 + for(index = 0;index < 10;index++) + { + time_t last_n_time = 0; + float last_n_lat = 0; + float last_n_lng = 0; + float last_n_speed = 0; + + if(false == circular_queue_get_by_index_i(&s_gps.gps_time_queue,index,(S32*)&last_n_time)) + { + break; + } + if (gps_data.gps_time - last_n_time >= 10) + { + break; + } + circular_queue_get_by_index_f(&s_gps.gps_lat_queue,index,&last_n_lat); + circular_queue_get_by_index_f(&s_gps.gps_lng_queue, index,&last_n_lng); + circular_queue_get_by_index_f(&s_gps.gps_speed_queue,index,&last_n_speed); + + lat_avg = (lat_avg*index + last_n_lat)/(index + 1); + lng_avg = (lng_avg*index + last_n_lng)/(index + 1); + speed_avg = (speed_avg*index + last_n_speed)/(index + 1); + } + gps_data.lat = lat_avg; + gps_data.lng = lng_avg; + gps_data.speed = speed_avg; + } + upload_gps_data(gps_data); + } +} + +//每1秒调用一次 +static void calc_alcr_by_speed(GPSData gps_info) +{ + float last_second_speed = 0; + float aclr_calculate_by_speed = 0; + + if (gps_info.speed >= MIN_CRUISE_SPEED) + { + s_gps.constant_speed_time++; + s_gps.static_speed_time = 0; + if (circular_queue_get_tail_f(&(s_gps.gps_speed_queue), &last_second_speed)) + { + aclr_calculate_by_speed = (gps_info.speed - last_second_speed) * 1000.0 / SECONDS_PER_HOUR; + s_gps.aclr_avg_calculate_by_speed = (s_gps.aclr_avg_calculate_by_speed * (s_gps.constant_speed_time - 1) + aclr_calculate_by_speed) / (s_gps.constant_speed_time); + } + } + else + { + s_gps.constant_speed_time = 0; + s_gps.static_speed_time++; + s_gps.aclr_avg_calculate_by_speed = 0; + } + +} + +static void check_over_speed_alarm(float speed) +{ + bool speed_alarm_enable = false; + U8 speed_threshold = 0; + U8 speed_check_time = 0; + GM_CHANGE_ENUM state_change = GM_NO_CHANGE; + AlarmInfo alarm_info; + alarm_info.type = ALARM_SPEED; + alarm_info.info = speed; + + config_service_get(CFG_SPEED_ALARM_ENABLE, TYPE_BOOL, &speed_alarm_enable, sizeof(speed_alarm_enable)); + config_service_get(CFG_SPEEDTHR, TYPE_BYTE, &speed_threshold, sizeof(speed_threshold)); + config_service_get(CFG_SPEED_CHECK_TIME, TYPE_BYTE, &speed_check_time, sizeof(speed_check_time)); + + if(!speed_alarm_enable) + { + return; + } + + state_change = util_check_state_change(speed > speed_threshold, &s_gps.over_speed_alarm_state, speed_check_time, speed_check_time); + if(GM_CHANGE_TRUE == state_change) + { + system_state_set_overspeed_alarm(true); + gps_service_push_alarm(&alarm_info); + } + else if(GM_CHANGE_FALSE == state_change) + { + system_state_set_overspeed_alarm(false); + } + else + { + + } +} + +time_t gps_get_constant_speed_time(void) +{ + return s_gps.constant_speed_time; +} + +float gps_get_aclr(void) +{ + return s_gps.aclr_avg_calculate_by_speed; +} + +static GpsDataModeEnum upload_mode(const GPSData current_gps_data) +{ + GM_ERRCODE err_code = GM_SUCCESS; + U32 seconds_from_reboot = util_clock(); + U16 upload_time_interval = 0; + bool static_upload_enable = false; + + err_code = config_service_get(CFG_UPLOADTIME, TYPE_SHORT, &upload_time_interval, sizeof(upload_time_interval)); + if (GM_SUCCESS != err_code) + { + LOG(ERROR, "Failed to config_service_get(CFG_UPLOADTIME),err_code=%d", err_code); + return GPS_MODE_NONE; + } + + if(false == system_state_has_reported_gps_since_boot()) + { + system_state_set_has_reported_gps_since_boot(true); + s_gps.distance_since_last_report = 0; + s_gps.report_time = seconds_from_reboot; + return GPS_MODE_POWER_UP; + } + + if(false == system_state_has_reported_gps_since_modify_ip()) + { + system_state_set_reported_gps_since_modify_ip(true); + s_gps.distance_since_last_report = 0; + s_gps.report_time = seconds_from_reboot; + return GPS_MODE_POWER_UP; + } + + config_service_get(CFG_IS_STATIC_UPLOAD, TYPE_BOOL, &static_upload_enable, sizeof(static_upload_enable)); + if (VEHICLE_STATE_STATIC == system_state_get_vehicle_state() && false == static_upload_enable && false == config_service_is_test_mode()) + { + LOG(DEBUG, "Need not upload data because of static."); + return GPS_MODE_NONE; + } + else + { + if ((seconds_from_reboot - s_gps.report_time) >= upload_time_interval) + { + s_gps.distance_since_last_report = 0; + s_gps.report_time = seconds_from_reboot; + if(VEHICLE_STATE_STATIC == system_state_get_vehicle_state()) + { + return GPS_MODE_STATIC_POSITION; + } + else + { + return GPS_MODE_FIX_TIME; + } + + } + else if (is_turn_point(current_gps_data)) + { + s_gps.distance_since_last_report = 0; + s_gps.report_time = seconds_from_reboot; + LOG(DEBUG, "GPS_MODE_TURN_POINT"); + return GPS_MODE_TURN_POINT; + } + else + { + return GPS_MODE_NONE; + } + } +} + +static void upload_gps_data(const GPSData current_gps_data) +{ + GM_ERRCODE ret = GM_SUCCESS; + GpsDataModeEnum mode = upload_mode(current_gps_data); + ST_Time st_time = {0}; + struct tm tm_time = {0}; + + static GPSData last_report_gps = {0}; + + if(false == s_gps.push_data_enbale) + { + LOG(WARN,"do not push data!"); + return; + } + + if (0 == current_gps_data.gps_time) + { + LOG(WARN,"Invalid GPS data!"); + return; + } + + if (GPS_MODE_NONE == mode) + { + return; + } + + if (GPS_MODE_POWER_UP == mode) + { + tm_time = util_gmtime(current_gps_data.gps_time); + util_tm_to_mtktime(&tm_time,&st_time); + GM_SetLocalTime(&st_time); + LOG(INFO,"Set local time:(%d-%02d-%02d %02d:%02d:%02d)).",st_time.year,st_time.month,st_time.day,st_time.hour,st_time.minute,st_time.second); + } + + ret = gps_service_push_gps(mode,¤t_gps_data); + + if (last_report_gps.gps_time != 0) + { + s_gps.distance_since_last_report = applied_math_get_distance(current_gps_data.lng, current_gps_data.lat, last_report_gps.lng, last_report_gps.lat); + system_state_set_mileage(system_state_get_mileage() + s_gps.distance_since_last_report); + } + + last_report_gps = current_gps_data; + + + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to gps_service_push_gps,ret=%d", ret); + return; + } +} + +static bool is_turn_point(const GPSData current_gps_data) +{ + U16 course_change_threshhold = 0; + float course_change = 0; + float current_course = current_gps_data.course; + float last_second_course = 0; + float last_speed = 0; + GM_ERRCODE ret = GM_SUCCESS; + U8 index = 0; + + ret = config_service_get(CFG_TURN_ANGLE, TYPE_SHORT, &course_change_threshhold, sizeof(course_change_threshhold)); + if(GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to config_service_get(CFG_TURN_ANGLE),ret=%d", ret); + return false; + } + + if(!circular_queue_get_by_index_f(&s_gps.gps_course_queue, 1, &last_second_course)) + { + return false; + } + + course_change = applied_math_get_angle_diff(current_course,last_second_course); + LOG(DEBUG,"[%s]:current course:%f,last second course:%f,course change:%f",__FUNCTION__,current_course,last_second_course,course_change); + + if (current_gps_data.speed >= 80.0f) + { + if (course_change >= ((s_gps.gpsdev_type == GM_GPS_TYPE_TD_AGPS) ? 10 : 6)) + { + return true; + } + else if (course_change >= course_change_threshhold) + { + return true; + } + else + { + return false; + } + } + else if (current_gps_data.speed >= 40.0f) + { + if (course_change >= ((s_gps.gpsdev_type == GM_GPS_TYPE_TD_AGPS) ? 11 : 7)) + { + return true; + } + else if (course_change >= course_change_threshhold) + { + return true; + } + else + { + return false; + } + } + else if (current_gps_data.speed >= 25.0f) + { + if (course_change >= ((s_gps.gpsdev_type == GM_GPS_TYPE_TD_AGPS) ? 12 : 8)) + { + return true; + } + else if (course_change >= course_change_threshhold) + { + return true; + } + else + { + return false; + } + } + else if (current_gps_data.speed >= 15.0f) + { + if (course_change >= ((s_gps.gpsdev_type == GM_GPS_TYPE_TD_AGPS) ? course_change_threshhold : (course_change_threshhold - 6))) + { + return true; + } + else + { + return false; + } + } + else if ((current_gps_data.speed >= 5.0f) && (course_change >= ((s_gps.gpsdev_type == GM_GPS_TYPE_TD_AGPS) ? 20 : 16)) && (s_gps.distance_since_last_report > 20.0f)) + { + // 连续5秒速度大于5KMH,角度大于20度,里程超过20米,上传拐点 + for (index =0; index < 5; index++) + { + if(!circular_queue_get_by_index_f(&s_gps.gps_speed_queue, index, &last_speed)) + { + return false; + } + if (last_speed <= 5.0f) + { + return false; + } + } + return true; + } + else + { + return false; + } +} + + + +//查询MTK版本号 +static void query_mtk_version(void) +{ + bool create_ret = false; + GM_ERRCODE write_ret = GM_SUCCESS; + + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + + //已经查到了版本号 + if (s_gps.internal_state > GM_GPS_STATE_WAIT_VERSION) + { + return; + } + else + { + GM_StartTimer(GM_TIMER_GPS_QUERY_MTK_VERSION, TIM_GEN_1SECOND*1, query_mtk_version); + } + + create_ret = nmea_creat_mtk_qeury_version_sentence(sentence, &len); + if (false == create_ret || 0 == len) + { + LOG(ERROR, "Failed to nmea_creat_mtk_qeury_version_sentence!"); + return; + } + write_ret = uart_write(GM_UART_GPS, sentence, len); + if (GM_SUCCESS != write_ret) + { + LOG(ERROR, "Failed to write to GPS UART,ret=%d!",write_ret); + } + else + { + LOG(DEBUG,"Send query_mtk_version cmd:%s",sentence); + } +} + +//知道9600波特率能收到数据,查询泰斗和中科微版本号 +static void query_td_and_at_version(void) +{ + bool create_ret = false; + GM_ERRCODE write_ret = GM_SUCCESS; + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + + //已经查到了版本号 + if (s_gps.internal_state > GM_GPS_STATE_WAIT_VERSION) + { + return; + } + else + { + GM_StartTimer(GM_TIMER_GPS_QUERY_TD_AT_VERSION, TIM_GEN_1SECOND*1, query_td_and_at_version); + } + + create_ret = nmea_creat_td_qeury_version_sentence(sentence, &len); + if (false == create_ret || 0 == len) + { + LOG(ERROR, "Failed to nmea_creat_td_qeury_version_sentence!"); + return; + } + write_ret = uart_write(GM_UART_GPS, sentence, len); + if (GM_SUCCESS != write_ret) + { + LOG(ERROR, "Failed to write to GPS UART,ret=%d!",write_ret); + } + + create_ret = false; + write_ret = GM_SUCCESS; + + GM_memset(sentence, 0, SENTENCE_MAX_LENGTH); + len = SENTENCE_MAX_LENGTH; + create_ret = nmea_creat_at_qeury_version_sentence(sentence, &len); + if (false == create_ret || 0 == len) + { + LOG(ERROR, "Failed to nmea_creat_at_qeury_version_sentence!"); + return; + } + write_ret = uart_write(GM_UART_GPS, sentence, len); + if (GM_SUCCESS != write_ret) + { + LOG(ERROR, "Failed to write to GPS UART,ret=%d!",write_ret); + } +} + +static void query_td_version(void) +{ + bool create_ret = false; + GM_ERRCODE write_ret = GM_SUCCESS; + + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + + //已经查到了版本号 + if (s_gps.internal_state > GM_GPS_STATE_WAIT_VERSION) + { + return; + } + else + { + GM_StartTimer(GM_TIMER_GPS_QUERY_TD_VERSION, TIM_GEN_1SECOND*1, query_td_version); + } + + create_ret = nmea_creat_td_qeury_version_sentence(sentence, &len); + if (false == create_ret || 0 == len) + { + LOG(ERROR, "Failed to nmea_creat_td_qeury_version_sentence!"); + return; + } + write_ret = uart_write(GM_UART_GPS, sentence, len); + if (GM_SUCCESS != write_ret) + { + LOG(ERROR, "Failed to write to GPS UART,ret=%d!",write_ret); + } +} + +static void query_at_version(void) +{ + bool create_ret = false; + GM_ERRCODE write_ret = GM_SUCCESS; + + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + + //已经查到了版本号 + if (s_gps.internal_state > GM_GPS_STATE_WAIT_VERSION) + { + return; + } + else + { + GM_StartTimer(GM_TIMER_GPS_QUERY_AT_VERSION, TIM_GEN_1SECOND*1, query_at_version); + } + + create_ret = nmea_creat_at_qeury_version_sentence(sentence, &len); + if (false == create_ret || 0 == len) + { + LOG(ERROR, "Failed to nmea_creat_at_qeury_version_sentence!"); + return; + } + write_ret = uart_write(GM_UART_GPS, sentence, len); + if (GM_SUCCESS != write_ret) + { + LOG(ERROR, "Failed to write to GPS UART,ret=%d!",write_ret); + } +} + +static GM_ERRCODE write_mtk_epo_time(const ST_Time utc_time) +{ + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + nmea_creat_mtk_aid_time_sentence(utc_time,sentence,&len); + LOG(DEBUG,"write_mtk_epo_time:%s",sentence); + return uart_write(GM_UART_GPS, sentence, len); +} + +static void write_mtk_epo_pos(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + nmea_creat_mtk_aid_pos_sentence(s_gps.ref_lat,s_gps.ref_lng,sentence,&len); + LOG(DEBUG,"write_mtk_epo_pos:%s",sentence); + ret = uart_write(GM_UART_GPS, sentence, len); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to write data to GM_UART_GPS,ret=%d",ret); + } +} + +static void write_mtk_full_cold_start(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + nmea_creat_mtk_full_cold_start_sentence(sentence,&len); + LOG(DEBUG,"write_mtk_full_cold_start:%s",sentence); + ret = uart_write(GM_UART_GPS, sentence, len); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to write data to GM_UART_GPS,ret=%d",ret); + } +} + +static void write_mtk_cold_start(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + nmea_creat_mtk_cold_start_sentence(sentence,&len); + LOG(DEBUG,"write_mtk_cold_start:%s",sentence); + ret = uart_write(GM_UART_GPS, sentence, len); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to write data to GM_UART_GPS,ret=%d",ret); + } +} + +/* +static void write_mtk_high_accuracy(bool enable) +{ + GM_ERRCODE ret = GM_SUCCESS; + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + nmea_creat_high_accuracy_sentence(enable,sentence,&len); + LOG(DEBUG,"write_mtk_high_accuracy:%s",sentence); + ret = uart_write(GM_UART_GPS, sentence, len); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to write data to GM_UART_GPS,ret=%d",ret); + } +}*/ + +void gps_write_mtk_cmd(const char* cmd) +{ + GM_ERRCODE ret = GM_SUCCESS; + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + nmea_create_common_mtk_sentence(cmd,sentence); + LOG(DEBUG,"gps_write_mtk_cmd:%s",sentence); + ret = uart_write(GM_UART_GPS, sentence, GM_strlen((char*)sentence)); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to write data to GM_UART_GPS,ret=%d",ret); + } +} + +/*static void write_set_min_snr(const U8 min_snr) +{ + GM_ERRCODE ret = GM_SUCCESS; + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + nmea_creat_set_min_snr_sentence(min_snr,sentence,&len); + LOG(DEBUG,"write_set_min_snr:%s",sentence); + ret = uart_write(GM_UART_GPS, sentence, len); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to write data to GM_UART_GPS,ret=%d",ret); + } +}*/ + +static void open_td_vtg(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + + //已经打开 + if (true == s_gps.has_opened_td_vtg) + { + return; + } + else + { + GM_StartTimer(GM_TIMER_GPS_OPEN_TD_VTG, TIM_GEN_1SECOND*1, open_td_vtg); + } + + nmea_creat_td_open_vtg_sentence(sentence,&len); + ret = uart_write(GM_UART_GPS, sentence, len); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to write data to GM_UART_GPS,ret=%d",ret); + } +} + +static GM_ERRCODE write_td_agps_time(const ST_Time utc_time,const U8 leap_sencond) +{ + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + nmea_creat_td_aid_time_sentence(utc_time,leap_sencond,sentence,&len); + LOG(INFO,"write_td_agps_time:len=%d",len); + LOG_HEX((char*)sentence,len); + return uart_write(GM_UART_GPS, sentence, len); +} + +static void write_td_agps_pos(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + nmea_creat_td_aid_pos_sentence(s_gps.ref_lat,s_gps.ref_lng,sentence,&len); + ret = uart_write(GM_UART_GPS, sentence, len); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to write data to GM_UART_GPS,ret=%d",ret); + } +} + +static GM_ERRCODE write_at_agps_info(const ST_Time utc_time,const U8 leap_sencond,const float ref_lat,const float ref_lng) +{ + U8 sentence[SENTENCE_MAX_LENGTH] = {0}; + U8 len = SENTENCE_MAX_LENGTH; + nmea_creat_at_aid_info_sentence(utc_time, leap_sencond, ref_lat, ref_lng,sentence,&len); + return uart_write(GM_UART_GPS, sentence, len); +} + diff --git a/src/gps_save.c b/src/gps_save.c new file mode 100644 index 0000000..3913eb6 --- /dev/null +++ b/src/gps_save.c @@ -0,0 +1,693 @@ +#include "gps_save.h" +#include +#include "gm_stdlib.h" +#include "gm_memory.h" +#include "log_service.h" +#include "gm_fs.h" +#include "utility.h" + +typedef struct // 6460 +{ + int handle; // file handle + u16 record_num; // total records in file +}HisDatFileType; + +#define CLOSE_FILE_HANDLE( handle ) \ +{ \ + if((handle) >= 0) \ + { \ + GM_FS_Close((handle)); \ + (handle) = -1; \ + } \ +} + +static HisDatFileType s_his_dat; /* 对应历史文件数据 */ + +static LocationCurData s_gps_data = {NULL, 0, 0, 0}; +static LocationCurData s_gps_sending = {NULL, 0, 0, 0}; + +static GM_ERRCODE gps_data_init(LocationCurData *pdata, HisDatFileType *phis, u16 size, bool read_from_file); +static u16 gps_data_get_len(LocationCurData *pdata); +static u16 gps_data_get_free_size(LocationCurData *pdata); +static GM_ERRCODE gps_data_peek_one(LocationCurData *pdata, HisDatFileType *phis, LocationSaveData *one, bool from_head); +static GM_ERRCODE gps_data_commit_peek(LocationCurData *pdata, HisDatFileType *phis,bool from_head,bool write_log); +static void gps_data_save_to_history_file(LocationCurData *pdata, HisDatFileType *phis); + + +static void gps_his_file_delete(HisDatFileType *phis); +static u32 gps_his_file_write_head(HisDatFileType *phis, u8 *head_buff); +static void gps_his_file_delete_record(HisDatFileType *phis, u16 del_num); +static void gps_data_release(LocationSaveData *one); +static u32 gps_his_file_write(HisDatFileType *phis, void * DataPtr, UINT Length, int Offset); +static GM_ERRCODE gps_his_file_create(HisDatFileType *phis); +static u32 gps_his_file_read(HisDatFileType *phis, void * DataPtr, UINT Length, int Offset); +static GM_ERRCODE gps_data_save_file(LocationCurData *pdata, HisDatFileType *phis); +static GM_ERRCODE gps_data_read_file(LocationCurData *pdata, HisDatFileType *phis,bool read_from_file); + +/*add to tail*/ +static GM_ERRCODE gps_data_insert_one(LocationCurData *pdata, HisDatFileType *phis, u8 *data, u8 len, bool log); + + + +GM_ERRCODE gps_data_init(LocationCurData *pdata, HisDatFileType *phis, u16 size, bool read_from_file) +{ + // the last block have to empty to keep read==write means empty. + size +=1; + + /* allocate gps space. */ + pdata->his = (LocationSaveData *) GM_MemoryAlloc(size * sizeof(LocationSaveData)); + if (pdata->his == NULL) + { + LOG(WARN,"gps_data_init(%p,%p) assert(GM_MemoryAlloc(%d) failed", pdata,phis, size * sizeof(LocationSaveData)); + return GM_MEM_NOT_ENOUGH; + } + + GM_memset((u8 *)pdata->his, 0x00, sizeof(LocationSaveData) * size); + + pdata->read_idx = 0; + pdata->write_idx = 0; + pdata->size = size; + + if(phis) + { + phis->handle = -1; + phis->record_num = 0; + + //if file exist, read from history file. + gps_data_read_file(pdata,phis,read_from_file); + } + + return GM_SUCCESS; +} + + +u16 gps_data_get_len(LocationCurData *pdata) +{ + int read_point = 0; + int write_point = 0; + int LeftDataSize = 0; + + read_point = pdata->read_idx; + write_point = pdata->write_idx; + + LeftDataSize = write_point - read_point; + if(LeftDataSize < 0) + { + LeftDataSize += pdata->size; + } + + return (u16)LeftDataSize; +} + + +u16 gps_data_get_free_size(LocationCurData *pdata) +{ + // the last block have to empty to keep read==write means empty. + return (pdata->size - gps_data_get_len(pdata)) - 1; +} + + +void gps_data_save_to_history_file(LocationCurData *pdata, HisDatFileType *phis) +{ + if(gps_data_get_len(pdata) > 0) + { + gps_data_save_file(pdata, phis); + } +} + + + +GM_ERRCODE gps_data_insert_one(LocationCurData *pdata, HisDatFileType *phis, u8 *data, u8 len, bool log) +{ + int read_point = 0; + int write_point = 0; + int write_idx; + + read_point = pdata->read_idx; + write_idx = write_point = pdata->write_idx; + write_point ++; + + if(write_point >= pdata->size) + { + write_point -= (int)pdata->size; + } + + if(write_point == read_point) + { + return GM_MEM_NOT_ENOUGH; + } + + pdata->his[write_idx].buf = (u8 *)GM_MemoryAlloc(len); + if(NULL == pdata->his[write_idx].buf) + { + LOG(WARN,"gps_data_init(%p,%p) assert(GM_MemoryAlloc(%d) failed",pdata, phis, len); + return GM_SYSTEM_ERROR; + } + + pdata->his[write_idx].len = len; + GM_memcpy(pdata->his[write_idx].buf, data, len); + + pdata->write_idx = write_point; + + if(log) // when read form file , no need log + { + LOG(DEBUG,"clock(%d) gps_data_insert_one(%p,%p)(r:%d,w:%d,size:%d, len:%d) his_num(%d).", util_clock(), + pdata,phis,pdata->read_idx,pdata->write_idx,pdata->size,len,(phis?phis->record_num:0)); + } + return GM_SUCCESS; +} + + +GM_ERRCODE gps_data_peek_one(LocationCurData *pdata, HisDatFileType *phis, LocationSaveData *one, bool from_head) +{ + int read_point = 0; + int write_point = 0; + int idx; + + if(pdata->his == NULL) + { + return GM_EMPTY_BUF; + } + + + read_point = pdata->read_idx; + write_point = pdata->write_idx; + + + if(write_point == read_point) + { + if((! from_head) && (phis != 0) && phis->record_num > 0) + { + //从尾部拿最新的gps数据的情况,只发生在发送数据给平台时, + //这时如果无数据,要补发历史数据 + if(GM_SUCCESS == gps_data_read_file(pdata, phis, true)) + { + return gps_data_peek_one(pdata, phis, one, from_head); + } + } + return GM_EMPTY_BUF; + } + + //data is between read_idx(include) and write_idx(not include) + write_point --; + if(write_point < 0) + { + write_point += (int)pdata->size; + } + + idx = from_head ? read_point : write_point; + + *one = pdata->his[idx]; + + return GM_SUCCESS; +} + + +GM_ERRCODE gps_data_commit_peek(LocationCurData *pdata, HisDatFileType *phis,bool from_head,bool write_log) +{ + int read_point = 0; + int write_point = 0; + int idx = 0; + int len = 0; + + read_point = pdata->read_idx; + write_point = pdata->write_idx; + + if(write_point == read_point) + { + return GM_EMPTY_BUF; + } + + if(from_head) + { + //删除头部一个元素 + idx = read_point; + read_point ++; + len = pdata->his[idx].len; + gps_data_release(&pdata->his[idx]); + if(read_point >= pdata->size) + { + read_point -= (int)pdata->size; + } + pdata->read_idx = read_point; + } + else + { + //data is between read_idx(include) and write_idx(not include) + write_point --; + if(write_point < 0) + { + write_point += (int)pdata->size; + } + idx = write_point; + len = pdata->his[idx].len; + gps_data_release(&pdata->his[idx]); + pdata->write_idx = write_point; + } + + if(write_log) + { + LOG(DEBUG,"clock(%d) gps_data_commit_peek(%p,%p)(r:%d,w:%d,size:%d, len:%d, from_head:%d) his_num(%d).", util_clock(), + pdata,phis,pdata->read_idx,pdata->write_idx,pdata->size,len,from_head,(phis?phis->record_num:0)); + } + return GM_SUCCESS; +} + + + + +static void gps_data_release(LocationSaveData *one) +{ + if(one && one->buf) + { + GM_MemoryFree(one->buf); + one->buf = NULL; + one->len = 0; + } +} + +void gps_his_file_delete(HisDatFileType *phis) +{ + int ret = -1; + + CLOSE_FILE_HANDLE(phis->handle) + + ret = GM_FS_CheckFile(GOOME_HIS_FILE); + if (ret >= 0) + { + GM_FS_Delete(GOOME_HIS_FILE); + LOG(INFO,"clock(%d) gps_his_file_delete", util_clock()); + } +} + +/* +文件没打开, 则打开文件, 并写入数据, 文件不会被关闭. +出错的情况下, 文件会被关闭 +*/ +static u32 gps_his_file_write(HisDatFileType *phis, void * DataPtr, UINT Length, int Offset) +{ + u32 fs_len = 0; + int ret = -1; + + if(phis->handle < 0) + { + phis->handle = GM_FS_Open(GOOME_HIS_FILE, GM_FS_READ_WRITE | GM_FS_ATTR_ARCHIVE | GM_FS_CREATE); + if (phis->handle < 0) + { + LOG(INFO,"goome_his_file_write-open fail return[%d]", phis->handle); + phis->handle = -1; + return 0; + } + LOG(DEBUG,"clock(%d) gps_his_file_write open or create file", util_clock()); + } + + GM_FS_Seek(phis->handle, Offset, 0); + ret = GM_FS_Write(phis->handle, DataPtr, Length, &fs_len); + if (ret < 0) + { + LOG(INFO,"goome_his_file_write-write fail return[%d]", ret); + CLOSE_FILE_HANDLE(phis->handle) + return 0; + } + + GM_FS_Commit(phis->handle); + + return fs_len; +} + + +/*文件一定会被删除, handle一定会被关掉, 再重新打开*/ +static GM_ERRCODE gps_his_file_create(HisDatFileType *phis) +{ + u8 file_head[20]; + + gps_his_file_delete(phis); + + GM_memset(file_head, 0x00, sizeof(file_head)); + file_head[0] = (HIS_FILE_HEAD_FLAG >> 24) & 0xFF; + file_head[1] = (HIS_FILE_HEAD_FLAG >> 16) & 0xFF; + file_head[2] = (HIS_FILE_HEAD_FLAG >> 8) & 0xFF; + file_head[3] = (HIS_FILE_HEAD_FLAG ) & 0xFF; + + if (HIS_FILE_OFFSET_CNT == gps_his_file_write(phis, (void *)&file_head, HIS_FILE_OFFSET_CNT, 0)) + { + LOG(INFO,"gps_his_file_create ok"); + phis->record_num = 0; + return GM_SUCCESS; + } + else + { + LOG(INFO,"gps_his_file_create failed"); + CLOSE_FILE_HANDLE(phis->handle) + return GM_SYSTEM_ERROR; + } +} + + +static u32 gps_his_file_read(HisDatFileType *phis, void * DataPtr, UINT Length, int Offset) +{ + u32 fs_len = 0; + int ret = -1; + + if(phis->handle < 0) + { + phis->handle = GM_FS_Open(GOOME_HIS_FILE, GM_FS_READ_WRITE | GM_FS_ATTR_ARCHIVE); + if (phis->handle < 0) + { + LOG(DEBUG,"gps_his_file_read open failed, return [%d]",phis->handle); + phis->handle = -1; + return 0; + } + LOG(DEBUG,"clock(%d) gps_his_file_read open file", util_clock()); + } + + GM_FS_Seek(phis->handle, Offset, 0); + ret = GM_FS_Read(phis->handle, DataPtr, Length, &fs_len); + if (ret < 0) + { + LOG(INFO,"gps_his_file_read failed, ret[%d]",ret); + CLOSE_FILE_HANDLE(phis->handle) + return 0; + } + + GM_FS_Commit(phis->handle); + + return fs_len; +} + + +/*将pdata缓存中的内容添加到文件后面*/ +static GM_ERRCODE gps_data_save_file(LocationCurData *pdata, HisDatFileType *phis) +{ + u8 head_buff[20]; + u8 one_frame[HIS_FILE_FRAME_SIZE]; + LocationSaveData one; + u16 fs_len = 0; + u16 write_len = 0; + + GM_memset(head_buff, 0x00, sizeof(head_buff)); + fs_len = gps_his_file_read(phis, (void *)&head_buff, HIS_FILE_OFFSET_CNT, 0); + if ((HIS_FILE_OFFSET_CNT != fs_len) || (HIS_FILE_HEAD_FLAG != MKDWORD(head_buff[0], head_buff[1], head_buff[2], head_buff[3]))) + { + if (GM_SUCCESS != gps_his_file_create(phis)) + { + //创建文件失败 + return GM_SYSTEM_ERROR; + } + } + else + { + phis->record_num = MKWORD(head_buff[4], head_buff[5]); + } + + while(GM_SUCCESS == gps_data_peek_one(pdata, phis, &one, 1)) + { + if(SAVE_HIS_MAX_NUM <= phis->record_num) + { + LOG(INFO,"gps_data_save_file SAVE_HIS_MAX_NUM reached."); + + //淘汰最旧的数据 + gps_his_file_delete_record(phis, gps_data_get_len(pdata)); + } + + one_frame[0] = one.len; + if(one.len >= HIS_FILE_FRAME_SIZE) + { + LOG(ERROR,"gps_data_save_file assert(len(%d)) failed.", one.len); + break; + } + + GM_memcpy(&one_frame[1], one.buf,one.len); + write_len = gps_his_file_write(phis, one_frame, HIS_FILE_FRAME_SIZE, phis->record_num*HIS_FILE_FRAME_SIZE + HIS_FILE_OFFSET_CNT); + if(write_len == HIS_FILE_FRAME_SIZE) + { + phis->record_num ++; + gps_data_commit_peek(pdata, phis, true, true); + } + else + { + LOG(WARN,"gps_data_save_file assert(write) failed, ret[%d]",write_len); + break; + } + } + + gps_his_file_write_head(phis, head_buff); + + CLOSE_FILE_HANDLE(phis->handle) + + LOG(DEBUG,"clock(%d) gps_data_save_file his_data(num:%d)", util_clock(), phis->record_num); + + return GM_SUCCESS; +} + + +/*将文件中的内容读到pdata缓存, 如果缓存满了, 剩余的文件中的记录前移*/ +static GM_ERRCODE gps_data_read_file(LocationCurData *pdata, HisDatFileType *phis, bool read_from_file) +{ + u8 head_buff[20]; + u8 one_frame[HIS_FILE_FRAME_SIZE]; + u16 fs_len = 0; + u16 write_len = 0; + int idx = 0; + int new_idx = 0; + + GM_memset(head_buff, 0x00, sizeof(head_buff)); + fs_len = gps_his_file_read(phis, (void *)&head_buff, HIS_FILE_OFFSET_CNT, 0); + if ((HIS_FILE_OFFSET_CNT != fs_len) || (HIS_FILE_HEAD_FLAG != MKDWORD(head_buff[0], head_buff[1], head_buff[2], head_buff[3]))) + { + CLOSE_FILE_HANDLE(phis->handle) + LOG(DEBUG,"clock(%d) gps_data_read_file no history file exist. read_len(%d).", util_clock(),fs_len); + + //record_num means records in history file. + phis->record_num = 0; + return GM_SYSTEM_ERROR; + } + else + { + phis->record_num = MKWORD(head_buff[4], head_buff[5]); + } + + if(!read_from_file) + { + // only read head. to get record_num + LOG(INFO,"clock(%d) gps_data_read_file only head(num:%d)", util_clock(), phis->record_num); + return GM_SUCCESS; + } + + for(idx = 0; idx < phis->record_num; ++idx) + { + fs_len = gps_his_file_read(phis, (void *)&one_frame[0], HIS_FILE_FRAME_SIZE, HIS_FILE_OFFSET_CNT + idx * HIS_FILE_FRAME_SIZE); + if(fs_len != HIS_FILE_FRAME_SIZE) + { + LOG(WARN,"gps_data_read_file assert(read) failed, ret[%d]",fs_len); + break; + } + if(gps_data_get_free_size(pdata) > 0) + { + gps_data_insert_one(pdata, phis, &one_frame[1], one_frame[0], false); + } + else + { + write_len = gps_his_file_write(phis, one_frame, HIS_FILE_FRAME_SIZE, new_idx*HIS_FILE_FRAME_SIZE + HIS_FILE_OFFSET_CNT); + if(write_len == HIS_FILE_FRAME_SIZE) + { + new_idx ++; + } + else + { + LOG(WARN,"gps_data_read_file assert(write) failed, ret[%d]",write_len); + break; + } + } + } + + phis->record_num = new_idx; + gps_his_file_write_head(phis, head_buff); + + CLOSE_FILE_HANDLE(phis->handle) + + LOG(INFO,"clock(%d) gps_data_read_file his_data(num:%d)", util_clock(), phis->record_num); + + return GM_SUCCESS; +} + + +static u32 gps_his_file_write_head(HisDatFileType *phis, u8 *head_buff) +{ + head_buff[0] = (HIS_FILE_HEAD_FLAG >> 24) & 0xFF; + head_buff[1] = (HIS_FILE_HEAD_FLAG >> 16) & 0xFF; + head_buff[2] = (HIS_FILE_HEAD_FLAG >> 8) & 0xFF; + head_buff[3] = (HIS_FILE_HEAD_FLAG) & 0xFF; + + head_buff[4] = (phis->record_num >> 8) & 0xFF; + head_buff[5] = (phis->record_num) & 0xFF; + return gps_his_file_write(phis, head_buff, HIS_FILE_OFFSET_CNT, 0); +} + + +static void gps_his_file_delete_record(HisDatFileType *phis, u16 del_num) +{ + u8 head_buff[20]; + u8 one_frame[HIS_FILE_FRAME_SIZE]; + u16 fs_len = 0; + u16 write_len = 0; + int idx = 0; + int new_idx = 0; + + if(phis->record_num <= 0) + { + LOG(ERROR,"clock(%d) gps_his_file_delete_record. assert(record_num(%d)) failed.", util_clock(),phis->record_num); + return; + } + if(phis->handle < 0) + { + LOG(ERROR,"clock(%d) gps_his_file_delete_record. assert(handle(%d)) failed.", util_clock(),phis->handle); + return; + } + + for(idx = 0; idx < phis->record_num; ++idx) + { + fs_len = gps_his_file_read(phis, (void *)&one_frame[0], HIS_FILE_FRAME_SIZE, HIS_FILE_OFFSET_CNT + idx * HIS_FILE_FRAME_SIZE); + if(fs_len != HIS_FILE_FRAME_SIZE) + { + LOG(WARN,"gps_data_read_file assert(read) failed, ret[%d]",fs_len); + break; + } + if(idx >= del_num) + { + write_len = gps_his_file_write(phis, one_frame, HIS_FILE_FRAME_SIZE, new_idx*HIS_FILE_FRAME_SIZE + HIS_FILE_OFFSET_CNT); + if(write_len == HIS_FILE_FRAME_SIZE) + { + new_idx ++; + } + else + { + LOG(WARN,"gps_his_file_delete_record assert(write) failed, ret[%d]",write_len); + break; + } + } + } + + phis->record_num = new_idx; + gps_his_file_write_head(phis, head_buff); + + LOG(INFO,"clock(%d) gps_his_file_delete_record(%d) his_data(num:%d)", util_clock(),del_num, phis->record_num); + + return; +} + + +GM_ERRCODE gps_service_save_to_cache(u8 *data, u8 len) +{ + if(s_gps_sending.his == NULL) + { + gps_data_init(&s_gps_sending, NULL, SAVE_CATCH_MAX_NUM, false); + } + if(gps_data_get_free_size(&s_gps_sending) == 0) + { + return GM_MEM_NOT_ENOUGH; + } + + return gps_data_insert_one(&s_gps_sending, NULL, data, len, true); +} + + +void gps_service_confirm_cache(u32 *from, u32 ack_place) +{ + u32 confirm_len = (ack_place - (*from)); + u32 confirm_total = 0; + LocationSaveData one; + + if(s_gps_sending.his == NULL) + { + gps_data_init(&s_gps_sending, NULL, SAVE_CATCH_MAX_NUM, false); + } + + if(0 == gps_data_get_len(&s_gps_sending)) + { + (*from) = ack_place; + return; + } + + if((*from == 0) && (ack_place == 0)) + { + ack_place = 1000000; //sdk还没支持GM_GetTcpStatus , 直接confirm 所有数据, 最后, (*from) = ack_place = 0; + LOG(DEBUG,"clock(%d) gps_service_confirm_cache(%d,%d) cache_data(num:%d)", util_clock(),*from, ack_place, gps_data_get_len(&s_gps_sending)); + } + + while(GM_SUCCESS == gps_data_peek_one(&s_gps_sending, NULL, &one, true)) + { + confirm_total += one.len; + if(confirm_total <= confirm_len) + { + LOG(DEBUG,"clock(%d) gps_service_confirm_cache(%d,%d) (%d < %d)", util_clock(),*from, ack_place, confirm_total, confirm_len); + gps_data_commit_peek(&s_gps_sending, NULL, true, true); + (*from) += one.len; + } + else + { + break; + } + } + + if(0 == gps_data_get_len(&s_gps_sending)) + { + (*from) = ack_place; + } +} + + + +GM_ERRCODE gps_service_push_to_stack(u8 *data, u8 len) +{ + if(s_gps_data.his == NULL) + { + gps_data_init(&s_gps_data, &s_his_dat, SAVE_HIS_MAX_NUM/3, true); + } + + if(gps_data_get_free_size(&s_gps_data) == 0) + { + gps_data_save_file(&s_gps_data, &s_his_dat); + } + + return gps_data_insert_one(&s_gps_data, &s_his_dat, data, len, true); +} + +GM_ERRCODE gps_service_peek_one(LocationSaveData *one, bool from_head) +{ + if(s_gps_data.his == NULL) + { + gps_data_init(&s_gps_data, &s_his_dat, SAVE_HIS_MAX_NUM/3, true); + } + + return gps_data_peek_one(&s_gps_data, &s_his_dat, one, from_head); +} + +GM_ERRCODE gps_service_commit_peek(bool from_head) +{ + return gps_data_commit_peek(&s_gps_data, &s_his_dat, from_head, true); +} + +void gps_service_his_file_delete(void) +{ + gps_his_file_delete(&s_his_dat); +} + +void gps_service_save_to_history_file(void) +{ + LocationSaveData one; + while(gps_data_get_len(&s_gps_sending) > 0) + { + one.len = 0; + gps_data_peek_one(&s_gps_sending, NULL, &one, true); + if(one.len > 0) + { + gps_service_push_to_stack(one.buf, one.len); + } + gps_data_commit_peek(&s_gps_sending, NULL, true, true); + } + + gps_data_save_to_history_file(&s_gps_data, &s_his_dat); +} + + diff --git a/src/gps_service.c b/src/gps_service.c new file mode 100644 index 0000000..5cd2b41 --- /dev/null +++ b/src/gps_service.c @@ -0,0 +1,1213 @@ +#include "gm_type.h" +#include "stdio.h" +#include "gm_stdlib.h" +#include "gm_gprs.h" +#include "gps_service.h" +#include "fifo.h" +#include "gps.h" +#include "protocol.h" +#include "log_service.h" +#include "gm_memory.h" +#include "utility.h" +#include "gsm.h" +#include "config_service.h" +#include "protocol_goome.h" +#include "protocol_concox.h" +#include "protocol_jt808.h" +#include "gprs.h" +#include "system_state.h" +#include "led.h" +#include "update_service.h" +#include "hard_ware.h" +#include "applied_math.h" +#include "gps_service.h" +#include "agps_service.h" +#include "update_service.h" + +#define GPS_PING_TIME 60 + +typedef struct +{ + bool heart_atonce; // 立即发送心跳 + u32 heart_send_time; // 心跳发送时间 + u32 heart_locate_send_time; // 定位发送时间 超越平台PROTOCOL_JT808只支持定位,不支持心跳,所以用定位代替心跳 + u32 heart_receive_time; // 心跳收到时间 + u32 receive_heart_counts; //收到心跳计数 + u32 send_location_counts; //发送定位数据计数 + u32 data_finish_time; //进入到SOCKET_STATUS_DATA_FINISH状态的时间 + u32 lbs_send_time; + u32 saved_socket_ack; //发消息前,ack的值 + u32 connection_time; //连接建立时间 +}SocketTypeExtend; + + + +static SocketType s_gps_socket = {-1,"",SOCKET_STATUS_ERROR,}; +static SocketTypeExtend s_gps_socket_extend = {0,0,0,0,0,0,0,0,0}; + +static GM_ERRCODE gps_service_transfer_status(u8 new_status); +static void gps_service_init_proc(void); +static void gps_service_connecting_proc(void); +static void gps_service_login_proc(void); +static void gps_service_work_proc(void); +static void gps_service_close(void); + +static GM_ERRCODE protocol_pack_gps_msg(GpsDataModeEnum mode, const GPSData *gps, u8 *pdata, u16 *idx, u16 len); +static GM_ERRCODE protocol_pack_lbs_msg(u8 *pdata, u16 *idx, u16 len); +static GM_ERRCODE protocol_pack_alarm_msg(AlarmInfo *alarm, u8 *pdata, u16 *idx, u16 len); +static GM_ERRCODE protocol_pack_position_request_msg(u8 *mobile_num, u8 num_len, u8 *command, u8 cmd_len,u8 *pdata, u16 *idx, u16 len); + +static GM_ERRCODE gps_service_transfer_status(u8 new_status) +{ + u8 old_status = (u8)s_gps_socket.status; + GM_ERRCODE ret = GM_PARAM_ERROR; + switch(s_gps_socket.status) + { + case SOCKET_STATUS_INIT: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_LOGIN: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_GET_HOST: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + break; + case SOCKET_STATUS_CONNECTING: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_LOGIN: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_CONNECTING: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_LOGIN: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_WORK: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_LOGIN: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_LOGIN: + break; + case SOCKET_STATUS_WORK: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_WORK: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_LOGIN: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_DATA_FINISH: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_LOGIN: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_ERROR: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_LOGIN: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + default: + break; + } + + + if(GM_SUCCESS == ret) + { + s_gps_socket.status = new_status; + s_gps_socket.status_fail_count = 0; + LOG(INFO,"clock(%d) gps_service_transfer_status from %s to %s success", util_clock(), + gm_socket_status_string((SocketStatus)old_status), gm_socket_status_string((SocketStatus)new_status)); + } + else + { + LOG(WARN,"clock(%d) gps_service_transfer_status assert(from %s to %s) failed", util_clock(), + gm_socket_status_string((SocketStatus)old_status), gm_socket_status_string((SocketStatus)new_status)); + } + + return ret; + +} + + +/* +// have ip, use ip to connect +// no ip, call gm_socket_get_host_by_name +*/ +static void gps_service_init_proc(void) +{ + u8 IP[4]; + gm_socket_get_host_by_name_trigger(&s_gps_socket); + system_state_get_ip_cache(SOCKET_INDEX_MAIN, IP); + if(GM_SUCCESS == gm_is_valid_ip(IP)) + { + GM_memcpy( s_gps_socket.ip , IP, sizeof(IP)); + gps_service_transfer_status(SOCKET_STATUS_CONNECTING); + if(GM_SUCCESS == gm_socket_connect(&s_gps_socket)) + { + } + // else do nothing . connecting_proc will deal. + } + else if((!s_gps_socket.excuted_get_host) && (GM_SUCCESS == gm_is_valid_ip(s_gps_socket.ip))) + { + gps_service_transfer_status(SOCKET_STATUS_CONNECTING); + if(GM_SUCCESS == gm_socket_connect(&s_gps_socket)) + { + } + // else do nothing . connecting_proc will deal. + } +} + +static void gps_service_connecting_proc(void) +{ + u32 current_time = util_clock(); + + if((current_time - s_gps_socket.send_time) > CONNECT_TIME_OUT) + { + s_gps_socket.status_fail_count ++; + gps_service_connection_failed(); + + if(s_gps_socket.status == SOCKET_STATUS_CONNECTING && + s_gps_socket.status_fail_count < MAX_CONNECT_REPEAT) + { + if(GM_SUCCESS == gm_socket_connect(&s_gps_socket)) + { + //do nothing. wait callback + } + } + + } +} + + + +static void gps_service_login_proc(void) +{ + u32 current_time = util_clock(); + + if((current_time - s_gps_socket.send_time) >= MESSAGE_TIME_OUT) + { + ++s_gps_socket.status_fail_count; + if(s_gps_socket.status_fail_count >= GPS_LOGIN_MSG_FAIL_MAX) + { + JsonObject* p_json_log = json_create(); + json_add_string(p_json_log, "event", "login"); + json_add_string(p_json_log, "state", "failed"); + json_add_int(p_json_log, "fail count", s_gps_socket.status_fail_count); + log_service_upload(WARN, p_json_log); + + system_state_set_gpss_reboot_reason("login failed."); + gps_service_close(); + s_gps_socket_extend.data_finish_time = util_clock(); + gps_service_transfer_status(SOCKET_STATUS_DATA_FINISH); + } + else + { + if(GM_SUCCESS != protocol_send_login_msg(&s_gps_socket)) + { + return; + } + } + } + + protocol_msg_receive(&s_gps_socket); +} + + + + +/* + get msg from fifo + if have no gps msg, sending heartbeat, else sending gpsmsg +*/ +static void gps_service_work_proc(void) +{ + u32 current_time = util_clock(); + u16 value_u16; + bool lbs_enable; + U32 send_counts = 0; + + //服务模块工作状态并且不是休眠状态LED常亮 + if (GM_SYSTEM_STATE_WORK == system_state_get_work_state()) + { + led_set_gsm_state(GM_LED_ON); + } + + config_service_get(CFG_IS_LBS_ENABLE, TYPE_BOOL, &lbs_enable, sizeof(lbs_enable)); + if(lbs_enable && (!gps_is_fixed())) + { + u16 wait_gps_time = 0; + config_service_get(CFG_WAIT_GPS_TIME, TYPE_SHORT, &wait_gps_time, sizeof(wait_gps_time)); + wait_gps_time = wait_gps_time < SECONDS_PER_MIN ? SECONDS_PER_MIN:wait_gps_time; + if((current_time > wait_gps_time) || (s_gps_socket_extend.lbs_send_time > 0)) + { + //启动了足够久(注意一百多天归0) 或已经发过 + config_service_get(CFG_LBS_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + if((current_time - s_gps_socket_extend.lbs_send_time) >= value_u16) + { + gps_service_push_lbs(); + } + } + } + + + if(PROTOCOL_JT808 == config_service_get_app_protocol()) + { + config_service_get(CFG_JT_HBINTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + if(value_u16) // != 0 + { + if((current_time - s_gps_socket_extend.heart_locate_send_time) >= value_u16) + { + gps_service_send_one_locate(GPS_MODE_FIX_TIME, false); + s_gps_socket_extend.heart_locate_send_time = current_time; + } + } + } + + config_service_get(CFG_HEART_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + if((current_time - s_gps_socket_extend.heart_send_time) >= value_u16 || s_gps_socket_extend.heart_atonce) + { + protocol_send_heartbeat_msg(&s_gps_socket); + s_gps_socket_extend.heart_send_time = current_time; + s_gps_socket_extend.heart_atonce = false; + } + + /* + 连接建立成功2次心跳间隔后才检测心跳有没有超时 + */ + if((current_time - s_gps_socket_extend.connection_time) > (2*value_u16) + && (current_time - s_gps_socket_extend.heart_receive_time) >= GPS_HEART_MSG_RECEIVE_TIME_OUT) + { + LOG(INFO,"clock(%d) gps_service_work_proc heart break. last heart time:%d", util_clock(), s_gps_socket_extend.heart_receive_time); + system_state_set_gpss_reboot_reason("heart broken."); + gps_service_close(); + s_gps_socket_extend.data_finish_time = util_clock(); + gps_service_transfer_status(SOCKET_STATUS_DATA_FINISH); + return; + } + + send_counts = protocol_send_gps_msg(&s_gps_socket); + s_gps_socket_extend.send_location_counts += send_counts; + + protocol_msg_receive(&s_gps_socket); +} + + +void gps_service_connection_ok(void) +{ + u32 current_time = util_clock(); + s_gps_socket_extend.connection_time = current_time; + gps_service_transfer_status(SOCKET_STATUS_LOGIN); + + protocol_send_login_msg(&s_gps_socket); + +} + +void gps_service_close_for_reconnect(void) +{ + gps_service_close(); + s_gps_socket_extend.data_finish_time = util_clock(); + gps_service_transfer_status(SOCKET_STATUS_DATA_FINISH); +} + +void gps_service_connection_failed(void) +{ + system_state_set_gpss_reboot_reason("connect failed."); + gps_service_close(); + + if(s_gps_socket.status_fail_count >= MAX_CONNECT_REPEAT) + { + // if excuted get_host reinit gprs, else get_host. + if(s_gps_socket.excuted_get_host || (s_gps_socket.addr[0] == 0)) + { + // reinit gprs + LOG(DEBUG,"clock(%d) gps_service_connection_failed excuted_get_host(%d)",util_clock(),s_gps_socket.excuted_get_host); + gps_service_destroy_gprs(); + } + else + { + gps_service_transfer_status(SOCKET_STATUS_INIT); + } + } + //else do nothing. wait gps_service_connecting_proc to deal +} + + +GM_ERRCODE gps_service_create(bool first_create) +{ + u8 addr[2*GOOME_DNS_MAX_LENTH+1]; + u8 IP[4]; + u32 port = 0; + u8 idx = 0; + + /*because s_gps_socket.fifo.base_addr is not initialized, here depend on first_create + to check base_addr is null or not*/ + if(!first_create) + { + if(s_gps_socket.fifo.base_addr) + { + return GM_SUCCESS; + } + } + + s_gps_socket.access_id = SOCKET_INDEX_MAIN; + gm_socket_init(&s_gps_socket); + + GM_memset(addr, 0x00, sizeof(addr)); + + if(config_service_is_test_mode() || config_service_is_default_imei()) + { + idx = GM_sscanf((const char *)config_service_get_pointer(CFG_TEST_SERVERADDR), "%[^:]:%d", addr, &port); + if (idx != 2) + { + LOG(WARN,"clock(%d) gps_service_create assert(idx ==2) failed.", util_clock()); + return GM_PARAM_ERROR; + } + } + else + { + idx = GM_sscanf((const char *)config_service_get_pointer(CFG_SERVERADDR), "%[^:]:%d", addr, &port); + if (idx != 2) + { + LOG(WARN,"clock(%d) gps_service_create assert(idx ==2) failed.", util_clock()); + return GM_PARAM_ERROR; + } + } + + if(GM_SUCCESS != GM_ConvertIpAddr(addr, IP)) + { + if(util_is_valid_dns(addr, GM_strlen((const char *)addr))) + { + gm_socket_set_addr(&s_gps_socket, addr, GM_strlen((const char *)addr), port, STREAM_TYPE_STREAM); + system_state_get_ip_cache(SOCKET_INDEX_MAIN, IP); + gm_socket_set_ip_port(&s_gps_socket, IP, port, STREAM_TYPE_STREAM); + } + else + { + LOG(WARN,"clock(%d) gps_service_create assert(dns(%s)) failed.", util_clock(), addr); + return GM_PARAM_ERROR; + } + } + else + { + gm_socket_set_ip_port(&s_gps_socket, IP, port, STREAM_TYPE_STREAM); + } + + + s_gps_socket_extend.heart_atonce = false; + s_gps_socket_extend.heart_send_time = 0; + s_gps_socket_extend.heart_locate_send_time = 0; + s_gps_socket_extend.receive_heart_counts = 0; + s_gps_socket_extend.send_location_counts = 0; + s_gps_socket_extend.data_finish_time = 0; + s_gps_socket_extend.saved_socket_ack = 0; + s_gps_socket_extend.lbs_send_time = 0; + + LOG(INFO,"clock(%d) gps_service_create access_id(%d) fifo(%p).", util_clock(), s_gps_socket.access_id, &s_gps_socket.fifo); + + return GM_SUCCESS; +} + + + +GM_ERRCODE gps_service_change_config(void) +{ + if (! gps_service_socket_is_same()) + { + u8 value_u8 = 0; + system_state_set_gpss_reboot_reason("change config."); + gps_service_destroy(); + + // clear previous connection info. + s_gps_socket.ip[0] = s_gps_socket.ip[1] = s_gps_socket.ip[2] = s_gps_socket.ip[3] = 0; + s_gps_socket.addr[0] = 0; + system_state_set_ip_cache(SOCKET_INDEX_MAIN, s_gps_socket.ip); + config_service_set(CFG_JT_ISREGISTERED, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + gps_service_create(false); + } + return GM_SUCCESS; +} + + +GM_ERRCODE gps_service_destroy(void) +{ + if(SOCKET_STATUS_ERROR == s_gps_socket.status) + { + return GM_SUCCESS; + } + + gps_service_close(); + led_set_gsm_state(GM_LED_FLASH); + + fifo_delete(&s_gps_socket.fifo); + + s_gps_socket_extend.data_finish_time = util_clock(); + gps_service_transfer_status(SOCKET_STATUS_ERROR); + + return GM_SUCCESS; +} + +static void gps_service_close(void) +{ + gps_service_save_to_history_file(); + + if(s_gps_socket.id >=0) + { + GM_SocketClose(s_gps_socket.id); + s_gps_socket.id=-1; + s_gps_socket_extend.saved_socket_ack = s_gps_socket.last_ack_seq = 0; + } +} + + +static void gps_service_data_finish_proc(void) +{ + u32 current_time = util_clock(); + + if(gprs_check_need_reboot(s_gps_socket_extend.heart_receive_time)) + { + //以下日志如果放开,会打印过多.(10ms一次) + //LOG(INFO,"clock(%d) gps_service_data_finish_proc heart break. last heart time:%d", util_clock(), s_gps_socket_extend.heart_receive_time); + return; + } + + if(! s_gps_socket.fifo.base_addr) + { + return; + } + + if((current_time - s_gps_socket_extend.data_finish_time) > GPS_PING_TIME) + { + LOG(DEBUG,"clock(%d) gps_service_data_finish_proc cur(%d) - fin(%d) > GPS_PING_TIME(%d).", + util_clock(), current_time, s_gps_socket_extend.data_finish_time,GPS_PING_TIME); + + // 可以重建连接 + gps_service_transfer_status(SOCKET_STATUS_INIT); + } +} + + +GM_ERRCODE gps_service_timer_proc(void) +{ + if(!s_gps_socket.fifo.base_addr) + { + return GM_SUCCESS; + } + + switch(s_gps_socket.status) + { + case SOCKET_STATUS_INIT: + gps_service_init_proc(); + break; + case SOCKET_STATUS_CONNECTING: + gps_service_connecting_proc(); + break; + case SOCKET_STATUS_LOGIN: + gps_service_login_proc(); + break; + case SOCKET_STATUS_WORK: + gps_service_work_proc(); + break; + case SOCKET_STATUS_DATA_FINISH: + gps_service_data_finish_proc(); + break; + case SOCKET_STATUS_ERROR: + gps_service_data_finish_proc(); + break; + default: + { + char reason[30]; + LOG(WARN,"clock(%d) gps_service_timer_proc assert(s_gps_socket.status(%d)) unknown.",util_clock(), s_gps_socket.status); + + // reinit gprs + snprintf(reason,sizeof(reason),"unknown status %d", s_gps_socket.status); + reason[sizeof(reason) - 1] = 0; + system_state_set_gpss_reboot_reason(reason); + gps_service_destroy_gprs(); + return GM_ERROR_STATUS; + } + } + + return GM_SUCCESS; +} + + + +u8 gps_service_socket_is_same(void) +{ + u8 addr[CONFIG_STRING_MAX_LEN+1]; + u8 IP[4]; + u32 port = 0; + u8 idx = 0; + + GM_memset(addr, 0x00, sizeof(addr)); + idx = GM_sscanf((const char *)config_service_get_pointer(CFG_SERVERADDR), "%[^:]:%d", addr, &port); + if (idx != 2) + { + LOG(WARN,"clock(%d) gps_service_socket_is_same assert(idx ==2) failed.",util_clock()); + return 1; // not change. + } + + if(s_gps_socket.port != port) + { + return 0; + } + + if(GM_SUCCESS == GM_ConvertIpAddr(addr, IP)) + { + if(s_gps_socket.ip[0] == IP[0] && s_gps_socket.ip[1] == IP[1] && + s_gps_socket.ip[2] == IP[2] && s_gps_socket.ip[3] == IP[3]) + { + return 1; + } + else + { + return 0; + } + } + else + { + if(0 == GM_strcmp(s_gps_socket.addr, (const char *)addr)) + { + return 1; + } + else + { + return 0; + } + } + // return 1; +} + + + + +static GM_ERRCODE protocol_pack_gps_msg(GpsDataModeEnum mode, const GPSData *gps, u8 *pdata, u16 *idx, u16 len) +{ + switch(config_service_get_app_protocol()) + { + case PROTOCOL_GOOME: + protocol_goome_pack_gps_msg(mode, gps, pdata, idx, len); //17 bytes + break; + case PROTOCOL_CONCOX: + protocol_concox_pack_gps_msg(mode, gps, pdata, idx, len); // 39 bytes + break; + case PROTOCOL_JT808: + protocol_jt_pack_gps_msg(mode, gps, pdata, idx, len); // 53 bytes + break; + default: + LOG(WARN,"clock(%d) protocol_pack_gps_msg assert(app protocol(%d)) failed.",util_clock(), config_service_get_app_protocol()); + return GM_SYSTEM_ERROR; + } + return GM_SUCCESS; +} + +GM_ERRCODE gps_service_cache_send(u8 *data, u8 len) +{ + gps_service_confirm_gps_cache(&s_gps_socket); + + if(GM_SUCCESS == gps_service_save_to_cache(data, len)) + { + if(GM_SUCCESS == gm_socket_send(&s_gps_socket, data, len)) + { + s_gps_socket.send_time = util_clock(); + return GM_SUCCESS; + } + else + { + system_state_set_gpss_reboot_reason("gm_socket_send cache_send"); + gps_service_destroy_gprs(); + return GM_NET_ERROR; + } + } + return GM_MEM_NOT_ENOUGH; +} + +void gps_service_confirm_gps_cache(SocketType *socket) +{ + gm_socket_get_ackseq(socket, &socket->last_ack_seq); + if(socket->access_id != SOCKET_INDEX_MAIN) + { + return; + } + + gps_service_confirm_cache(&s_gps_socket_extend.saved_socket_ack, s_gps_socket.last_ack_seq); +} + + +GM_ERRCODE gps_service_push_gps(GpsDataModeEnum mode, const GPSData *gps) +{ + u8 buff[HIS_FILE_FRAME_SIZE]; + u16 len = sizeof(buff); + u16 idx = 0; + bool gps_close = false; + + + if(NULL == gps) + { + return GM_PARAM_ERROR; + } + + LOG(DEBUG,"Report GPS,LAT:%f,LNG:%f,SPEED:%f,COURSE:%f,SATES:%d,PRECI:%f,SIGNAL:%d", + gps->lat, + gps->lng, + gps->speed, + gps->course, + gps->satellites, + gps->precision, + gps->signal_intensity_grade); + + config_service_get(CFG_GPS_CLOSE, TYPE_BOOL, &gps_close, sizeof(gps_close)); + if(gps_close) + { + LOG(DEBUG,"clock(%d) gps_service_push_gps not enabled.",util_clock()); + return GM_ERROR_STATUS; + } + + system_state_set_last_gps(gps); + if(GM_SUCCESS != protocol_pack_gps_msg(mode, gps, buff, &idx, len)) + { + return GM_SYSTEM_ERROR; + } + + len=idx; // idx is msg len + + if(SOCKET_STATUS_WORK == s_gps_socket.status) + { + LOG(DEBUG,"clock(%d) gps_service_push_gps msglen(%d)", util_clock(), idx); + if(GM_SUCCESS == gps_service_cache_send(buff, idx)) + { + s_gps_socket_extend.send_location_counts++; + return GM_SUCCESS; + } + } + + return gps_service_push_to_stack(buff, idx); +} + +void gps_service_heart_atonce(void) +{ + LOG(INFO,"gps_service_heart_atonce"); + s_gps_socket_extend.heart_atonce = true; +} + +GM_ERRCODE gps_service_send_one_locate(GpsDataModeEnum mode, bool use_lbs) +{ + u8 buff[HIS_FILE_FRAME_SIZE]; + u16 len = sizeof(buff); + u16 idx = 0; + GPSData gps; + + LOG(DEBUG,"clock(%d) gps_service_send_one_locate mode(%d) use_lbs(%d).",util_clock(), mode, use_lbs); + if(s_gps_socket.status != SOCKET_STATUS_LOGIN && s_gps_socket.status != SOCKET_STATUS_WORK) + { + LOG(WARN,"clock(%d) gps_service_send_one_locate socket->status(%s) error.", util_clock(), gm_socket_status_string((SocketStatus)s_gps_socket.status)); + return GM_PARAM_ERROR; + } + + //超越平台 不认心跳包,没有GPS包就会显示掉线 + if(use_lbs) + { + if(!gps_is_fixed()) + { + //未定位, 发LBS + if(GM_SUCCESS != protocol_pack_lbs_msg(buff, &idx, len)) + { + return GM_SYSTEM_ERROR; + } + + len=idx; // idx is msg len + + if(SOCKET_STATUS_WORK == s_gps_socket.status) + { + LOG(DEBUG,"clock(%d) gps_service_send_one_locate lbs msglen(%d)", util_clock(), idx); + if(GM_SUCCESS == gm_socket_send(&s_gps_socket, buff, idx)) + { + s_gps_socket.send_time = util_clock(); + return GM_SUCCESS; + } + else + { + system_state_set_gpss_reboot_reason("gm_socket_send one_locate"); + gps_service_destroy_gprs(); + } + } + + return GM_SUCCESS; + } + } + + //已定位,或不用lbs + GM_memset(&gps,0,sizeof(gps)); + gps_get_last_data(&gps); + if(gps.gps_time == (time_t)0) + { + system_state_get_last_gps(&gps); + } + + if(gps.gps_time == (time_t)0) + { + gps.lat = agps_service_get_unfix_lat(); + gps.lng = agps_service_get_unfix_lng(); + + if(gps.lat < 0.00001f) + { + // prevent send not located position. + return GM_SUCCESS; + } + + } + + //use current time. + gps.gps_time = util_get_utc_time(); + //如果静止状态,速度设置为0 + if (VEHICLE_STATE_STATIC == system_state_get_vehicle_state()) + { + gps.speed = 0; + } + + if(GM_SUCCESS != protocol_pack_gps_msg(mode, &gps, buff, &idx, len)) + { + return GM_SYSTEM_ERROR; + } + + len=idx; // idx is msg len + + if(SOCKET_STATUS_WORK == s_gps_socket.status) + { + LOG(DEBUG,"clock(%d) gps_service_send_one_locate gps msglen(%d)", util_clock(), idx); + if(GM_SUCCESS == gm_socket_send(&s_gps_socket, buff, idx)) + { + s_gps_socket.send_time = util_clock(); + return GM_SUCCESS; + } + else + { + system_state_set_gpss_reboot_reason("gm_socket_send onelocate"); + gps_service_destroy_gprs(); + } + } + + return GM_SUCCESS; +} + + +static GM_ERRCODE protocol_pack_lbs_msg(u8 *pdata, u16 *idx, u16 len) +{ + switch(config_service_get_app_protocol()) + { + case PROTOCOL_GOOME: + protocol_goome_pack_lbs_msg(pdata, idx, len); //47 bytes + break; + case PROTOCOL_CONCOX: + protocol_concox_pack_lbs_msg(pdata, idx, len); //63 bytes + break; + case PROTOCOL_JT808: + protocol_jt_pack_lbs_msg(pdata, idx, len); // max 97 bytes + break; + default: + LOG(WARN,"clock(%d) protocol_pack_lbs_msg assert(app protocol(%d)) failed.",util_clock(), config_service_get_app_protocol()); + return GM_SYSTEM_ERROR; + } + return GM_SUCCESS; +} + + + +GM_ERRCODE gps_service_push_lbs(void) +{ + u8 buff[HIS_FILE_FRAME_SIZE]; + u16 len = sizeof(buff); + u16 idx = 0; + + s_gps_socket_extend.lbs_send_time = util_clock(); + + if(GM_SUCCESS != protocol_pack_lbs_msg(buff, &idx, len)) + { + return GM_SYSTEM_ERROR; + } + + len=idx; // idx is msg len + + if(SOCKET_STATUS_WORK == s_gps_socket.status) + { + LOG(DEBUG,"clock(%d) gps_service_push_lbs msglen(%d)", util_clock(), idx); + if(GM_SUCCESS == gps_service_cache_send(buff, idx)) + { + return GM_SUCCESS; + } + } + + return gps_service_push_to_stack(buff, idx); +} + + +static GM_ERRCODE protocol_pack_alarm_msg(AlarmInfo *alarm,u8 *pdata, u16 *idx, u16 len) +{ + switch(config_service_get_app_protocol()) + { + case PROTOCOL_GOOME: + protocol_goome_pack_alarm_msg(alarm, pdata, idx, len); //35 bytes + break; + case PROTOCOL_CONCOX: + protocol_concox_pack_alarm_msg(alarm, pdata, idx, len); //42 bytes + break; + case PROTOCOL_JT808: + protocol_jt_pack_gps_msg2(pdata, idx, len); // 53 bytes + break; + default: + LOG(WARN,"clock(%d) protocol_pack_alarm_msg assert(app protocol(%d)) failed.", util_clock(), config_service_get_app_protocol()); + return GM_SYSTEM_ERROR; + } + return GM_SUCCESS; +} + + + + +GM_ERRCODE gps_service_push_alarm(AlarmInfo *alarm) +{ + u8 buff[HIS_FILE_FRAME_SIZE]; + u16 len = sizeof(buff); + u16 idx = 0; + + //不定位不报警,很可能造成断电报警丢失 + //先报上去,等GPS定位了也会上报位置的——王志华 + + if(GM_SUCCESS != protocol_pack_alarm_msg(alarm, buff, &idx, len)) + { + LOG(ERROR,"Failed to protocol_pack_alarm_msg!"); + return GM_SYSTEM_ERROR; + } + + len=idx; + + if(SOCKET_STATUS_WORK == s_gps_socket.status) + { + LOG(DEBUG,"clock(%d) gps_service_push_alarm msglen(%d) alarm(%d)", util_clock(), len,alarm->type); + if(GM_SUCCESS == gps_service_cache_send(buff, idx)) + { + return GM_SUCCESS; + } + } + + return gps_service_push_to_stack(buff, idx); +} + + +static GM_ERRCODE protocol_pack_position_request_msg(u8 *mobile_num, u8 num_len, u8 *command, u8 cmd_len,u8 *pdata, u16 *idx, u16 len) +{ + switch(config_service_get_app_protocol()) + { + case PROTOCOL_GOOME: + protocol_goome_pack_position_request_msg(mobile_num,num_len,command,cmd_len, pdata, idx, len); //53+cmd_len bytes + break; + case PROTOCOL_CONCOX: + protocol_concox_pack_position_request_msg(mobile_num,num_len,command,cmd_len, pdata, idx, len); //45 bytes + break; + default: + LOG(WARN,"clock(%d) gps_service_push_position_request assert(app protocol(%d)) failed.", util_clock(), config_service_get_app_protocol()); + return GM_SYSTEM_ERROR; + } + return GM_SUCCESS; +} + + + + +GM_ERRCODE gps_service_push_position_request(u8 *mobile_num, u8 num_len, u8 *command, u8 cmd_len) +{ + u8 buff[HIS_FILE_FRAME_SIZE]; + u16 len = sizeof(buff); + u16 idx = 0; + + if(GM_SUCCESS != protocol_pack_position_request_msg(mobile_num,num_len,command,cmd_len, buff, &idx, len)) + { + LOG(ERROR,"Failed to gps_service_push_position_request!"); + return GM_SYSTEM_ERROR; + } + + len=idx; + + if(SOCKET_STATUS_WORK == s_gps_socket.status) + { + LOG(DEBUG,"clock(%d) gps_service_push_position_request msglen(%d) mobile_num(%s)", util_clock(), len,mobile_num); + if(GM_SUCCESS == gm_socket_send(&s_gps_socket, buff, len)) + { + s_gps_socket.send_time = util_clock(); + return GM_SUCCESS; + } + else + { + LOG(WARN,"Failed to send data by socket!"); + system_state_set_gpss_reboot_reason("gm_socket_send position_req"); + gps_service_destroy_gprs(); + } + } + + return gps_service_push_to_stack(buff, idx); +} + + +void gps_service_after_register_response(void) +{ + if(SOCKET_STATUS_LOGIN != s_gps_socket.status) + { + LOG(WARN,"clock(%d) gps_service_after_register_response assert(socket->status(%d) == SOCKET_STATUS_LOGIN) failed.", util_clock(), s_gps_socket.status); + return; + } + protocol_send_login_msg(&s_gps_socket); +} + + +void gps_service_after_login_response(void) +{ + JsonObject* p_json_log = json_create(); + + char ip_str[16] = {0}; + U8* ip = gps_service_get_current_ip(); + GM_snprintf(ip_str, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); + + if(SOCKET_STATUS_LOGIN != s_gps_socket.status) + { + LOG(WARN,"clock(%d) gps_service_after_login_response assert(socket->status(%d) == SOCKET_STATUS_LOGIN) failed.", util_clock(), s_gps_socket.status); + return; + } + + if(GM_SUCCESS != protocol_send_device_msg(&s_gps_socket)) + { + return; + } + + protocol_send_heartbeat_msg(&s_gps_socket); + s_gps_socket_extend.heart_locate_send_time = s_gps_socket_extend.heart_send_time = util_clock(); + + if(PROTOCOL_JT808 == config_service_get_app_protocol()) + { + gps_service_send_one_locate(GPS_MODE_FIX_TIME, false); + } + + gps_service_transfer_status(SOCKET_STATUS_WORK); + + json_add_string(p_json_log, "event", "login"); + json_add_string(p_json_log, "state", "ok"); + json_add_int(p_json_log, "protocol", config_service_get_app_protocol()); + json_add_string(p_json_log, "ip", ip_str); + log_service_upload(INFO, p_json_log); +} + +void gps_service_after_receive_heartbeat(void) +{ + if(SOCKET_STATUS_LOGIN != s_gps_socket.status && SOCKET_STATUS_WORK != s_gps_socket.status) + { + LOG(WARN,"clock(%d) gps_service_after_receive_heartbeat assert(socket->status(%d)) failed.", util_clock(), s_gps_socket.status); + return; + } + + LOG(INFO,"clock(%d) gps_service_after_receive_heartbeat.", util_clock()); + s_gps_socket_extend.heart_receive_time = util_clock(); + s_gps_socket_extend.receive_heart_counts++; +} + +U32 gps_service_get_heart_counts(void) +{ + return s_gps_socket_extend.receive_heart_counts; +} + +U32 gps_service_get_location_counts(void) +{ + return s_gps_socket_extend.send_location_counts; +} + +void gps_service_after_server_req(void) +{ + if(SOCKET_STATUS_WORK != s_gps_socket.status) + { + LOG(WARN,"clock(%d) gps_service_after_server_req assert(socket->status(%d)) failed.", util_clock(), s_gps_socket.status); + return; + } + protocol_send_general_ack(&s_gps_socket); +} + + +void gps_service_after_server_locate_req(void) +{ + if(SOCKET_STATUS_WORK != s_gps_socket.status) + { + LOG(WARN,"clock(%d) gps_service_after_server_locate_req assert(socket->status(%d)) failed.", util_clock(), s_gps_socket.status); + return; + } + + //发送一条gps数据 + gps_service_send_one_locate(GPS_MODE_FIX_TIME, true); +} + + +void gps_service_after_receive_remote_msg(u8 *pRet, u16 len) +{ + protocol_send_remote_ack(&s_gps_socket, pRet, len); +} + +void gps_service_after_param_get(void) +{ + protocol_send_param_get_ack(&s_gps_socket); +} + +void gps_service_destroy_gprs(void) +{ + if(SOCKET_STATUS_DATA_FINISH == update_service_get_status() || + SOCKET_STATUS_ERROR == update_service_get_status()) + { + LOG(DEBUG,"clock(%d) gps_service_destroy_gprs update_service_status(%d)",util_clock(),update_service_get_status()); + gprs_destroy(); + } + else + { + //wait gprs reinit + gps_service_destroy(); + } +} + +bool gps_service_is_login_ok(void) +{ + return (SOCKET_STATUS_WORK == s_gps_socket.status); +} + +U8* gps_service_get_current_ip(void) +{ + return s_gps_socket.ip; +} + + diff --git a/src/gsm.c b/src/gsm.c new file mode 100644 index 0000000..be03ea9 --- /dev/null +++ b/src/gsm.c @@ -0,0 +1,425 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: gsm.h + * Author: 李耀轩 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. 创建gsm模块 + 2. 销毁gsm模块 + 3. gsm模块定时处理入口 + * History: + 1. Date: 2019-03-01 + Author: 李耀轩 + Modification: 创建初始版本 + + 2. Date: 2019-04-08 + Author: 王志华 + Modification: 实现基本功能 + + */ + +#include +#include +#include +#include +#include +#include +#include +#include "utility.h" +#include "gsm.h" +#include "log_service.h" +#include "gps_service.h" +#include "system_state.h" +#include "gps.h" +#include "led.h" +#include "config_service.h" +#include "auto_test.h" + + +//伪基站检查周期20秒 +#define GM_FAKE_CELL_CHECK_PERIOD 20 + +//伪基站持续时间120秒,报警 +#define GM_FAKE_CELL_CONTINUE_MAX_TIME 120 + +//伪基站持续时间内总次数达到50次以上才报警 +#define GM_FAKE_CELL_CONTINUE_MAX_COUNT 50 + + +#define GM_CSQ_MIN 0 +#define GM_CSQ_MAX 31 + + + +typedef struct +{ + bool sim_is_valid; + + U8 imei[GM_IMEI_LEN + 1]; + U8 imsi[GM_IMSI_LEN + 1]; + U8 iccid[GM_ICCID_LEN + 1]; + + gm_cell_info_struct cell_info; + + //每20秒收到伪基站回调次数 + U8 fake_cell_count_per_20second; + + //每120秒收到伪基站回调次数 + U8 fake_cell_count_per_120second; + + //伪基站信号持续时间(秒) + U8 fake_cell_continue_seconds; +}GSM; + +static GSM s_gsm; + +static void check_sim_card(void); +GsmRegState gsm_get_creg_state(void); +static bool imei_is_valid(U8* p_imei); +static void get_gsm_info(void); +static void gsm_iccid_callback(void* p_msg); +static void gsm_lbs_callback(void* p_msg); +static void gsm_imei_callback(void* p_imei); +static void gsm_call_status_callback(void* p_msg); +static void gsm_incomming_call(void* evt); +static void gsm_fake_cell_callback(void* evt); +static void check_fake_cell_alarm_timer_proc(void); + + + + + +GM_ERRCODE gsm_create(void) +{ + s_gsm.sim_is_valid = false; + GM_memset(s_gsm.imei,0,GM_IMEI_LEN + 1); + GM_memset(s_gsm.imsi,0,GM_IMSI_LEN + 1); + GM_memset(s_gsm.iccid,0,GM_ICCID_LEN + 1); + + GM_memset(&s_gsm.cell_info,0,sizeof(s_gsm.cell_info)); + + s_gsm.fake_cell_count_per_20second = 0; + s_gsm.fake_cell_count_per_120second = 0; + s_gsm.fake_cell_continue_seconds = 0; + + GM_RegisterCallBack(GM_CB_FAKE_CELL_RECEIVE, (U32)gsm_fake_cell_callback); + GM_RegisterCallBack(GM_CB_CALL_RECEIVE, (U32)gsm_incomming_call); + + GM_StartTimer(GM_TIMER_GSM_CHECK_SIMCARD, TIM_GEN_1SECOND*5, check_sim_card); + GM_StartTimer(GM_TIMER_GSM_CHECK_FAKE_CELL_ALARM, TIM_GEN_1SECOND*GM_FAKE_CELL_CHECK_PERIOD, check_fake_cell_alarm_timer_proc); + return GM_SUCCESS; +} + +GM_ERRCODE gsm_destroy(void) +{ + return GM_SUCCESS; +} + +GsmRegState gsm_get_creg_state(void) +{ + GsmRegState status = GSM_CREG_UNREGISTER; + if(!GM_GetCregStatus(&status)) + { + LOG(ERROR, "Failed to GM_GetCregStatus!"); + } + return status; +} + +GM_ERRCODE gsm_get_iccid(U8* p_iccid) +{ + U8 len = GM_strlen((char*)s_gsm.iccid); + if (GM_ICCID_LEN == len) + { + GM_memcpy(p_iccid, s_gsm.iccid, GM_ICCID_LEN); + p_iccid[GM_ICCID_LEN] = 0; + return GM_SUCCESS; + } + else + { + return GM_NOT_INIT; + } +} + +GM_ERRCODE gsm_get_imsi(U8* p_imsi) +{ + U8 len = GM_strlen((char*)s_gsm.imsi); + if (GM_IMSI_LEN == len) + { + GM_memcpy(p_imsi, s_gsm.imsi, GM_IMSI_LEN); + p_imsi[GM_IMSI_LEN] = 0; + return GM_SUCCESS; + } + else + { + return GM_NOT_INIT; + } +} + +GM_ERRCODE gsm_get_imei(U8* p_imei) +{ + U8 len = GM_strlen((char*)s_gsm.imei); + if (GM_IMEI_LEN == len) + { + GM_memcpy(p_imei, s_gsm.imei, GM_IMEI_LEN); + p_imei[GM_IMEI_LEN] = 0; + return GM_SUCCESS; + } + else + { + GM_memcpy(p_imei, GOOME_IMEI_DEFAULT, GM_IMEI_LEN); + return GM_NOT_INIT; + } +} + +GM_ERRCODE gsm_set_imei(U8* p_imei) +{ + U8 index_string = 0; + U8 index_hex = 0; + U8 imei_hex_write[GM_IMEI_HEX_LEN] = {0}; + U8 imei_hex_read[GM_IMEI_HEX_LEN] = {0}; + U16 lib_index = 0; + S32 imei_len = -1; + + if (!imei_is_valid(p_imei)) + { + LOG(ERROR,"Invalid IMEI:%s",p_imei); + return GM_PARAM_ERROR; + } + + //写入IMEI号,停止自检启动定时器 + GM_StopTimer(GM_TIMER_SELF_CHECK_START); + auto_test_destroy(); + + for (index_string = 0; index_string < GM_IMEI_LEN - 1; index_string += 2) + { + imei_hex_write[index_hex++] = (util_chr(p_imei[index_string + 1]) << 4) + util_chr(p_imei[index_string]); + } + + imei_hex_write[index_hex++] = 0xF0 + util_chr(p_imei[GM_IMEI_LEN - 1]); + imei_hex_write[index_hex++] = 0xFF; + imei_hex_write[index_hex++] = 0xFF; + + + lib_index = GM_ReadNvramLid(NVRAM_EF_IMEI_IMEISV_LID); + GM_ReadWriteNvram(false, lib_index, 1, imei_hex_write, GM_IMEI_HEX_LEN, &imei_len); + + //写入长度正确,再读出来校验一次 + if (GM_IMEI_HEX_LEN == imei_len) + { + GM_ReadWriteNvram(true, lib_index, 1, imei_hex_read, GM_IMEI_HEX_LEN, &imei_len); + if (0 == GM_memcmp(imei_hex_write, imei_hex_read, GM_IMEI_HEX_LEN)) + { + GM_memcpy(s_gsm.imei, p_imei, GM_IMEI_LEN); + LOG(INFO,"Succeed to write IMEI:%s",p_imei); + return GM_SUCCESS; + } + else + { + LOG(ERROR,"IMEI check error,read:%s,write:%s",imei_hex_read,p_imei); + return GM_SYSTEM_ERROR; + } + } + else + { + LOG(ERROR,"error len:%d",imei_len); + return GM_SYSTEM_ERROR; + } +} + +static bool imei_is_valid(U8* p_imei) +{ + U8 index = 0; + if (GM_IMEI_LEN != GM_strlen((char*)p_imei)) + { + return false; + } + + for (index = 0; index < GM_IMEI_LEN; index++) + { + if (!util_isdigit(p_imei[index])) + { + return false; + } + } + return true; +} + + +U8 gsm_get_csq(void) +{ + S32 csq = GM_GetSignalValue(); + csq = csq < GM_CSQ_MIN ? GM_CSQ_MIN : csq; + csq = csq > GM_CSQ_MAX ? GM_CSQ_MAX : csq; + return (U8)csq; +} + +GM_ERRCODE gsm_get_cell_info(gm_cell_info_struct* p_cell_info) +{ + if (NULL == p_cell_info) + { + return GM_PARAM_ERROR; + } + + if (!s_gsm.sim_is_valid) + { + return GM_NOT_INIT; + } + + if (0 == s_gsm.cell_info.nbr_cell_num) + { + return GM_NOT_INIT; + } + + *p_cell_info = s_gsm.cell_info; + LOG(DEBUG,"Succeed to Get LBS"); + return GM_SUCCESS; +} + +static void check_sim_card(void) +{ + if (GM_CheckSimValid()) + { + if (!s_gsm.sim_is_valid) + { + LOG(DEBUG,"sim ready!"); + } + s_gsm.sim_is_valid = true; + } + else + { + s_gsm.sim_is_valid = false; + } + get_gsm_info(); +} + +static void get_gsm_info(void) +{ + GM_GetIccid(gsm_iccid_callback); + GM_GetLbsInfo(gsm_lbs_callback); + GM_memset(s_gsm.imsi, 0, sizeof(s_gsm.imsi)); + GM_GetImsi((char*)s_gsm.imsi); + GM_GetImei(gsm_imei_callback); +} + +//20秒内出现50次以上伪基站信号报警,20秒内没有伪基站信号报警恢复,报警最先间隔2分钟 +static void gsm_iccid_callback(void* p_msg) +{ + if (NULL == p_msg || GM_strlen((char*)p_msg) != GM_ICCID_LEN) + { + return; + } + GM_memcpy(s_gsm.iccid, p_msg, GM_ICCID_LEN); +} + +static void gsm_lbs_callback(void* p_msg) +{ + U32 delay = 0; + if (NULL == p_msg) + { + GM_StartTimer(GM_TIMER_GSM_CHECK_SIMCARD, TIM_GEN_1SECOND, check_sim_card); + return; + } + + GM_memcpy((void *)&s_gsm.cell_info, (void *)(p_msg), sizeof(gm_cell_info_struct)); + if (s_gsm.cell_info.nbr_cell_num == 0) + { + delay = TIM_GEN_1SECOND; + } + else + { + delay = TIM_GEN_1SECOND * 10; + } + GM_StartTimer(GM_TIMER_GSM_CHECK_SIMCARD, delay, check_sim_card); +} + +static void gsm_imei_callback(void* p_imei) +{ + if (NULL == p_imei || !imei_is_valid(p_imei)) + { + return; + } + if (GM_IMEI_LEN != GM_strlen((char*)s_gsm.imei)) + { + GM_memcpy(s_gsm.imei, p_imei, GM_IMEI_LEN); + } +} + +static void gsm_call_status_callback(void* p_msg) +{ + int status = *(int*) p_msg; + + switch(status) + { + case 0: + LOG(INFO,"phone calling."); + break; + case 1: + LOG(INFO,"call OK."); + break; + case 2: + LOG(INFO,"call hang."); + break; + } +} + +static void gsm_incomming_call(void* p_phone_number) +{ + if (NULL == p_phone_number) + { + return; + } + LOG(INFO,"incoming:%s", (char*)p_phone_number); + GM_CallAnswer(gsm_call_status_callback); +} + +static void gsm_fake_cell_callback(void* evt) +{ + u16* arfcn =(u16 *)evt; + LOG(DEBUG,"gsm_fake_cell_callback: arfcn=%d,%d,%d,%d",*arfcn, + s_gsm.fake_cell_count_per_20second, + s_gsm.fake_cell_count_per_120second, + s_gsm.fake_cell_continue_seconds); + + s_gsm.fake_cell_count_per_20second++; + s_gsm.fake_cell_count_per_120second++; +} + +//每20秒内有伪基站回调,连续6个20秒都有回调,且总次数大于50次报警 +static void check_fake_cell_alarm_timer_proc(void) +{ + if (s_gsm.fake_cell_count_per_20second > 0) + { + s_gsm.fake_cell_continue_seconds += GM_FAKE_CELL_CHECK_PERIOD; + } + else + { + s_gsm.fake_cell_count_per_120second = 0; + s_gsm.fake_cell_continue_seconds = 0; + system_state_set_fakecell_alarm(false); + } + + //20秒计数器清零 + s_gsm.fake_cell_count_per_20second = 0; + + if (s_gsm.fake_cell_continue_seconds >= GM_FAKE_CELL_CONTINUE_MAX_TIME) + { + //1、连续超过120秒 + //2、休眠状态 + //3、未定位 + if (s_gsm.fake_cell_count_per_120second > GM_FAKE_CELL_CONTINUE_MAX_COUNT + && system_state_get_work_state() == GM_SYSTEM_STATE_SLEEP + && !gps_is_fixed()) + { + AlarmInfo alarm_info; + alarm_info.type = ALARM_FAKE_CELL; + gps_service_push_alarm(&alarm_info); + system_state_set_fakecell_alarm(true); + } + s_gsm.fake_cell_count_per_120second = 0; + s_gsm.fake_cell_continue_seconds = 0; + } +} + diff --git a/src/hard_ware.c b/src/hard_ware.c new file mode 100644 index 0000000..6f8af2a --- /dev/null +++ b/src/hard_ware.c @@ -0,0 +1,1276 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: hard_ware.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-01 + * Description: 简单硬件(开关)读写操作封装,包括读取ADC的数值 + * Others: + * Function List: + 1. 创建hard_ware模块 + 2. 销毁hard_ware模块 + 3. 定时处理入口 + 4. 获取ACC输入状态 + 5. 设置GPS LED状态 + 6. 设置GSM LED状态 + 7. 设置断油电IO状态 + 8. 获取供电电源电压值 + 9. 设置内置电池充电状态(GS05) + * History: + 1. Date: 2019-03-01 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "g_sensor.h" +#include "hard_ware.h" +#include "gps.h" +#include "uart.h" +#include "system_state.h" +#include "log_service.h" +#include "config_service.h" +#include "utility.h" +#include "gps_service.h" +#include "applied_math.h" +#include "auto_test.h" +#include "gsm.h" +#include "gps_service.h" + +//输入:电池是否充满 +#define GM_GPS_CHARGE_LEVLE_GPIO_PIN GM_GPIO4 + +//输出:充电控制 +#define GM_GPS_CHARGE_CTROL_GPIO_PIN GM_GPIO5 + +//输出:GPS开关 +#define GM_GPS_POWER_CTROL_GPIO_PIN GM_GPIO19 + +//输出:断油电 +#define GM_RELAY_CTROL_GPIO_PIN GM_GPIO25 + +//输出:看门狗 +#define GM_WDT_CTROL_GPIO_PIN GM_GPIO28 + +//输入:ACC高低 +#define GM_ACC_LEVEL_GPIO_PIN GM_GPIO20 + +//输入:电源电压,ADC,通道ID +#define GM_POWER_VOLTAGE_ADC_CHANNEL 4 + +//计算电压平均值的次数 +#define GM_POWER_VOLTAGE_CALC_NUM 10 + +#define GM_HIGH_VOLTAGE_ALARM_THRESHHOLD_90V 96 + +#define GM_HIGH_VOLTAGE_ALARM_THRESHHOLD_36V 36 + +#define GM_BATTERY_HIGHEST_VOLTAGE 7.0 + +typedef struct +{ + bool inited; + //设备型号 + ConfigDeviceTypeEnum dev_type; + + //电源电压 + float power_voltage; + + //外部电池电量百分比(根据供电电压计算) + float extern_battery_percent; + + //电池电压 + float battery_voltage; + + bool battery_is_charging; + + bool battery_is_full; + + //电池充电电流 + float battery_charge_current; + + S32 battery_charge_time; + + U16 timer_ms; + + StateRecord power_off_alarm_record; + + StateRecord low_voltage_alarm_record; + + StateRecord high_voltage_alarm_record; + + StateRecord acc_record; + bool acc_line_is_valid; + U32 acc_low_but_run_seconds; + + StateRecord battery_is_full_record; + + bool gps_led_is_on; + bool gsm_led_is_on; + +}HardWare, *PHardWare; + +static HardWare s_hard_ware; + +static GM_ERRCODE init_gpio(void); + +static void hard_ware_read_voltage(void); + +static U8 hard_ware_calc_extern_voltage_grade(float voltage); + +static float hard_ware_calc_extern_battery_percent(float voltage, U8 voltage_grade); + +static void hard_ware_check_high_voltage_alarm(void); + +static void hard_ware_check_power_off_alarm(void); + +static void hard_ware_check_battery(void); + +static void hard_ware_check_acc(void); + +static void hard_ware_set_auto_defence(void); + +static void hard_ware_reboot_atonce(void); + +static bool hard_ware_has_acc_line(const ConfigDeviceTypeEnum dev_type); + +static bool hard_ware_has_battery(const ConfigDeviceTypeEnum dev_type); + +/** + * Function: 创建hard_ware模块 + * Description:创建hard_ware模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 管脚(参看电路图及管脚功能表) + */ +GM_ERRCODE hard_ware_create(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + + if (s_hard_ware.inited) + { + return GM_SUCCESS; + } + + ret = init_gpio(); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to init GPIO!"); + } + + s_hard_ware.inited = false; + s_hard_ware.dev_type = DEVICE_NONE; + s_hard_ware.power_voltage = 0.0; + s_hard_ware.extern_battery_percent = 0.0; + s_hard_ware.battery_is_charging = false; + s_hard_ware.battery_is_full = false; + s_hard_ware.battery_charge_current = 0; + s_hard_ware.battery_charge_time = -1; + s_hard_ware.timer_ms = 0; + s_hard_ware.gps_led_is_on = false; + s_hard_ware.gsm_led_is_on = false; + + LOG(DEBUG, "hard_ware_create"); + + s_hard_ware.power_off_alarm_record.state = system_state_get_power_off_alarm(); + s_hard_ware.power_off_alarm_record.true_state_hold_seconds = 0; + s_hard_ware.power_off_alarm_record.false_state_hold_seconds = 0; + + s_hard_ware.low_voltage_alarm_record.state = system_state_get_battery_low_voltage_alarm(); + s_hard_ware.low_voltage_alarm_record.true_state_hold_seconds = 0; + s_hard_ware.low_voltage_alarm_record.false_state_hold_seconds = 0; + + s_hard_ware.high_voltage_alarm_record.state = system_state_get_high_voltage_alarm(); + s_hard_ware.high_voltage_alarm_record.true_state_hold_seconds = 0; + s_hard_ware.high_voltage_alarm_record.false_state_hold_seconds = 0; + + s_hard_ware.acc_record.state = false; + s_hard_ware.acc_record.true_state_hold_seconds = 0; + s_hard_ware.acc_record.false_state_hold_seconds = 0; + s_hard_ware.acc_line_is_valid = true; + s_hard_ware.acc_low_but_run_seconds = 0; + + s_hard_ware.battery_is_full_record.state = true; + s_hard_ware.battery_is_full_record.true_state_hold_seconds = 0; + s_hard_ware.battery_is_full_record.false_state_hold_seconds = 0; + + + s_hard_ware.inited = true; + + return GM_SUCCESS; +} + +static GM_ERRCODE init_gpio(void) +{ + S32 ret = GM_SUCCESS; + ret = GM_GpioInit(GM_GPS_CHARGE_LEVLE_GPIO_PIN, PINDIRECTION_IN, PINLEVEL_LOW, PINPULLSEL_DISABLE); + if (GM_SUCCESS != ret) + { + LOG(FATAL,"Failed to init GM_GPS_CHARGE_LEVLE_GPIO_PIN!"); + return GM_HARD_WARE_ERROR; + } + + ret = GM_GpioInit(GM_GPS_CHARGE_CTROL_GPIO_PIN, PINDIRECTION_OUT, PINLEVEL_HIGH, PINPULLSEL_DISABLE); + if (GM_SUCCESS != ret) + { + LOG(FATAL,"Failed to init GM_GPS_CHARGE_CTROL_GPIO_PIN!"); + return GM_HARD_WARE_ERROR; + } + + ret = GM_GpioInit(GM_GPS_POWER_CTROL_GPIO_PIN, PINDIRECTION_OUT, PINLEVEL_HIGH, PINPULLSEL_DISABLE); + if (GM_SUCCESS != ret) + { + LOG(FATAL,"Failed to init GM_GPS_POWER_CTROL_GPIO_PIN!"); + return GM_HARD_WARE_ERROR; + } + + ret = GM_GpioInit(GM_RELAY_CTROL_GPIO_PIN, PINDIRECTION_OUT, PINLEVEL_LOW, PINPULLSEL_PULLDOWN); + if (GM_SUCCESS != ret) + { + LOG(FATAL,"Failed to init GM_RELAY_CTROL_GPIO_PIN!"); + return GM_HARD_WARE_ERROR; + } + + ret = GM_GpioInit(GM_WDT_CTROL_GPIO_PIN, PINDIRECTION_OUT, PINLEVEL_LOW, PINPULLSEL_DISABLE); + if (GM_SUCCESS != ret) + { + LOG(FATAL,"Failed to init GM_WDT_CTROL_GPIO_PIN!"); + return GM_HARD_WARE_ERROR; + } + + ret = GM_GpioInit(GM_ACC_LEVEL_GPIO_PIN, PINDIRECTION_IN, PINLEVEL_HIGH, PINPULLSEL_PULLUP); + if (GM_SUCCESS != ret) + { + LOG(FATAL,"Failed to init GM_ACC_LEVEL_GPIO_PIN!"); + return GM_HARD_WARE_ERROR; + } + return GM_SUCCESS; +} + +/** + * Function: 销毁hard_ware模块 + * Description:销毁hard_ware模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_destroy(void) +{ + s_hard_ware.inited = false; + return GM_SUCCESS; +} + +GM_ERRCODE hard_ware_timer_proc(void) +{ + U8 extern_battery_voltage_grade = 0; + u16 device_type; + + + if (false == s_hard_ware.inited) + { + return GM_NOT_INIT; + } + + if (GM_SYSTEM_STATE_WORK == system_state_get_work_state()) + { + s_hard_ware.timer_ms += TIM_GEN_10MS; + } + else + { + s_hard_ware.timer_ms += TIM_GEN_1SECOND; + } + + //100ms读一次数据 + if (s_hard_ware.timer_ms % TIM_GEN_100MS == 0) + { + hard_ware_read_voltage(); + } + + //1秒以内不做其它处理 + if (s_hard_ware.timer_ms < TIM_GEN_1SECOND) + { + return GM_SUCCESS; + } + + config_service_get(CFG_DEVICETYPE, TYPE_SHORT, &device_type , sizeof(device_type)); + + s_hard_ware.dev_type = (ConfigDeviceTypeEnum)device_type; + + if (hard_ware_has_acc_line(s_hard_ware.dev_type)) + { + hard_ware_check_acc(); + } + else + { + system_state_set_acc_is_line_mode(false); + } + + //设备类型未知的时候也要能充电 + if (hard_ware_has_battery(s_hard_ware.dev_type) || DEVICE_NONE == s_hard_ware.dev_type) + { + hard_ware_check_battery(); + } + + //检查电源电压过高报警 + hard_ware_check_high_voltage_alarm(); + + //检查断电报警 + hard_ware_check_power_off_alarm(); + + //计算外部电压等级并保存到系统状态中 + extern_battery_voltage_grade = hard_ware_calc_extern_voltage_grade(s_hard_ware.power_voltage); + system_state_set_extern_battery_voltage_grade(extern_battery_voltage_grade); + + //计算外部电池百分比(根据电源电压估算) + s_hard_ware.extern_battery_percent = hard_ware_calc_extern_battery_percent(s_hard_ware.power_voltage, extern_battery_voltage_grade); + + //毫秒计时器清零 + s_hard_ware.timer_ms = 0; + return GM_SUCCESS; +} + +static ConfigDeviceTypeEnum four_line_devtypes[] = +{ + DEVICE_GS03A, + DEVICE_AS03A, + DEVICE_GS07A, + DEVICE_AS07A, + DEVICE_GS03H, + DEVICE_GS05A, + DEVICE_GS05H, + DEVICE_GM06E +}; + +static bool hard_ware_has_acc_line(const ConfigDeviceTypeEnum dev_type) +{ + U8 index = 0; + for (index = 0; index < sizeof(four_line_devtypes)/sizeof(ConfigDeviceTypeEnum); ++index) + { + if (dev_type == four_line_devtypes[index]) + { + return true; + } + } + + return false; +} + +static ConfigDeviceTypeEnum battery_devtypes[] = +{ + DEVICE_GS03A, //4线单sensor 有电池 + DEVICE_AS03A, //4线单sensor 有电池 + DEVICE_GS03F, //2线单sensor 有电池 + DEVICE_AS03F, //2线单sensor 有电池 + DEVICE_GS07B, //2线单sensor 有电池90V + DEVICE_AS07B, //2线单sensor 有电池90V + DEVICE_GS03H, //4线双sensor,同03A + DEVICE_GS05A, //4线单sensor 90V,有电池 + DEVICE_GS05F, //2线单sensor 90V,有电池 + DEVICE_GS05H, //4线双sensor 90V,有电池 + DEVICE_GM06E, //同GS03A,客户定制 +}; + +static bool hard_ware_has_battery(const ConfigDeviceTypeEnum dev_type) +{ + U8 index = 0; + for (index = 0; index < sizeof(battery_devtypes)/sizeof(ConfigDeviceTypeEnum); ++index) + { + if (dev_type == battery_devtypes[index]) + { + return true; + } + } + return false; +} + +GM_ERRCODE hard_ware_get_acc_level(bool* p_state) +{ + if (false == s_hard_ware.inited || NULL == p_state) + { + return GM_NOT_INIT; + } + if(system_state_get_acc_is_line_mode()) + { + *p_state = s_hard_ware.acc_record.state; + LOG(DEBUG,"ACC from line is %d",*p_state); + } + else + { + *p_state = (GM_SYSTEM_STATE_WORK == system_state_get_work_state()); + LOG(DEBUG,"ACC from sensor is %d",*p_state); + } + return GM_SUCCESS; +} + +GM_ERRCODE hard_ware_get_acc_line_level(bool* p_state) +{ + if (false == s_hard_ware.inited || NULL == p_state) + { + return GM_NOT_INIT; + } + if(system_state_get_acc_is_line_mode()) + { + *p_state = s_hard_ware.acc_record.state; + LOG(DEBUG,"ACC from line is %d",*p_state); + } + else + { + *p_state = false; + LOG(DEBUG,"ACC line is invalid,return false"); + } + return GM_SUCCESS; +} + +/** + * Function: 设置GPS LED状态 + * Description: + * Input: state:true——亮灯;false——灭灯 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_set_gps_led(bool is_on) +{ + S32 ret = 0; + + + if (false == s_hard_ware.inited) + { + return GM_NOT_INIT; + } + + if (s_hard_ware.gps_led_is_on == is_on) + { + return GM_SUCCESS; + } + else + { + s_hard_ware.gps_led_is_on = is_on; + + ret = GM_IsinkBacklightCtrl(is_on,is_on); + if (0 == ret) + { + return GM_SUCCESS; + } + else + { + LOG(ERROR,"Failed to GM_IsinkBacklightCtrl,ret=%d!",ret); + return GM_HARD_WARE_ERROR; + } + } +} + +/** + * Function: 设置GSM LED状态 + * Description: + * Input: state:true——亮灯;false——灭灯 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_set_gsm_led(bool is_on) +{ + S32 ret = 0; + if (false == s_hard_ware.inited) + { + return GM_NOT_INIT; + } + + if (s_hard_ware.gsm_led_is_on == is_on) + { + return GM_SUCCESS; + } + else + { + s_hard_ware.gsm_led_is_on = is_on; + + ret = GM_KpledLevelCtrl(is_on,is_on); + if (0 == ret) + { + return GM_SUCCESS; + } + else + { + LOG(ERROR,"Failed to GM_KpledLevelCtrl,ret=%d!",ret); + return GM_HARD_WARE_ERROR; + } + } +} + +/** + * Function: 设置断油电IO状态 + * Description: + * Input: state:true——断油电;false——恢复油电 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_set_relay(bool state) +{ + if (false == s_hard_ware.inited) + { + return GM_NOT_INIT; + } + GM_GpioSetLevel(GM_RELAY_CTROL_GPIO_PIN,(Enum_PinLevel)state); + return GM_SUCCESS; +} + +/** + * Function: 设置看门狗IO电平 + * Description: + * Input: state:true——高电平;false——低电平 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_set_watchdog(bool state) +{ + if (false == s_hard_ware.inited) + { + return GM_NOT_INIT; + } + //总是返回0,不需要检查是否执行成功 + GM_GpioSetLevel(GM_WDT_CTROL_GPIO_PIN, (Enum_PinLevel)state); + return GM_SUCCESS; +} + + +/** + * Function: 获取供电电源电压值 + * Description:单位伏特(v) + * Input: 无 + * Output: p_voltage:电压值指针 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_get_power_voltage(float* p_voltage) +{ + if (false == s_hard_ware.inited || NULL == p_voltage) + { + return GM_NOT_INIT; + } + *p_voltage = s_hard_ware.power_voltage; + return GM_SUCCESS; +} + +GM_ERRCODE hard_ware_get_internal_battery_voltage(float* p_voltage) +{ + if (false == s_hard_ware.inited || NULL == p_voltage) + { + LOG(ERROR,"Has not inited hardware!"); + return GM_NOT_INIT; + } + *p_voltage = s_hard_ware.battery_voltage; + return GM_SUCCESS; +} + +bool hard_ware_battery_is_charging(void) +{ + return s_hard_ware.battery_is_charging; +} + +bool hard_ware_battery_is_full(void) +{ + return s_hard_ware.battery_is_full; +} + + +GM_ERRCODE hard_ware_get_extern_battery_percent(U8* p_percent) +{ + if (false == s_hard_ware.inited || NULL == p_percent) + { + return GM_NOT_INIT; + } + *p_percent = applied_math_round(s_hard_ware.extern_battery_percent); + return GM_SUCCESS; +} + +GM_ERRCODE hard_ware_get_internal_battery_percent(U8* p_percent) +{ + if (!s_hard_ware.inited) + { + return GM_NOT_INIT; + } + + if (NULL == p_percent) + { + return GM_PARAM_ERROR; + } + + if (s_hard_ware.battery_voltage >= 4.15) + { + *p_percent = 100; + } + else if (s_hard_ware.battery_voltage <= 3.50) + { + *p_percent = 0; + } + else + { + *p_percent = applied_math_round((s_hard_ware.battery_voltage - 3.50) * 100 / 0.65); + } + return GM_SUCCESS; + +} + +GM_ERRCODE hard_ware_get_internal_battery_level(U8* p_level) +{ + if (!s_hard_ware.inited) + { + return GM_NOT_INIT; + } + + if (NULL == p_level) + { + return GM_PARAM_ERROR; + } + + if (s_hard_ware.battery_voltage <= 3.45f) + { + *p_level = 0; + } + else if (s_hard_ware.battery_voltage <= 3.5f) + { + *p_level = 1; + } + else if (s_hard_ware.battery_voltage <= 3.6f) + { + *p_level = 2; + } + else if (s_hard_ware.battery_voltage <= 3.8f) + { + *p_level = 3; + } + else if (s_hard_ware.battery_voltage <= 3.95f) + { + *p_level = 4; + } + else if (s_hard_ware.battery_voltage <= 4.1f) + { + *p_level = 5; + } + else + { + *p_level = 6; + } + return GM_SUCCESS; +} + + +static void hard_ware_read_voltage(void) +{ + u32 realtime_voltage = 0; + float power_voltage = 0; + if(0xFFFF == GM_AdcRead(GM_POWER_VOLTAGE_ADC_CHANNEL,&realtime_voltage)) + { + LOG(ERROR,"Failed to GM_AdcRead!"); + return; + } + + power_voltage = realtime_voltage * 145.6 /1024.0; + + //补偿二极管压降 + if (power_voltage > 0.5) + { + power_voltage += (0.7 + 0.35); + } + if(power_voltage < 7) + { + s_hard_ware.power_voltage = 0; + } + else + { + if (s_hard_ware.power_voltage > 7) + { + s_hard_ware.power_voltage = applied_math_lowpass_filter(s_hard_ware.power_voltage, power_voltage, 0.5); + } + else + { + s_hard_ware.power_voltage = power_voltage; + } + } + //LOG(DEBUG,"power_voltage=%f",s_hard_ware.power_voltage); +} + +//电压等级标准 +static U8 voltage_grade_standard[]={1,12,24,36,48,60,72,84,96}; + +/** + * Function: 判断电压等级 + * Description: + * Input: voltage:电压 + * Output: + * Return: 电压等级:0——未知,其它情况返回对应12,24,36,48,60,72,84,96 + * Others: + */ +static U8 hard_ware_calc_extern_voltage_grade(float voltage) +{ + U8 index = 0; + + U8 array_size = sizeof(voltage_grade_standard)/sizeof(U8); + + if (voltage > voltage_grade_standard[array_size -1]) + { + return voltage_grade_standard[array_size -1]; + } + for (index = 0; index < array_size - 1; ++index) + { + if (voltage > voltage_grade_standard[index] + 6 && voltage <= voltage_grade_standard[index + 1] + 6) + { + return voltage_grade_standard[array_size -1]; + } + } + return 0; +} + +//根据电压值和电压等级计算电量百分比,返回[0,100.0] +static float hard_ware_calc_extern_battery_percent(float voltage, U8 voltage_grade) +{ + float extern_battery_percent = 0; + + switch(voltage_grade) + { + case 0: + extern_battery_percent = 0; + break; + + case 12: + if (voltage >= 12) + { + extern_battery_percent = 100; + } + else + { + extern_battery_percent = 0; + } + break; + + case 24: + if (voltage >= 24) + { + extern_battery_percent = 100; + } + else + { + extern_battery_percent = 0; + } + break; + + case 36: + if (voltage > 33) + { + extern_battery_percent = (voltage - 33) * 100 /9; + } + else + { + extern_battery_percent = 0; + } + break; + + case 48: + if (voltage > 42) + { + extern_battery_percent = (voltage - 42) * 100 /14; + } + else + { + extern_battery_percent = 0; + } + break; + + case 60: + if (voltage > 56) + { + extern_battery_percent = (voltage - 56) * 100 /14; + } + else + { + extern_battery_percent = 0; + } + break; + + case 72: + if (voltage > 70) + { + extern_battery_percent = (voltage - 70) * 100 /14; + } + else + { + extern_battery_percent = 0; + } + break; + + case 84: + if (voltage > 83) + { + extern_battery_percent = (voltage - 83) * 100 /13; + } + else + { + extern_battery_percent = 0; + } + break; + + default: + extern_battery_percent = 100; + break; + } + + extern_battery_percent = (extern_battery_percent > 100) ? 100 : extern_battery_percent; + + return extern_battery_percent; + +} + +static void hard_ware_check_high_voltage_alarm(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + U16 voltage_alarm_hold_time_sec = 5; + bool is_90v_power = false; + U8 high_voltage_alarm_threshhold = GM_HIGH_VOLTAGE_ALARM_THRESHHOLD_36V; + JsonObject* p_log_root = NULL; + GM_CHANGE_ENUM alarm_state_change = GM_NO_CHANGE; + AlarmInfo alarm_info; + + ret = config_service_get(CFG_POWER_CHECK_TIME, TYPE_SHORT, &voltage_alarm_hold_time_sec, sizeof(voltage_alarm_hold_time_sec)); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to config_service_get,ret=%d",ret); + return; + } + + ret = config_service_get(CFG_IS_90V_POWER, TYPE_BOOL, &is_90v_power, sizeof(bool)); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to config_service_get,ret=%d",ret); + return; + } + + high_voltage_alarm_threshhold = is_90v_power ? GM_HIGH_VOLTAGE_ALARM_THRESHHOLD_90V : GM_HIGH_VOLTAGE_ALARM_THRESHHOLD_36V; + alarm_state_change = util_check_state_change(s_hard_ware.power_voltage > high_voltage_alarm_threshhold, &s_hard_ware.high_voltage_alarm_record,voltage_alarm_hold_time_sec,voltage_alarm_hold_time_sec); + + if (GM_CHANGE_TRUE == alarm_state_change) + { + //报电压过高报警 + alarm_info.type = ALARM_POWER_HIGH; + alarm_info.info = (u16)s_hard_ware.power_voltage; + ret = gps_service_push_alarm(&alarm_info); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to gps_service_push_alarm(ALARM_POWER_HIGH),ret=%d", ret); + } + + system_state_set_high_voltage_alarm(true); + + //上传日志 + p_log_root = json_create(); + json_add_string(p_log_root, "event", ("high_voltage_alarm")); + json_add_double(p_log_root, "voltage", s_hard_ware.power_voltage); + log_service_upload(FATAL,p_log_root); + } + else if(GM_CHANGE_FALSE == alarm_state_change) + { + + system_state_set_high_voltage_alarm(false); + + //上传日志 + p_log_root = json_create(); + json_add_string(p_log_root, "event", ("high_voltage_alarm recover")); + json_add_double(p_log_root, "voltage", s_hard_ware.power_voltage); + log_service_upload(FATAL,p_log_root); + } + else + { + } + +} + +static void hard_ware_check_power_off_alarm(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + U16 voltage_alarm_hold_time_sec = 0; + JsonObject* p_log_root = NULL; + GM_CHANGE_ENUM alarm_state_change = GM_NO_CHANGE; + AlarmInfo alarm_info; + U8 power_off_alarm_disable = 0; + + config_service_get(CFG_POWER_CHECK_TIME, TYPE_SHORT, &voltage_alarm_hold_time_sec, sizeof(voltage_alarm_hold_time_sec)); + config_service_get(CFG_CUTOFFALM_DISABLE, TYPE_BYTE, &power_off_alarm_disable, sizeof(power_off_alarm_disable)); + + if (power_off_alarm_disable) + { + return; + } + + alarm_state_change = util_check_state_change(s_hard_ware.power_voltage < GM_BATTERY_HIGHEST_VOLTAGE ,&s_hard_ware.power_off_alarm_record,voltage_alarm_hold_time_sec,10); + + if (GM_CHANGE_TRUE == alarm_state_change) + { + //报断电报警 + alarm_info.type = ALARM_POWER_OFF; + alarm_info.info = (u16)s_hard_ware.power_voltage; + ret = gps_service_push_alarm(&alarm_info); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to gps_service_push_alarm(ALARM_POWER_OFF),ret=%d", ret); + } + + system_state_set_power_off_alarm(true); + + //上传日志 + p_log_root = json_create(); + json_add_string(p_log_root, "event", ("power_off_alarm")); + json_add_double(p_log_root, "voltage", s_hard_ware.power_voltage); + log_service_upload(DEBUG,p_log_root); + } + else if(GM_CHANGE_FALSE == alarm_state_change) + { + system_state_set_power_off_alarm(false); + + //上传日志 + p_log_root = json_create(); + json_add_string(p_log_root, "event", ("power_off_alarm recover")); + json_add_double(p_log_root, "voltage", s_hard_ware.power_voltage); + log_service_upload(DEBUG,p_log_root); + + } + else + { + //do nothing + } + +} + +static void hard_ware_check_battery(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + U16 voltage_alarm_hold_time_sec = 0; + JsonObject* p_log_root = NULL; + gm_chr_status_struct charge_status = {0}; + bool app_battery_mgr = true; + bool current_alarm_state = false; + GM_CHANGE_ENUM alarm_state_change = GM_NO_CHANGE; + GM_CHANGE_ENUM battery_is_full_change = GM_NO_CHANGE; + AlarmInfo alarm_info; + bool voltage_alarm_disable = false; + + U16 min_charge_time = 0; + + ret = config_service_get(CFG_POWER_CHECK_TIME, TYPE_SHORT, &voltage_alarm_hold_time_sec, sizeof(voltage_alarm_hold_time_sec)); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to config_service_get(CFG_POWER_CHECK_TIME),ret=%d",ret); + return; + } + + ret = config_service_get(CFG_APP_BATTERT_MGR, TYPE_BOOL, &app_battery_mgr, sizeof(app_battery_mgr)); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to config_service_get(CFG_APP_BATTERT_MGR),ret=%d", ret); + return; + } + + config_service_get(CFG_POWER_CHARGE_MIN_TIME, TYPE_SHORT, &min_charge_time, sizeof(min_charge_time)); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to config_service_get(CFG_APP_BATTERT_MGR),ret=%d", ret); + return; + } + + //GS05系列没有使用MTK内部充电管理,这些数据对05无效 + ret = (GM_ERRCODE)GM_GetChrStatus((U8* )&charge_status); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to GM_GetChrStatus(),ret=%d", ret); + return; + } + + s_hard_ware.battery_voltage = charge_status.VBAT/1000000.0; + s_hard_ware.battery_is_full = GM_GpioGetLevel(GM_GPS_CHARGE_LEVLE_GPIO_PIN); + + LOG(DEBUG,"battery voltage:%f,charge_current:%f,is_charging:%d,is_full:%d",s_hard_ware.battery_voltage,s_hard_ware.battery_charge_current,s_hard_ware.battery_is_charging,s_hard_ware.battery_is_full); + + //即使型号未知也一直充电 + GM_GpioSetLevel(GM_GPS_CHARGE_CTROL_GPIO_PIN,PINLEVEL_LOW); + //GS05系列,应用层控制 + if (app_battery_mgr) + { + battery_is_full_change = util_check_state_change(s_hard_ware.battery_is_full, &s_hard_ware.battery_is_full_record, voltage_alarm_hold_time_sec,voltage_alarm_hold_time_sec); + if (GM_CHANGE_TRUE == battery_is_full_change || s_hard_ware.power_voltage < GM_BATTERY_HIGHEST_VOLTAGE) + { + s_hard_ware.battery_is_charging = false; + s_hard_ware.battery_charge_current = 0.02; + //GM_GpioSetLevel(GM_GPS_CHARGE_CTROL_GPIO_PIN,PINLEVEL_HIGH); + LOG(DEBUG,"is full"); + } + else if(GM_CHANGE_FALSE == battery_is_full_change) + { + s_hard_ware.battery_is_charging = true; + s_hard_ware.battery_charge_current = 0.06; + //GM_GpioSetLevel(GM_GPS_CHARGE_CTROL_GPIO_PIN,PINLEVEL_LOW); + LOG(DEBUG,"is not full."); + } + else + { + LOG(DEBUG,"Dont change charge state."); + } + } + else + { + LOG(DEBUG,"MTK charge."); + s_hard_ware.battery_charge_current = charge_status.ICHARGE > 0 ? charge_status.ICHARGE/1000000.0 : 0.0; + s_hard_ware.battery_is_charging = (charge_status.chr_plug == CHARGER_PLUG_IN); + } + + system_state_set_has_started_charge(s_hard_ware.battery_is_charging); + config_service_get(CFG_LOWBATTALM_DISABLE, TYPE_BYTE, &voltage_alarm_disable, sizeof(voltage_alarm_disable)); + + //正在充电或者报警关闭 + if (s_hard_ware.battery_is_charging || voltage_alarm_disable) + { + return; + } + + current_alarm_state = s_hard_ware.low_voltage_alarm_record.state; + if (s_hard_ware.battery_voltage > 3.80) + { + current_alarm_state = false; + } + else if (s_hard_ware.battery_voltage < 3.65) + { + current_alarm_state = true; + } + else + { + } + + alarm_state_change = util_check_state_change(current_alarm_state,&s_hard_ware.low_voltage_alarm_record,voltage_alarm_hold_time_sec,min_charge_time); + if (GM_CHANGE_TRUE == alarm_state_change) + { + //报低电压报警 + alarm_info.type = ALARM_BATTERY_LOW; + alarm_info.info = (u16)s_hard_ware.battery_voltage; + ret = gps_service_push_alarm(&alarm_info); + if (GM_SUCCESS != ret) + { + LOG(ERROR, "Failed to gps_service_push_alarm(ALARM_BATTERY_LOW),ret=%d", ret); + } + system_state_set_battery_low_voltage_alarm(true); + + + //上传日志 + p_log_root = json_create(); + json_add_string(p_log_root, "event", ("low_voltage_alarm")); + log_service_upload(DEBUG,p_log_root); + } + else if(GM_CHANGE_FALSE == alarm_state_change) + { + system_state_set_battery_low_voltage_alarm(false); + + //上传日志 + p_log_root = json_create(); + json_add_string(p_log_root, "event", ("low_voltage_alarm recover")); + json_add_double(p_log_root, "voltage", s_hard_ware.power_voltage); + log_service_upload(DEBUG,p_log_root); + } + else + { + //do nothing + } + + return; +} + +static void hard_ware_check_acc(void) +{ + //硬件设计上,高电平是没有接ACC,低电平是接了ACC,所以这里要取反 + bool acc_level = !GM_GpioGetLevel(GM_ACC_LEVEL_GPIO_PIN); + GM_CHANGE_ENUM change = GM_NO_CHANGE; + U16 auto_defence_delay = 0; + bool is_defence_by_hand = false; + + config_service_get(CFG_IS_MANUAL_DEFENCE,TYPE_BOOL, &is_defence_by_hand, sizeof(is_defence_by_hand)); + config_service_get(CFG_AUTO_DEFENCE_DELAY, TYPE_SHORT, &auto_defence_delay, sizeof(auto_defence_delay)); + + change = util_check_state_change(acc_level,&s_hard_ware.acc_record,5,5); + if (GM_CHANGE_TRUE == change) + { + auto_test_acc_on(); + if(!is_defence_by_hand) + { + GM_StopTimer(GM_TIMER_HARDWARE_AUTODEFENCE); + system_state_set_defence(false); + } + } + else if(GM_CHANGE_FALSE == change) + { + auto_test_acc_off(); + if(!is_defence_by_hand) + { + GM_StartTimer(GM_TIMER_HARDWARE_AUTODEFENCE, auto_defence_delay, hard_ware_set_auto_defence); + } + } + else + { + //do nothing + } + + if (s_hard_ware.acc_record.state == false && system_state_get_vehicle_state() == VEHICLE_STATE_RUN) + { + s_hard_ware.acc_low_but_run_seconds++; + } + + if(s_hard_ware.acc_record.state) + { + s_hard_ware.acc_low_but_run_seconds = 0; + } + + //连续24小时ACC高 ————>接常电 + //连续1分钟运动状态ACC低————>没接ACC线 + if (s_hard_ware.acc_record.true_state_hold_seconds > SECONDS_PER_DAY || s_hard_ware.acc_low_but_run_seconds > SECONDS_PER_HOUR) + { + //ACC无效,取消自动设防 + system_state_set_acc_is_line_mode(false); + if(!is_defence_by_hand) + { + GM_StopTimer(GM_TIMER_HARDWARE_AUTODEFENCE); + system_state_set_defence(false); + } + } + else + { + system_state_set_acc_is_line_mode(true); + } + + //如果ACC状态发生变化,立即触发一次心跳 + if (change != GM_NO_CHANGE) + { + gps_service_heart_atonce(); + } +} + +static void hard_ware_set_auto_defence(void) +{ + system_state_set_defence(true); +} + +static void hard_ware_reboot_atonce(void) +{ + gps_service_save_to_history_file(); + if (0 == GM_SystemReboot()) + { + LOG(FATAL,"Failed to GM_SystemReboot!"); + } +} + +/** + * Function: 重启 + * Description:重启整个系统软件 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_reboot(const BootReason reason,U16 delay_seconds) +{ + //快速重复调用这个函数启动定时器会取消之前设置的定时器,导致无法重启,因此要用个静态变量记录下来 + static bool has_reboot = false; + system_state_set_boot_reason(reason); + + if (0 == delay_seconds) + { + hard_ware_reboot_atonce(); + has_reboot = true; + } + else + { + if(!has_reboot) + { + GM_StartTimer(GM_TIMER_HARDWARE_REBOOT,delay_seconds*TIM_GEN_1SECOND,hard_ware_reboot_atonce); + has_reboot = true; + } + } + return GM_SUCCESS; +} + +/** + * Function: 休眠 + * Description:使系统休眠 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_sleep(void) +{ + if (0 == ZG_SleepEnable()) + { + return GM_HARD_WARE_ERROR; + } + else + { + //上传日志 + JsonObject* p_log_root = json_create();; + json_add_string(p_log_root, "event", ("sleep")); + json_add_int(p_log_root, "csq", gsm_get_csq()); + log_service_upload(INFO,p_log_root); + return GM_SUCCESS; + } +} + +GM_ERRCODE hard_ware_close_gps(void) +{ + GM_GpioSetLevel(GM_GPS_POWER_CTROL_GPIO_PIN, PINLEVEL_LOW); + return GM_SUCCESS; +} + + +/** + * Function: 唤醒 + * Description:使系统唤醒 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE hard_ware_awake(void) +{ + if (0 == ZG_SleepDisable()) + { + return GM_HARD_WARE_ERROR; + } + else + { + //上传日志 + JsonObject* p_log_root = json_create(); + json_add_string(p_log_root, "event", ("awake")); + json_add_int(p_log_root, "csq", gsm_get_csq()); + json_add_int(p_log_root, "run time", system_state_get_start_time()); + log_service_upload(INFO,p_log_root); + return GM_SUCCESS; + } +} + +GM_ERRCODE hard_ware_open_gps(void) +{ + GM_GpioSetLevel(GM_GPS_POWER_CTROL_GPIO_PIN, PINLEVEL_HIGH); + GM_SysMsdelay(10); + GM_GpioSetLevel(GM_GPS_POWER_CTROL_GPIO_PIN, PINLEVEL_HIGH); + GM_SysMsdelay(10); + GM_GpioSetLevel(GM_GPS_POWER_CTROL_GPIO_PIN, PINLEVEL_HIGH); + return GM_SUCCESS; +} + diff --git a/src/json.c b/src/json.c new file mode 100644 index 0000000..3e785e8 --- /dev/null +++ b/src/json.c @@ -0,0 +1,235 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: log_service.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-05-21 + * Description: 来自于cJSON,删除了大部分不用的功能和特性,print函数完全重写 + * Others: + * Function List: + 1. 创建对象 + 2. 添加数字 + 3. 添加字符串 + 4. 打印到字符串 + 5. 释放内存 + * History: + 1. Date: 2019-03-01 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include +#include +#include "json.h" + +static char* json_strdup(const char* string) +{ + U8 length = 0; + char* copy = NULL; + + if (NULL == string) + { + return NULL; + } + + length = GM_strlen(string) + 1; + copy = (char*)GM_MemoryAlloc(length); + if (NULL == copy) + { + return NULL; + } + GM_memcpy(copy, string, length - 1); + copy[length - 1] = '\0'; + return copy; +} + +static void suffix_object(JsonObject* prev, JsonObject* item) +{ + prev->next = (struct JsonObject*)item; + item->prev = (struct JsonObject*)prev; +} + + +static bool add_item_to_array(JsonObject* array, JsonObject* item) +{ + JsonObject* child = NULL; + + if ((item == NULL) || (array == NULL)) + { + return false; + } + + child = (JsonObject*)array->child; + + if (child == NULL) + { + array->child = (struct JsonObject*)item; + } + else + { + while (child->next) + { + child = (JsonObject*)child->next; + } + suffix_object(child, item); + } + return true; +} + + +static bool add_item_to_object(JsonObject* object, const char* name, JsonObject* item) +{ + if ((object == NULL) || (name == NULL) || (item == NULL)) + { + return false; + } + + item->name = json_strdup(name); + return add_item_to_array(object, item); +} + +static JsonObject* json_create_int(double value) +{ + JsonObject* item = json_create(); + if(item) + { + item->type = JSON_INT; + item->int_value = value; + } + + return item; +} + +static JsonObject* json_create_double(double value) +{ + JsonObject* item = json_create(); + if(item) + { + item->type = JSON_DOUBLE; + item->double_value = value; + } + + return item; +} + +static JsonObject* json_create_string(const char *string) +{ + JsonObject* item = json_create(); + if(item) + { + item->type = JSON_STRING; + item->str_value = json_strdup(string); + } + return item; +} + +JsonObject* json_create(void) +{ + JsonObject* p_object = (JsonObject*)GM_MemoryAlloc(sizeof(JsonObject)); + if (p_object) + { + GM_memset(p_object, 0, sizeof(JsonObject)); + p_object->type = JSON_OBJECT; + } + return p_object; +} + +void json_destroy(JsonObject* p_object) +{ + JsonObject* pChild; + pChild = (JsonObject*)p_object->child; + while(NULL != pChild) + { + JsonObject* pNext; + if (JSON_STRING == pChild->type) + { + GM_MemoryFree(pChild->str_value); + } + GM_MemoryFree(pChild->name); + + pNext = (JsonObject*)pChild->next; + GM_MemoryFree(pChild); + + pChild = (JsonObject*)pNext; + } + GM_MemoryFree(p_object); +} + +JsonObject* json_add_int(JsonObject* p_object, const char* name, const int value) +{ + JsonObject* int_item = json_create_int(value); + if (add_item_to_object(p_object, name, int_item)) + { + return int_item; + } + return NULL; +} + +JsonObject* json_add_double(JsonObject* p_object, const char* name, const double value) +{ + JsonObject* double_item = json_create_double(value); + if (add_item_to_object(p_object, name, double_item)) + { + return double_item; + } + return NULL; +} + +JsonObject* json_add_string(JsonObject* p_object, const char* name, const char* string) +{ + JsonObject* string_item = json_create_string(string); + if (add_item_to_object(p_object, name, string_item)) + { + return string_item; + } + return NULL; +} + +bool json_print_to_buffer(JsonObject* object, char* buffer, const int length) +{ + U16 index = 0; + U8 item_num = 0; + JsonObject* item = NULL; + + if(NULL == buffer || NULL == object) + { + return false; + } + buffer[index++] = '{'; + + item = (JsonObject*)object->child; + while(NULL != item) + { + if (0 != item_num) + { + buffer[index++] = ','; + } + index += sprintf(buffer+index, "\"%s\"", item->name); + buffer[index++] = ':'; + switch ((item->type) & 0xFF) + { + case JSON_INT: + index += GM_sprintf(buffer+index, "%d", item->int_value); + break; + case JSON_DOUBLE: + index += GM_sprintf(buffer+index, "%.2f", item->double_value); + break; + case JSON_STRING: + index += GM_sprintf(buffer+index, "\"%s\"", item->str_value); + break; + default: + return false; + } + item = (JsonObject*)item->next; + item_num++; + } + buffer[index++] = '}'; + buffer[index++] = '\0'; + return true; +} + + diff --git a/src/led.c b/src/led.c new file mode 100644 index 0000000..6a8a590 --- /dev/null +++ b/src/led.c @@ -0,0 +1,179 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: led.c + * Author: 王志华 + * Version: 1.0 + * Date: 2019-04-08 + * Description: 封装LED接口 + * Others: 提供GSM、GPS指示灯常亮、灭、闪烁等功能 + * Function List: + 1. 创建led模块 + 2. 销毁led模块 + 3. 定时处理入口 + 4. + + * History: + 1. Date: 2019-04-08 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include +#include "led.h" +#include "hard_ware.h" +#include "log_service.h" +#include "system_state.h" + +//处理LED定时器周期(毫秒) +#define GM_LED_PROC_PERIOD_MS 10 + +//GSM指示灯开始时快闪的时间(秒) +#define GM_GSM_LED_QUICK_FLASH_SECONDS 7 + +//指示灯快闪周期(毫秒) +#define GM_LED_QUICK_FLASH_PERIOD_MS 100 + +//指示灯慢闪亮灯时长(毫秒) +#define GM_LED_SLOW_FLASH_ON_MS 100 + +//指示灯慢闪灭灯时长(毫秒) +#define GM_LED_SLOW_FLASH_OFF_MS 1900 + + + + +typedef struct +{ + U32 start_time_ms; + + bool gsm_led_is_on; + U16 gsm_led_state_time; + LedState gsm_state; + + bool gps_led_is_on; + U16 gps_led_state_time; + LedState gps_state; + + +}Led; + +static Led s_led; + +static void gsm_led_proc(void); + +static void gps_led_proc(void); + + +GM_ERRCODE led_create(void) +{ + s_led.start_time_ms = 0; + + s_led.gsm_led_is_on = false; + s_led.gsm_led_state_time = 0; + s_led.gsm_state = GM_LED_FLASH; + + s_led.gps_led_is_on = false; + s_led.gps_led_state_time = 0; + s_led.gps_state = GM_LED_FLASH; + + return GM_SUCCESS; +} + + +GM_ERRCODE led_destroy(void) +{ + return GM_SUCCESS; +} + +void led_timer_proc(void) +{ + s_led.start_time_ms += GM_LED_PROC_PERIOD_MS; + + gsm_led_proc(); + gps_led_proc(); +} + +static void gsm_led_proc(void) +{ + s_led.gsm_led_state_time += GM_LED_PROC_PERIOD_MS; + + //7秒以内快闪 + if (s_led.start_time_ms < GM_GSM_LED_QUICK_FLASH_SECONDS * TIM_GEN_1SECOND) + { + if (s_led.gsm_led_state_time >= GM_LED_QUICK_FLASH_PERIOD_MS) + { + s_led.gsm_led_is_on = !s_led.gsm_led_is_on; + hard_ware_set_gsm_led(s_led.gsm_led_is_on); + s_led.gsm_led_state_time = 0; + } + } + else + { + //常亮或者长灭 + if (s_led.gsm_state != GM_LED_FLASH) + { + s_led.gsm_led_is_on = (bool)s_led.gsm_state; + hard_ware_set_gsm_led(s_led.gsm_led_is_on); + s_led.gsm_led_state_time = 0; + } + //慢闪 + else + { + if (s_led.gsm_led_is_on && s_led.gsm_led_state_time >= GM_LED_SLOW_FLASH_ON_MS) + { + s_led.gsm_led_is_on = false; + hard_ware_set_gsm_led(s_led.gsm_led_is_on); + s_led.gsm_led_state_time = 0; + + } + else if(false == s_led.gsm_led_is_on && s_led.gsm_led_state_time >= GM_LED_SLOW_FLASH_OFF_MS) + { + s_led.gsm_led_is_on = true; + hard_ware_set_gsm_led(s_led.gsm_led_is_on); + s_led.gsm_led_state_time = 0; + } + else + { + } + } + } +} + +static void gps_led_proc(void) +{ + s_led.gps_led_state_time += GM_LED_PROC_PERIOD_MS; + + //常亮或者长灭 + if (s_led.gps_state != GM_LED_FLASH) + { + s_led.gps_led_is_on = (bool)s_led.gps_state; + hard_ware_set_gps_led(s_led.gps_led_is_on); + s_led.gps_led_state_time = 0; + } + //快闪 + else + { + if (s_led.gps_led_state_time >= GM_LED_QUICK_FLASH_PERIOD_MS) + { + s_led.gps_led_is_on = !s_led.gps_led_is_on; + hard_ware_set_gps_led(s_led.gps_led_is_on); + s_led.gps_led_state_time = 0; + } + } +} + + +void led_set_gps_state(LedState state) +{ + s_led.gps_state = state; +} + +void led_set_gsm_state(LedState state) +{ + s_led.gsm_state = state; +} + diff --git a/src/log_service.c b/src/log_service.c new file mode 100644 index 0000000..f4ee798 --- /dev/null +++ b/src/log_service.c @@ -0,0 +1,711 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: log_service.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-22 + * Description: + * Others: + * Function List: + 1. 创建log_service模块 + 2. 销毁log_service模块 + 3. log_service模块定时处理入口 + 4. 打印日志到串口 + 5. 上传日志到日志后台 + * History: + 1. Date: 2019-03-22 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include +#include +#include +#include "log_service.h" +#include "config_service.h" +#include "gm_stdlib.h" +#include "gm_gprs.h" +#include "utility.h" +#include "gm_memory.h" +#include "uart.h" +#include "gsm.h" +#include "gprs.h" +#include "system_state.h" + +#define LOG_PING_TIME 60 + +typedef struct +{ + U8* buf; + u16 len; +}LogSaveData; + + +/*它是个fifo*/ +typedef struct +{ + LogSaveData *his; + u16 size; /*总空间*/ + u16 read_idx; /*当前读到哪一条, read==write 表示队列空*/ + u16 write_idx; /*当前写到哪一条, 新消息往write处写*/ +}LogCurData; + +typedef struct +{ + u32 data_finish_time; +}LogServiceExtend; + + +static FifoType s_log_data_fifo = {0,0,0,0,0}; + +static LogServiceExtend s_log_socket_extend; + +#define GM_LOG_MAX_LEN 1536 + +static char s_log_level_str[5][6] = {"DEBUG","INFO","WARN","ERROR","FATAL"}; + +static SocketType s_log_socket = {-1,"",SOCKET_STATUS_ERROR,}; + +#if __GOOME_TRACE_DEBUG_ENABLE__ +static LogLevel s_log_level = DEBUG; +static LogLevel s_upload_level = FATAL; +#else +static LogLevel s_log_level = ERROR; +static LogLevel s_upload_level = FATAL; +#endif + +static bool s_log_enable = true; + +static GM_ERRCODE log_service_transfer_status(u8 new_status); +static void log_service_init_proc(void); +static void log_service_connecting_proc(void); +static void log_service_work_proc(void); +static void log_msg_receive(void); +static void log_service_close(void); +static void log_service_data_finish_proc(void); +static GM_ERRCODE log_data_insert_one(U8* data, u16 len); +static void log_data_release(LogSaveData *one); + +static GM_ERRCODE log_data_insert_one(U8* data, u16 len) +{ + GM_ERRCODE ret; + LogSaveData log_data = {0}; + //多申请一个字节,放字符串结束符 + log_data.buf = (U8* )GM_MemoryAlloc(len + 1); + if(NULL == log_data.buf) + { + //这里不适合再调用 log_service_print,出错会导致递归, 打印只求速死 + log_service_print(WARN,"clock(%d) log_data_insert_one assert(GM_MemoryAlloc(%d) failed", util_clock(), len); + return GM_SYSTEM_ERROR; + } + log_data.len = len; + GM_memcpy(log_data.buf, data, len); + log_data.buf[len] = '\0'; + + ret = fifo_insert(&s_log_data_fifo, (u8*)&log_data, sizeof(LogSaveData)); + if(ret != GM_SUCCESS) + { + //这里不适合再调用 log_service_print,出错会导致递归 + GM_MemoryFree(log_data.buf); + } + return ret; +} + +static void log_data_release(LogSaveData *one) +{ + if(one && one->buf) + { + GM_MemoryFree(one->buf); + one->buf = NULL; + one->len = 0; + } +} + +static GM_ERRCODE log_service_transfer_status(u8 new_status) +{ + u8 old_status = (u8)s_log_socket.status; + GM_ERRCODE ret = GM_PARAM_ERROR; + switch(s_log_socket.status) + { + case SOCKET_STATUS_INIT: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_GET_HOST: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + break; + case SOCKET_STATUS_CONNECTING: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_CONNECTING: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_WORK: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_DATA_FINISH: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_ERROR: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + default: + break; + } + + + if(GM_SUCCESS == ret) + { + s_log_socket.status = new_status; + s_log_socket.status_fail_count = 0; + log_service_print(INFO,"clock(%d) log_service_transfer_status from %s to %s success", util_clock(), + gm_socket_status_string((SocketStatus)old_status), gm_socket_status_string((SocketStatus)new_status)); + } + else + { + log_service_print(INFO,"clock(%d) log_service_transfer_status from %s to %s failed", util_clock(), + gm_socket_status_string((SocketStatus)old_status), gm_socket_status_string((SocketStatus)new_status)); + } + + return ret; + +} + + +GM_ERRCODE log_service_create(void) +{ + u8 addr[2*GOOME_DNS_MAX_LENTH+1]; + u8 IP[4]; + u32 port = 0; + u8 idx = 0; + + s_log_socket.access_id = SOCKET_INDEX_LOG; + gm_socket_init(&s_log_socket); + s_log_socket_extend.data_finish_time = 0; + + GM_memset(addr, 0x00, sizeof(addr)); + idx = GM_sscanf((const char *)config_service_get_pointer(CFG_LOGSERVERADDR), "%[^:]:%d", addr, &port); + if (idx != 2) + { + log_service_print(WARN,"clock(%d) log_service_create assert(idx ==2) failed.", util_clock()); + return GM_PARAM_ERROR; + } + + if(GM_SUCCESS != GM_ConvertIpAddr(addr, IP)) + { + if(util_is_valid_dns(addr, GM_strlen((const char *)addr))) + { + gm_socket_set_addr(&s_log_socket, addr, GM_strlen((const char *)addr), port, STREAM_TYPE_DGRAM); + } + else + { + log_service_print(WARN,"clock(%d) log_service_create assert(dns(%s)) failed.", util_clock(), addr); + return GM_PARAM_ERROR; + } + } + else + { + gm_socket_set_ip_port(&s_log_socket, IP, port, STREAM_TYPE_DGRAM); + } + + fifo_init(&s_log_data_fifo, LOG_BUFFER_NUM * sizeof(LogSaveData)); + log_service_print(WARN,"clock(%d) log_service_create access_id(%d) fifo(%p).", util_clock(), s_log_socket.access_id, &s_log_socket.fifo); + return GM_SUCCESS; +} + +GM_ERRCODE log_service_destroy(void) +{ + if(SOCKET_STATUS_ERROR == s_log_socket.status) + { + return GM_SUCCESS; + } + + log_service_close(); + + //log_service是在gprs_create中创建, 后面 重建连接, 所以保留fifo + log_service_transfer_status(SOCKET_STATUS_ERROR); + return GM_SUCCESS; +} + + +static void log_service_close(void) +{ + if(s_log_socket.id >=0) + { + GM_SocketClose(s_log_socket.id); + s_log_socket.id=-1; + } +} + + +static void log_service_data_finish_proc(void) +{ + u32 current_time = 0; + + if(!gprs_is_ok()) + { + return; + } + + current_time = util_clock(); + if((current_time - s_log_socket_extend.data_finish_time) > LOG_PING_TIME) + { + log_service_print(DEBUG,"clock(%d) log_service_data_finish_proc cur(%d) - fin(%d) > LOG_PING_TIME(%d).", + util_clock(), current_time, s_log_socket_extend.data_finish_time,LOG_PING_TIME); + // 可以重建连接 + log_service_transfer_status(SOCKET_STATUS_INIT); + } +} + + +GM_ERRCODE log_service_timer_proc(void) +{ + if(!s_log_socket.fifo.base_addr) + { + return GM_SUCCESS; + } + + switch(s_log_socket.status) + { + case SOCKET_STATUS_INIT: + log_service_init_proc(); + break; + case SOCKET_STATUS_CONNECTING: + log_service_connecting_proc(); + break; + case SOCKET_STATUS_WORK: + log_service_work_proc(); + break; + case SOCKET_STATUS_DATA_FINISH: + log_service_data_finish_proc(); + break; + case SOCKET_STATUS_ERROR: + log_service_data_finish_proc(); + break; + default: + log_service_print(WARN,"clock(%d) log_service_timer_proc assert(s_log_socket.status(%d)) unknown.", util_clock(),s_log_socket.status); + return GM_ERROR_STATUS; + } + + return GM_SUCCESS; +} + +void log_service_set_level(LogLevel log_level, LogLevel upload_level) +{ + s_log_level = log_level; + s_upload_level = upload_level; +} + +void log_service_get_level(LogLevel *log_level, LogLevel *upload_level) +{ + (*log_level) = s_log_level; + (*upload_level) = s_upload_level; +} + +void log_service_enable_print(bool enable) +{ + s_log_enable = enable; +} + +static void log_service_init_proc(void) +{ + u8 IP[4]; + gm_socket_get_host_by_name_trigger(&s_log_socket); + system_state_get_ip_cache(SOCKET_INDEX_LOG, IP); + if(GM_SUCCESS == gm_is_valid_ip(IP)) + { + GM_memcpy( s_log_socket.ip , IP, sizeof(IP)); + log_service_transfer_status(SOCKET_STATUS_CONNECTING); + if(GM_SUCCESS == gm_socket_connect(&s_log_socket)) + { + } + // else do nothing . connecting_proc will deal. + } + else if((!s_log_socket.excuted_get_host) && (GM_SUCCESS == gm_is_valid_ip(s_log_socket.ip))) + { + log_service_transfer_status(SOCKET_STATUS_CONNECTING); + if(GM_SUCCESS == gm_socket_connect(&s_log_socket)) + { + } + // else do nothing . connecting_proc will deal. + } +} + +void log_service_connection_failed(void) +{ + log_service_close(); + + if(s_log_socket.status_fail_count >= MAX_CONNECT_REPEAT) + { + // if excuted get_host transfer to error statu, else get_host. + if(s_log_socket.excuted_get_host || (s_log_socket.addr[0] == 0)) + { + s_log_socket_extend.data_finish_time = util_clock(); + log_service_transfer_status(SOCKET_STATUS_DATA_FINISH); + } + else + { + log_service_transfer_status(SOCKET_STATUS_INIT); + } + } + // else do nothing . wait connecting proc to deal. +} + + +void log_service_connection_ok(void) +{ + log_service_transfer_status(SOCKET_STATUS_WORK); +} + +void log_service_close_for_reconnect(void) +{ + log_service_close(); + s_log_socket_extend.data_finish_time = util_clock(); + log_service_transfer_status(SOCKET_STATUS_DATA_FINISH); +} + + +static void log_service_connecting_proc(void) +{ + u32 current_time = util_clock(); + + if((current_time - s_log_socket.send_time) > CONNECT_TIME_OUT) + { + s_log_socket.status_fail_count ++; + log_service_connection_failed(); + + if(s_log_socket.status == SOCKET_STATUS_CONNECTING && + s_log_socket.status_fail_count < MAX_CONNECT_REPEAT) + { + if(GM_SUCCESS == gm_socket_connect(&s_log_socket)) + { + //do nothing. wait callback + } + } + + } +} + + +#define LOG_PKT_HEAD "' + +void log_service_send_msg(SocketType *socket) +{ + LogSaveData log_data; + + U8 imei[GM_IMEI_LEN + 1] = {0}; + if(GM_SUCCESS != gsm_get_imei(imei)) + { + LOG(WARN,"Failed to get IMEI"); + return; + } + + if(GM_SUCCESS == fifo_peek(&s_log_data_fifo, (U8*)&log_data, sizeof(LogSaveData))) + { + char* p_send_buf = NULL; + U16 send_buf_len = 0; + + if (log_data.len > GM_LOG_MAX_LEN) + { + fifo_pop_len(&s_log_data_fifo, sizeof(LogSaveData)); + LOG(ERROR,"clock(%d) log_service_send_msg data is too long(%d)", util_clock(), log_data.len); + log_data_release(&log_data); + return; + } + + //一条日志,6个字节:LOG_PKT_HEAD——3个字节,2个分隔符,1和结束符 + //日志回复 + send_buf_len = 6 + GM_strlen((const char*)imei) + log_data.len; + p_send_buf = GM_MemoryAlloc(send_buf_len + 1); + p_send_buf[send_buf_len] = 0; + + //最多从源字符串format中拷贝size字节的内容(含字符串结尾标志'\0')到目标字符串 + GM_snprintf(p_send_buf, send_buf_len + 1, "%s%c%s%c%s%c", LOG_PKT_HEAD,LOG_PKT_SPLIT,(const char*)imei,LOG_PKT_SPLIT,(const char*)log_data.buf,LOG_PKT_TAIL); + + if(GM_SUCCESS == gm_socket_send(socket, (U8*)p_send_buf, send_buf_len)) + { + fifo_pop_len(&s_log_data_fifo, sizeof(LogSaveData)); + //LOG(DEBUG,"clock(%d) log_service_send_msg msglen(%d):%s", util_clock(), send_buf_len,p_send_buf); + log_data_release(&log_data); + } + else + { + LOG(ERROR,"Failed to send log data!"); + log_service_close(); + s_log_socket_extend.data_finish_time = util_clock(); + log_service_transfer_status(SOCKET_STATUS_DATA_FINISH); + } + GM_MemoryFree(p_send_buf); + } + + return; +} + +static void log_service_work_proc(void) +{ + u32 current_time = util_clock(); + + //每秒钟最多一条日志,防止发送过快 + if((current_time - s_log_socket.send_time) >= 1) + { + log_service_send_msg(&s_log_socket); + s_log_socket.send_time = current_time; + } + log_msg_receive(); +} + +void log_service_print_test(const char *format, ...) +{ + va_list p_va_list; + char buf[GM_LOG_MAX_LEN] = { 0 }; + char log_format[GM_LOG_MAX_LEN] = {0}; + + U16 log_data_len = 0; + + va_start(p_va_list, format); + GM_snprintf(log_format, GM_LOG_MAX_LEN, "%s\r\n",format); + GM_vsprintf(buf, log_format, p_va_list); + va_end(p_va_list); + log_data_len = GM_strlen(buf); + if (log_data_len >= GM_LOG_MAX_LEN - 1) + { + uart_write(GM_UART_DEBUG, "len is wrong\n", 13); + return; + } + uart_write(GM_UART_DEBUG, (U8*)buf, log_data_len); +} + + +void log_service_print(LogLevel level,const char *format, ...) +{ + va_list p_va_list; + char buf[GM_LOG_MAX_LEN] = { 0 }; + char log_format[GM_LOG_MAX_LEN] = {0}; + + U16 log_data_len = 0; + + if (level < s_log_level || false == s_log_enable) + { + return; + } + + va_start(p_va_list, format); + GM_snprintf(log_format, GM_LOG_MAX_LEN, "[%s]:%s\r\n", s_log_level_str[level], format); + GM_vsprintf(buf, log_format, p_va_list); + va_end(p_va_list); + log_data_len = GM_strlen(buf); + if (log_data_len >= GM_LOG_MAX_LEN - 1) + { + uart_write(GM_UART_DEBUG, "len is wrong\n", 13); + return; + } + uart_write(GM_UART_DEBUG, (U8*)buf, log_data_len); + + // DEBUG 编译默认不upload, 改loglevel后,只报info以上级别的 + if (level > DEBUG && s_log_level > DEBUG && s_upload_level <= level + && s_log_data_fifo.base_addr) + { + JsonObject* p_log_root = json_create(); + json_add_string(p_log_root, "log", buf); + log_service_upload(level, p_log_root); + } +} + + +void log_service_print_hex(const char* p_data, const U16 len) +{ + char buf[GM_LOG_MAX_LEN] = { 0 }; + U16 index = 0; + + if (false == s_log_enable || s_log_level > INFO) + { + return; + } + + if ((2*len + 1) >= GM_LOG_MAX_LEN) + { + return; + } + + for (index = 0; index < len; ++index) + { + GM_snprintf(buf + 2*index, GM_LOG_MAX_LEN - 2*index, "%02X", p_data[index]); + } + + + uart_write(GM_UART_DEBUG, (U8*)buf, GM_strlen(buf)); + uart_write(GM_UART_DEBUG, "\n", 1); +} + + +void log_service_upload(LogLevel level,JsonObject* p_root) +{ + s8 zone = 0; + ST_Time t = {0}; + char date[50] = {0}; + char log_str[GM_LOG_MAX_LEN] = {0}; + + zone = config_service_get_zone(); + util_get_current_local_time(NULL, &t, zone); + + GM_snprintf(date,50, "%d-%d-%d %d:%d:%d",t.year,t.month,t.day,t.hour,t.minute,t.second); + json_add_string(p_root, "date", date); + json_add_int(p_root,"clock", util_clock()); + + if(json_print_to_buffer(p_root, log_str, GM_LOG_MAX_LEN - 1)) + { + log_data_insert_one((U8*)log_str, GM_strlen(log_str)); + } + + //debug级肯定不再回调log_service_upload + log_service_print(DEBUG, log_str); + json_destroy(p_root); + p_root = NULL; +} + +/*当前服务器是只收不发响应的. 下面这个函数正常来説不会工作 */ +static void log_msg_receive(void) +{ + // parse buf msg + // if OK, after creating other socket, transfer to finish + // not ok, ignore msg. + u8 head[100]; + u32 len = sizeof(head); + + if(SOCKET_STATUS_WORK != s_log_socket.status) + { + return; + } + + //get head then delete + if(GM_SUCCESS != fifo_peek(&s_log_socket.fifo, head, len)) + { + // no msg + return; + } + + fifo_pop_len(&s_log_socket.fifo, len); + + log_service_print(DEBUG,"clock(%d) log_msg_receive msg len(%d)", util_clock(), len); + + //do nothing. just read and clear msgs + +} + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..4cf5df6 --- /dev/null +++ b/src/main.c @@ -0,0 +1,222 @@ +/** + * Copyright ? Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: main.c + * Author: 王志华 + * Version: 1.0 + * Date: 2019-02-28 + * Description: APP主函数头 + * Others: + * Function List: + 1. APP主入口 + * History: + 1. Date: 2019-02-28 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + + +#include +#include +#include +#include +#include +#include "main.h" +#include "error_code.h" +#include "utility.h" +#include "hard_ware.h" +#include "led.h" +#include "system_state.h" +#include "config_service.h" +#include "g_sensor.h" +#include "uart.h" +#include "watch_dog.h" +#include "log_service.h" +#include "relay.h" +#include "gsm.h" +#include "sms.h" +#include "gps.h" +#include "gprs.h" +#include "auto_test.h" +#include "update_file.h" +#include "bms.h" + + +static void timer_self_test_start(void); +static void upload_boot_log(void); + + +//注意主函数里面调用其他函数的顺序有严格要求 +void app_main_entry(void) +{ + //基础部分 + util_create(); + uart_create(); + system_state_create(); + config_service_read_from_local(); + config_service_save_to_local(); + + gsm_create(); + //其中创建网络服务 + gprs_create(); + sms_create(); + hard_ware_create(); + led_create(); + relay_create(); + watch_dog_create(); + gps_create(); + bms_create(); + + GM_StartTimer(GM_TIMER_MAIN_UPLOAD_LOG, 2*TIM_GEN_1SECOND, upload_boot_log); + + g_sensor_create(); + system_state_set_work_state(GM_SYSTEM_STATE_WORK); + gps_power_on(true); + + + //延迟10秒再开始自检,否则还没有获取到IMEI会误入自检 + if(GM_REBOOT_POWER_ON == system_state_get_boot_reason(false)) + { + GM_StartTimer(GM_TIMER_SELF_CHECK_START, 30*TIM_GEN_1SECOND, timer_self_test_start); + LOG(INFO,"It may enter self check 30 seconds later."); + } + + + //更精准的定时器 + GM_CreateKalTimer(0); + GM_StartKalTimer(0, kal_timer_1s_proc, GM_TICKS_1_SEC); + + GM_StartTimer(GM_TIMER_10MS_MAIN, TIM_GEN_10MS, timer_10ms_proc); + GM_StartTimer(GM_TIMER_1S_MAIN, TIM_GEN_1SECOND, timer_1s_proc); +} + + +//唤醒时用这个定时器处理 +void timer_10ms_proc(void) +{ + if (GM_SYSTEM_STATE_WORK == system_state_get_work_state()) + { + GM_StartTimer(GM_TIMER_10MS_MAIN, TIM_GEN_10MS, timer_10ms_proc); + led_timer_proc(); + g_sensor_timer_proc(); + gprs_timer_proc(); + hard_ware_timer_proc(); + } +} + +void timer_1s_proc(void) +{ + if (GM_SYSTEM_STATE_WORK == system_state_get_work_state()) + { + GM_StartTimer(GM_TIMER_1S_MAIN, TIM_GEN_1SECOND, timer_1s_proc); + util_timer_proc(); + watch_dog_timer_proc(); + uart_timer_proc(); + system_state_timer_proc(); + relay_timer_proc(); + auto_test_timer_proc(); + } +} + +//休眠时用这个定时器处理 +void kal_timer_1s_proc(void* p_arg) +{ + if (GM_SYSTEM_STATE_SLEEP == system_state_get_work_state()) + { + //降频处理 + led_timer_proc(); + g_sensor_timer_proc(); + gprs_timer_proc(); + hard_ware_timer_proc(); + + //正常处理 + util_timer_proc(); + watch_dog_timer_proc(); + uart_timer_proc(); + system_state_timer_proc(); + relay_timer_proc(); + auto_test_timer_proc(); + } +} + +static void timer_self_test_start(void) +{ + auto_test_create(true); +} + +static void upload_boot_log(void) +{ + JsonObject* p_log_root = NULL; + char kernel_version[50] = {0}; + GPSChipType gps_chip_type = GM_GPS_TYPE_UNKNOWN; + char gsensor_type_str[20] = {0}; + ConfigDeviceTypeEnum dev_type_id = DEVICE_MAX; + char check_sum_str[9] = {0}; + U8 protocol_type = 0; + U8 protocol_ver = 0; + U32 app_check_sum = 0; + float voltage = 0; + + p_log_root = json_create(); + json_add_string(p_log_root, "event", "boot"); + + json_add_string(p_log_root, "reason", system_state_get_boot_reason_str(system_state_get_boot_reason(true))); + + system_state_set_boot_reason(GM_RREBOOT_UNKNOWN); + + + json_add_string(p_log_root, "app version", VERSION_NUMBER); + + json_add_string(p_log_root, "app build time", SW_APP_BUILD_DATE_TIME); + + app_check_sum = update_filemod_get_checksum(UPDATE_TARGET_IMAGE); + GM_snprintf(check_sum_str, 8, "%4X", app_check_sum); + system_state_set_bin_checksum(app_check_sum); + + json_add_string(p_log_root, "app check sum",check_sum_str); + + GM_ReleaseVerno((U8*)kernel_version); + GM_sprintf(kernel_version + GM_strlen(kernel_version), "(%s)",GM_BuildDateTime()); + json_add_string(p_log_root, "kernel version", kernel_version); + + config_service_get(CFG_DEVICETYPE, TYPE_SHORT, &dev_type_id, sizeof(U16)); + json_add_string(p_log_root, "device type", (char*)config_service_get_device_type(dev_type_id)); + + hard_ware_get_power_voltage(&voltage); + json_add_double(p_log_root, "power voltage", voltage); + + config_service_get(CFG_GPS_TYPE, TYPE_BYTE, &gps_chip_type, sizeof(gps_chip_type)); + json_add_int(p_log_root, "gps chip", gps_chip_type); + + g_sensor_get_typestr(system_state_get_gsensor_type(),gsensor_type_str,sizeof(gsensor_type_str)); + json_add_string(p_log_root, "g_sensor type", gsensor_type_str); + + json_add_string(p_log_root, "server", (char*)config_service_get_pointer(CFG_SERVERADDR)); + + config_service_get(CFG_PROTOCOL, TYPE_BYTE, &protocol_type, sizeof(protocol_type)); + json_add_int(p_log_root, "protocol", protocol_type); + config_service_get(CFG_PROTOCOL_VER, TYPE_BYTE, &protocol_ver, sizeof(protocol_ver)); + json_add_int(p_log_root, "protocol_ver", protocol_ver); + + json_add_int(p_log_root, "system state bits", system_state_get_status_bits()); + + json_add_int(p_log_root, "power on", system_state_get_reboot_counts(GM_REBOOT_POWER_ON)); + json_add_int(p_log_root, "exceptions reboots", system_state_get_reboot_counts(GM_RREBOOT_UNKNOWN)); + json_add_int(p_log_root, "GPRS reboots", system_state_get_reboot_counts(GM_REBOOT_GPRS)); + json_add_int(p_log_root, "GPS reboots", system_state_get_reboot_counts(GM_REBOOT_GPS)); + json_add_int(p_log_root, "command reboots", system_state_get_reboot_counts(GM_REBOOT_CMD)); + json_add_int(p_log_root, "upgrade reboots", system_state_get_reboot_counts(GM_REBOOT_UPDATE)); + json_add_int(p_log_root, "check params reboots", system_state_get_reboot_counts(GM_REBOOT_CHECKPARA)); + + json_add_int(p_log_root, "gprs_last_good", system_state_get_last_good_time()); + json_add_int(p_log_root, "gprs_ok_count", system_state_get_call_ok_count()); + json_add_string(p_log_root, "gpss_reboot_reason", system_state_get_gpss_reboot_reason()); + + log_service_upload(INFO,p_log_root); +} + + + diff --git a/src/nmea_protocol.c b/src/nmea_protocol.c new file mode 100644 index 0000000..6ee253f --- /dev/null +++ b/src/nmea_protocol.c @@ -0,0 +1,1705 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: nmea.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-19 + * Description: GPS标准协议NMEA-0183实现 + * Others: + * Function List: + 1. + + * History: + 1. Date: 2019-03-19 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "utility.h" +#include "nmea_protocol.h" +#include "log_service.h" + +#define MAX_TYPE_LEN 12 + +// AGPS信息(位置,时间,频率) +typedef struct +{ + double lat; + double lng; + double alt; + double tow; + float df; + float pos_acc; + float t_acc; + float f_acc; + U32 res; + U16 wn; + U8 time_source; + U8 flags;// BIT0:位置有效标志 BIT1:时间有效标志 +} ATAidInfo; + + +static S32 hex2int(char c); + +static U8 nmea_checksum(const char* p_sentence); + +static bool nmea_check(const char* p_sentence, bool strict); + +static bool nmea_isfield(char c); + +static bool nmea_scan(const char* p_sentence, const char *format, ...); + +static bool nmea_create_td_sentence(const U16 cmd,const U8* p_data,const U16 data_len, U8* p_sentence, U8* p_len); + + +static S32 hex2int(char c) +{ + if (c >= '0' && c <= '9') + { + return c - '0'; + } + if (c >= 'A' && c <= 'F') + { + return c - 'A' + 10; + } + if (c >= 'a' && c <= 'f') + { + return c - 'a' + 10; + } + return -1; +} + + + +/** + * Function: 检查语句有效性和校验和 + * Description:不检查语句完整性 + * Input: 无 + * Output: 无 + * Return: true——有效;false——无效 + * Others: + */ +static bool nmea_check(const char* p_sentence, bool strict) +{ + U8 checksum = 0; + S32 upper = 0; + S32 lower = 0; + S32 expected = 0; + const char* org_sentence = p_sentence; + + // 语句长度限制 + if (strlen(p_sentence) > SENTENCE_MAX_LENGTH + 3) + { + + return false; + } + + // 有效的语句应该以'$'开头 + if (*p_sentence++ != '$') + { + LOG(WARN,"It is not begin with $!"); + return false; + } + + while (*p_sentence && *p_sentence != '*' && util_isprint((U8)*p_sentence)) + { + checksum ^= *p_sentence++; + } + + // 有校验和 + if (*p_sentence == '*') + { + p_sentence++; + + upper = hex2int(*p_sentence++); + if (upper == -1) + { + LOG(WARN,"upper is -1"); + return false; + } + + lower = hex2int(*p_sentence++); + if (lower == -1) + { + LOG(WARN,"lower is -1"); + return false; + } + + expected = upper << 4 | lower; + if (checksum != expected) + { + LOG(WARN, "checksum=%d,expected=%d", checksum,expected); + return false; + } + } + else if (strict) + { + // 严格模式下没有校验和的数据是无效的 + LOG(WARN,"It has not checksum:%s",org_sentence); + return false; + } + + // 最后一定要是换行 + if (strict && *p_sentence && GM_strcmp(p_sentence, "\n") && GM_strcmp(p_sentence, "\r\n")) + { + LOG(WARN," It has not end flag:%s",org_sentence); + return false; + } + + return true; +} + +static bool nmea_isfield(char c) +{ + return util_isprint((U8)c) && c != ',' && c != '*'; +} + +/** + * Function: 从语句中提取变量 + * Description: + * Input: p_sentence:语句;format——格式; + * Output: ...——变量 + * Return: true——成功;false——失败 + * Others: 类似于scanf的处理方式,支持下面几种格式: + c - single character (char*) + d - direction, returned as 1/-1, default 0 (S32*) + f - fractional, returned as value + scale (S32*, S32*) + i - decimal, default zero (S32*) + s - string (char*) + t - talker identifier and type (char*) + T - date/time stamp (S32*, S32*, S32*) + */ +static bool nmea_scan(const char* p_sentence, const char* p_format, ...) + +{ + bool result = false; + bool optional = false; + const char* p_field = p_sentence; + char type = 0; + char value_8 = 0; + S32 value_32 = 0; + S32 sign_32 = 0; + S32 scale_32 = 0; + S32 digit_32 = 0; + char* p_buf = NULL; + U8 index = 0; + S32 d = 0; + S32 m = 0; + S32 y = 0; + char dArr[3] = {0}; + char mArr[3] = {0}; + char yArr[3] = {0}; + char hArr[3] = {0}; + char iArr[3] = {0}; + char sArr[3] = {0}; + NMEAFloat fraction = {0}; + NMEATime* p_time = NULL; + S32 h = -1; + S32 i = -1; + S32 s = -1; + S32 u = -1; + + + va_list ap; + va_start(ap, p_format); + + while (*p_format) + { + type = *p_format++; + + if (type == ';') + { + // 后面所有的域都是可选的 + optional = true; + continue; + } + + if (!p_field && !optional) + { + goto parse_error; + } + + switch (type) + { + // Single character field(char) + case 'c': + { + value_8 = '\0'; + if (p_field && nmea_isfield(*p_field)) + { + value_8 = *p_field; + } + + *va_arg(ap, char*) = value_8; + } + break; + // Single character direction field(S32) + case 'd': + { + value_32 = 0; + + if (p_field && nmea_isfield(*p_field)) + { + switch (*p_field) + { + case 'N': + case 'E': + value_32 = 1; + break; + case 'S': + case 'W': + value_32 = -1; + break; + default: + goto parse_error; + } + } + + *va_arg(ap, S32*) = value_32; + } + break; + + // Fractional value with scale (NMEAFloat). + case 'f': + { + sign_32 = 0; + value_32 = -1; + scale_32 = 0; + + if (p_field) + { + while (nmea_isfield(*p_field)) + { + if (*p_field == '+' && !sign_32 && value_32 == -1) + { + sign_32 = 1; + } + else if (*p_field == '-' && !sign_32 && value_32 == -1) + { + sign_32 = -1; + } + else if (util_isdigit((U8) *p_field)) + { + digit_32 = *p_field - '0'; + if (value_32 == -1) + { + value_32 = 0; + } + if (value_32 > (INT_LEAST32_MAX - digit_32) / 10) + { + /* we ran out of bits, what do we do? */ + if (scale_32) + { + /* truncate extra precision */ + break; + } + else + { + /* integer overflow. bail out. */ + goto parse_error; + } + } + value_32 = (10 * value_32) + digit_32; + scale_32 *= 10; + + } + else if (*p_field == '.' && scale_32 == 0) + { + scale_32 = 1; + } + else if (*p_field == ' ') + { + /* Allow spaces at the start of the p_field. Not NMEA + * conformant, but some modules do this. */ + if (sign_32 != 0 || value_32 != -1 || scale_32 != 0) + { + goto parse_error; + } + } + else + { + goto parse_error; + } + p_field++; + } + } + + if ((sign_32 || scale_32) && value_32 == -1) + { + goto parse_error; + } + + if (value_32 == -1) + { + /* No digits were scanned. */ + value_32 = 0; + scale_32 = 0; + } + else if (scale_32 == 0) + { + /* No decimal point. */ + scale_32 = 1; + } + if (sign_32) + { + value_32 *= sign_32; + } + fraction.value = value_32; + fraction.scale = scale_32; + *va_arg(ap, NMEAFloat*) = fraction; + } + break; + + // Integer value, default 0 (S32). + case 'i': + { + value_32 = 0; + + if (p_field) + { + char *endptr = NULL; + value_32 = util_strtol(p_field, &endptr); + if (nmea_isfield(*endptr)) + { + goto parse_error; + } + } + *va_arg(ap, S32*) = value_32; + } + break; + + // String value (char *). + case 's': + { + p_buf = va_arg(ap, char *); + + if (p_field) + { + while (nmea_isfield(*p_field)) + { + *p_buf++ = *p_field++; + } + } + + *p_buf = '\0'; + } + break; + + // NMEA talker+sentence identifier (char*). + case 't': + { + // This p_field is always mandatory. + if (!p_field) + { + goto parse_error; + } + + if (p_field[0] != '$') + { + goto parse_error; + } + + while(nmea_isfield(p_field[index]) && index < MAX_TYPE_LEN) + { + index++; + } + index--; + + p_buf = va_arg(ap, char*); + memcpy(p_buf, p_field+1, index); + p_buf[index] = '\0'; + } + break; + + // Date (S32, S32, S32), -1 if empty. + case 'D': + { + NMEADate *date = va_arg(ap, NMEADate *); + + d = -1; + m = -1; + y = -1; + + if (p_field && nmea_isfield(*p_field)) + { + // Always six digits. + for (index = 0; index < 6; index++) + { + if (!util_isdigit((U8) p_field[index])) + { + goto parse_error; + } + } + + dArr[0] = p_field[0]; + dArr[1] = p_field[1]; + dArr[2] = '\0'; + mArr[0] = p_field[2]; + mArr[1] = p_field[3]; + mArr[2] = '\0'; + yArr[0] = p_field[4]; + yArr[1] = p_field[5]; + yArr[2] = '\0'; + d = util_strtol(dArr, NULL); + m = util_strtol(mArr, NULL); + y = util_strtol(yArr, NULL); + } + + date->day = d; + date->month = m; + date->year = y; + } + break; + + // Time (S32, S32, S32, S32), -1 if empty. + case 'T': + { + p_time = va_arg(ap, NMEATime *); + + h = -1; + i = -1; + s = -1; + u = -1; + + if (p_field && nmea_isfield(*p_field)) + { + // Minimum required: integer time. + for (index = 0; index < 6; index++) + { + if (!util_isdigit((U8) p_field[index])) + { + goto parse_error; + } + } + + hArr[0] = p_field[0]; + hArr[1] = p_field[1]; + hArr[2] = '\0'; + iArr[0] = p_field[2]; + iArr[1] = p_field[3]; + iArr[2] = '\0'; + sArr[0] = p_field[4]; + sArr[1] = p_field[5]; + sArr[2] = '\0'; + + h = util_strtol(hArr, NULL); + i = util_strtol(iArr, NULL); + s = util_strtol(sArr, NULL); + p_field += 6; + + // Extra: fractional time. Saved as microseconds. + if (*p_field++ == '.') + { + value_32 = 0; + scale_32 = 1000000LU; + while (util_isdigit((U8) *p_field) && scale_32 > 1) + { + value_32 = (value_32 * 10) + (*p_field++ - '0'); + scale_32 /= 10; + } + u = value_32 * scale_32; + } + else + { + u = 0; + } + } + + p_time->hours = h; + p_time->minutes = i; + p_time->seconds = s; + p_time->microseconds = u; + } break; + + // Ignore the p_field. + case '_': + { + } + break; + + default: + { + goto parse_error; + } + } + + /* Progress to the next p_field. */ + while (nmea_isfield(*p_sentence)) + { + p_sentence++; + } + /* Make sure there is a p_field there. */ + if (*p_sentence == ',') + { + p_sentence++; + p_field = p_sentence; + } + else + { + p_field = NULL; + } + } + + result = true; + +parse_error: + va_end(ap); + return result; +} + +NMEASentenceID nmea_sentence_id(const char* p_sentence, const U16 len, bool strict) +{ + char type[MAX_TYPE_LEN] = {0}; + U16 head_buff[3] = {0}; + U16 head = 0; + U16 cmd = 0; + + GM_memcpy(head_buff,p_sentence,6); + head = head_buff[0]; + + if (TD_SENTENCE_HEAD == head) + { + if (len < 8) + { + return NMEA_INVALID; + } + cmd = head_buff[1]; + if (TD_AID_ACK_CMD == cmd) + { + return NMEA_SENTENCE_TD_ACK; + } + else if(TD_AID_VER_CMD == cmd) + { + return NMEA_SENTENCE_TD_VER; + } + else + { + return NMEA_INVALID; + } + } + if (AT_SENTENCE_HEAD == head) + { + if (len < 8) + { + return NMEA_INVALID; + } + cmd = head_buff[2];; + if (AT_AID_ACK_CMD == cmd) + { + return NMEA_SENTENCE_AT_ACK; + } + else if(AT_AID_NACK_CMD == cmd) + { + return NMEA_SENTENCE_AT_NACK; + } + else if(AT_AID_VER_CMD == cmd) + { + return NMEA_SENTENCE_AT_VER; + } + else + { + return NMEA_INVALID; + } + } + + if (!nmea_check(p_sentence, strict)) + { + return NMEA_INVALID; + } + + if (!nmea_scan(p_sentence, "t", type)) + { + return NMEA_INVALID; + } + + if (!GM_strcmp(type+2, "TXT")) + { + return NMEA_SENTENCE_TXT; + } + + if (!GM_strcmp(type+2, "INF")) + { + return NMEA_SENTENCE_INF; + } + + if (!GM_strcmp(type, "PMTK011") || !GM_strcmp(type,"PMTK010")) + { + return NMEA_SENTENCE_MTK_START; + } + + if (!GM_strcmp(type, "PMTK001")) + { + return NMEA_SENTENCE_MTK_ACK; + } + + if (!GM_strcmp(type, "PMTK705")) + { + return NMEA_SENTENCE_MTK_VER; + } + + if (!GM_strcmp(type+2, "RMC")) + { + return NMEA_SENTENCE_RMC; + } + if (!GM_strcmp(type+2, "GGA")) + { + return NMEA_SENTENCE_GGA; + } + if (!GM_strcmp(type+2, "GSA")) + { + return NMEA_SENTENCE_GSA; + } + if (!GM_strcmp(type+2, "GLL")) + { + return NMEA_SENTENCE_GLL; + } + if (!GM_strcmp(type+2, "GST")) + { + return NMEA_SENTENCE_GST; + } + if (!GM_strcmp(type, "GPGSV")) + { + return NMEA_SENTENCE_GSV; + } + if (!GM_strcmp(type+2, "VTG")) + { + return NMEA_SENTENCE_VTG; + } + if (!GM_strcmp(type+2, "ZDA")) + { + return NMEA_SENTENCE_ZDA; + } + if (!GM_strcmp(type+2, "ACCURACY")) + { + return NMEA_SENTENCE_ACCURACY; + } + //LOG(DEBUG,"Unknown type:%s",type); + return NMEA_UNKNOWN; +} + +static U8 nmea_checksum(const char* p_sentence) +{ + U8 checksum = 0; + //跳过'$' + if (*p_sentence == '$') + { + p_sentence++; + } + + // 校验和算法是计算'$'和'*'之间的所有字节的异或 + while (*p_sentence && *p_sentence != '*') + { + checksum ^= *p_sentence++; + } + return checksum; +} + + +//$GPTXT,01,01,02,MA=CASIC*27 +//$GPTXT,01,01,02,IC=AT6558-5N-32-1C510800*48 +//$$GPTXT,01,01,02,SW=URANUS5,V5.1.0.0*1F +//$$GPTXT,01,01,02,TB=2018-04-18,10:28:16*40 +//$GPTXT,01,01,02,MO=GB*77 +bool nmea_parse_txt(NMEASentenceVER* p_frame, const char* p_sentence) +{ + char type[MAX_TYPE_LEN] = {0}; + //不知道前面这三个数字是什么意思 + U8 a = 0; + U8 b = 0; + U8 c = 0; + char str1[64] = {0}; + char str2[64] = {0}; + if (!nmea_scan(p_sentence, "tiiis;s", + type, + &a, + &b, + &c, + str1, + str2)) + { + LOG(DEBUG,"Failed to parse TXT:%s",p_sentence); + return false; + } + + if (GM_strcmp(type+2, "TXT")) + { + LOG(DEBUG,"Failed to parse type:%s",type+2); + return false; + } + + if (GM_strstr(str1, "IC=")) + { + GM_memset(p_frame->ver, 0, sizeof(p_frame->ver)); + GM_memcpy(p_frame->ver, str1, GM_strlen(str1)); + + return false; + } + + if (GM_strstr(str1, "SW=")) + { + //加个逗号分隔符 + GM_memcpy(p_frame->ver + GM_strlen(p_frame->ver), ",", 1); + GM_memcpy(p_frame->ver + GM_strlen(p_frame->ver), str1, GM_strlen(str1)); + if (GM_strlen(str2) != 0) + { + GM_memcpy(p_frame->ver + GM_strlen(p_frame->ver), ",", 1); + GM_memcpy(p_frame->ver + GM_strlen(p_frame->ver), str2, GM_strlen(str2)); + } + return true; + } + return false; +} + +//$TDINF,Techtotop Multi-GNSS Receiver*63 +//$TDINF,T3,RomFw,1.1(48),Aug 12 2016 16:57:35*02 +//$TDINF,GNSS=BDS+GPS,ANT=Disable*6D +//ic:T3;sw:RomFw;version:1.1(48) +bool nmea_parse_inf(NMEASentenceVER* p_frame, const char* p_sentence) +{ + char type[MAX_TYPE_LEN] = {0}; + char str1[32] = {0}; + char str2[32] = {0}; + char str3[32] = {0}; + char str4[32] = {0}; + if (!nmea_scan(p_sentence, "ts;sss", + type, + str1, + str2, + str3, + str4)) + { + return false; + } + if (GM_strcmp(type, "TDINF")) + { + LOG(WARN, "type(%s) is not TDINF", type); + return false; + } + + if (!GM_strcmp(str1, "T3")) + { + GM_memcpy(p_frame->ver, str1, GM_strlen(str1)); + if (GM_strlen(str2) != 0) + { + GM_memcpy(p_frame->ver + GM_strlen(p_frame->ver), ",", 1); + GM_memcpy(p_frame->ver + GM_strlen(p_frame->ver), str2, GM_strlen(str2)); + } + if (GM_strlen(str3) != 0) + { + GM_memcpy(p_frame->ver + GM_strlen(p_frame->ver), ",", 1); + GM_memcpy(p_frame->ver + GM_strlen(p_frame->ver), str3, GM_strlen(str3)); + } + if (GM_strlen(str4) != 0) + { + GM_memcpy(p_frame->ver + GM_strlen(p_frame->ver), ",", 1); + GM_memcpy(p_frame->ver + GM_strlen(p_frame->ver), str4, GM_strlen(str4)); + } + } + else + { + return false; + } + return true; +} + +//泰斗: $GNRMC,032713.00,A,2232.53348,N,11357.15840,E,0.624,,250619,,,A,V*18 +//中科微:$GNRMC,080452.042,V,,,,,,,190319,,,M,V*24 +bool nmea_parse_rmc(NMEASentenceRMC* p_frame, const char* p_sentence) +{ + char type[MAX_TYPE_LEN] = {0}; + char validity = 0; + S32 latitude_direction = 0; + S32 longitude_direction = 0; + S32 variation_direction = 0; + if (!nmea_scan(p_sentence, "t;TcfdfdffDfd", + type, + &p_frame->time, + &validity, + &p_frame->latitude, + &latitude_direction, + &p_frame->longitude, + &longitude_direction, + &p_frame->speed, + &p_frame->course, + &p_frame->date, + &p_frame->variation, + &variation_direction)) + { + return false; + } + if (GM_strcmp(type+2, "RMC")) + { + return false; + } + + p_frame->valid = (validity == 'A'); + p_frame->latitude.value *= latitude_direction; + p_frame->longitude.value *= longitude_direction; + p_frame->variation.value *= variation_direction; + + return true; +} + + +//泰斗: $GNGGA,081243.00,,,,,0,00,99.9,,,,,,*4D +//中科微:$GNGGA,080458.042,,,,,0,00,25.5,,,,,,*7D +bool nmea_parse_gga(NMEASentenceGGA* p_frame, const char* p_sentence) +{ + char type[MAX_TYPE_LEN] = {0}; + S32 latitude_direction = 0; + S32 longitude_direction = 0; + + if (!nmea_scan(p_sentence, "tTfdfdiiffcfcf_", + type, + &p_frame->time, + &p_frame->latitude, &latitude_direction, + &p_frame->longitude, &longitude_direction, + &p_frame->fix_quality, + &p_frame->satellites_tracked, + &p_frame->hdop, + &p_frame->altitude, &p_frame->altitude_units, + &p_frame->height, &p_frame->height_units, + &p_frame->dgps_age)) + { + return false; + } + if (GM_strcmp(type+2, "GGA")) + { + return false; + } + + p_frame->latitude.value *= latitude_direction; + p_frame->longitude.value *= longitude_direction; + + return true; +} + +//泰斗: $GNGSA,A,1,,,,,,,,,,,,,99.9,99.9,99.9,1*0A +//中科微: $GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 +//MTK: $GPGSA,A,3,30,28,19,,,,,,,,,,2.28,1.39,1.81*08 + +bool nmea_parse_gsa(NMEASentenceGSA* p_frame, const char* p_sentence) +{ + char type[MAX_TYPE_LEN] = {0}; + + p_frame->fix_type = NMEA_GPGSA_FIX_3D; + + if (!nmea_scan(p_sentence, "tci;iiiiiiiiiiiifff", + type, + &p_frame->mode, + &p_frame->fix_type, + &p_frame->satellites[0], + &p_frame->satellites[1], + &p_frame->satellites[2], + &p_frame->satellites[3], + &p_frame->satellites[4], + &p_frame->satellites[5], + &p_frame->satellites[6], + &p_frame->satellites[7], + &p_frame->satellites[8], + &p_frame->satellites[9], + &p_frame->satellites[10], + &p_frame->satellites[11], + &p_frame->pdop, + &p_frame->hdop, + &p_frame->vdop)) + { + LOG(WARN, "Failed to parse GSA,sentence:%s", p_sentence); + return false; + } + + if (GM_strcmp(type+2, "GSA")) + { + return false; + } + return true; +} + +bool nmea_parse_gll(NMEASentenceGLL* p_frame, const char* p_sentence) +{ + char type[MAX_TYPE_LEN] = {0}; + S32 latitude_direction = 0; + S32 longitude_direction = 0; + + if (!nmea_scan(p_sentence, "tfdfdTc;c", + type, + &p_frame->latitude, &latitude_direction, + &p_frame->longitude, &longitude_direction, + &p_frame->time, + &p_frame->status, + &p_frame->mode)) + { + return false; + } + + if (GM_strcmp(type+2, "GLL")) + { + return false; + } + + p_frame->latitude.value *= latitude_direction; + p_frame->longitude.value *= longitude_direction; + + return true; +} + +bool nmea_parse_gst(NMEASentenceGST*p_frame, const char* p_sentence) +{ + char type[MAX_TYPE_LEN] = {0}; + + if (!nmea_scan(p_sentence, "tTfffffff", + type, + &p_frame->time, + &p_frame->rms_deviation, + &p_frame->semi_major_deviation, + &p_frame->semi_minor_deviation, + &p_frame->semi_major_orientation, + &p_frame->latitude_error_deviation, + &p_frame->longitude_error_deviation, + &p_frame->altitude_error_deviation)) + { + return false; + } + + if (GM_strcmp(type+2, "GST")) + { + return false; + } + + return true; +} + + +//泰斗: $GPGSV,4,2,14,09,34,250,,11,58,192,,16,24,064,,18,51,145,,0*66 +//中科微:$GPGSV,3,1,10,01,29,175,,07,43,325,,08,66,357,,09,35,255,,0*6F +bool nmea_parse_gsv(NMEASentenceGSV* p_frame, const char* p_sentence) +{ + char type[MAX_TYPE_LEN] = {0}; + + if (!nmea_scan(p_sentence, "tiii;iiiiiiiiiiiiiiii", + type, + &p_frame->total_msgs, + &p_frame->msg_number, + &p_frame->total_satellites, + &p_frame->satellites[0].nr, + &p_frame->satellites[0].elevation, + &p_frame->satellites[0].azimuth, + &p_frame->satellites[0].snr, + &p_frame->satellites[1].nr, + &p_frame->satellites[1].elevation, + &p_frame->satellites[1].azimuth, + &p_frame->satellites[1].snr, + &p_frame->satellites[2].nr, + &p_frame->satellites[2].elevation, + &p_frame->satellites[2].azimuth, + &p_frame->satellites[2].snr, + &p_frame->satellites[3].nr, + &p_frame->satellites[3].elevation, + &p_frame->satellites[3].azimuth, + &p_frame->satellites[3].snr + )) + { + return false; + } + + if (GM_strcmp(type+2, "GSV")) + { + return false; + } + return true; +} + +bool nmea_parse_vtg(NMEASentenceVTG* p_frame, const char* p_sentence) +{ + char type[MAX_TYPE_LEN] = {0}; + char c_true = 0; + char c_magnetic = 0; + char c_knots = 0; + char c_kph = 0; + char c_faa_mode = 0; + + if (!nmea_scan(p_sentence, "t;fcfcfcfcc", + type, + &p_frame->true_track_degrees, + &c_true, + &p_frame->magnetic_track_degrees, + &c_magnetic, + &p_frame->speed_knots, + &c_knots, + &p_frame->speed_kph, + &c_kph, + &c_faa_mode)) + { + return false; + } + + if (GM_strcmp(type+2, "VTG")) + { + return false; + } + + // check chars + if (c_true != 'T' || c_magnetic != 'M' || c_knots != 'N' || c_kph != 'K') + { + return false; + } + + p_frame->faa_mode = (NMEAFAAMode)c_faa_mode; + + return true; +} + +bool nmea_parse_zda(NMEASentenceZDA* p_frame, const char* p_sentence) +{ + char type[MAX_TYPE_LEN] = {0}; + + if(!nmea_scan(p_sentence, "tTiiiii", + type, + &p_frame->time, + &p_frame->date.day, + &p_frame->date.month, + &p_frame->date.year, + &p_frame->hour_offset, + &p_frame->minute_offset)) + { + return false; + } + + if (GM_strcmp(type+2, "ZDA")) + { + return false; + } + + // check offsets + if (abs(p_frame->hour_offset) > 13 || p_frame->minute_offset > 59 || p_frame->minute_offset < 0) + { + return false; + } + return true; +} + +bool nmea_parse_mtk_ack(NMEASentenceMTKACK* p_frame, const char* p_sentence) +{ + char type[MAX_TYPE_LEN] = {0}; + U16 ack_type = 0; + if(!nmea_scan(p_sentence, "ti", + type, + &ack_type)) + { + return false; + } + if (GM_strcmp(type, "PMTK001")) + { + return false; + } + p_frame->ack_type = (MTKAckType)ack_type; + + return true; +} + +bool nmea_parse_mtk_ver(NMEASentenceVER* p_frame, const char* p_sentence) +{ + return true; +} + + +bool nmea_parse_td_ack(U16* p_cmd, const char* p_sentence, const U16 len) +{ + U16 head_buff[8] = {0}; + if (NULL == p_cmd || NULL == p_sentence || len < 8) + { + return false; + } + GM_memcpy(head_buff, p_sentence, 8); + *p_cmd = head_buff[3]; + return true; +} + +bool nmea_parse_td_ver(NMEASentenceVER* p_frame, const char* p_sentence, const U16 len) +{ + U16 head_buff[8] = {0}; + U16 data_len = 0; + GM_memcpy(head_buff, p_sentence, 8); + data_len = head_buff[1]; + if (len < data_len + 6) + { + return false; + } + else + { + GM_memcpy(p_frame->ver,p_sentence + 6, data_len); + return true; + } +} + +bool nmea_parse_at_ack(U16* p_cmd, const char* p_sentence, const U16 len) +{ + U16 head_buff[8] = {0}; + if (NULL == p_cmd || NULL == p_sentence || len < 8) + { + return false; + } + GM_memcpy(head_buff, p_sentence, 8); + *p_cmd = head_buff[3]; + return true; +} + +//中科微二进制查询版本号响应包,目前芯片还不支持,只有TXT格式的查询版本号 +bool nmea_parse_at_ver(NMEASentenceVER* p_frame, const char* p_sentence, const U16 len) +{ + U16 head_buff[8] = {0}; + U16 data_len = 0; + GM_memcpy(head_buff, p_sentence, 8); + data_len = head_buff[1]; + if (len < data_len + 6) + { + return false; + } + else + { + GM_memcpy(p_frame->ver,p_sentence + 6, data_len); + return true; + } +} + +void nmea_create_common_mtk_sentence(const char* cmd,U8* p_sentence) +{ + GM_sprintf((char*)p_sentence,"$%s*%02X\r\n",cmd, nmea_checksum(cmd)); +} + + +/** + * Function: 创建内置(MTK)查询版本号语句 + * Description: + * Input: p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_mtk_qeury_version_sentence(U8* p_sentence, U8* p_len) +{ + char cmd[] = "PMTK605"; + if (NULL == p_sentence || NULL == p_len || *p_len < GM_strlen(cmd)) + { + *p_len = 0; + return false; + } + nmea_create_common_mtk_sentence(cmd,p_sentence); + *p_len = GM_strlen((char*)p_sentence); + return true; +} + + +/** + * Function: 创建MTK(2503内置)GPS芯片AGPS辅助时间语句 + * Description: + * Input: st_time:UTC时间(注意不是本地时间);leap_sencond——闰秒值;p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_mtk_aid_time_sentence(const ST_Time st_time, U8* p_sentence, U8* p_len) +{ + U8 max_lenth = 64; + char cmd[64] = {0}; + if (NULL == p_sentence || NULL == p_len || *p_len < max_lenth) + { + *p_len = 0; + return false; + } + GM_snprintf(cmd,max_lenth,"PMTK740,%d,%d,%d,%d,%d,%d",st_time.year,st_time.month,st_time.day,st_time.hour,st_time.minute,st_time.second); + nmea_create_common_mtk_sentence(cmd,p_sentence); + *p_len = GM_strlen((char*)p_sentence); + return true; +} + +/** + * Function: 创建MTK(2503内置)GPS芯片AGPS辅助位置语句 + * Description: + * Input: ref_lat:辅助位置纬度;ref_lng:辅助位置经度;p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_mtk_aid_pos_sentence(const float ref_lat, const float ref_lng, U8* p_sentence, U8* p_len) +{ + U8 max_lenth = 64; + char cmd[64] = {0}; + if (NULL == p_sentence || NULL == p_len || *p_len < max_lenth) + { + *p_len = 0; + return false; + } + GM_snprintf(cmd,max_lenth,"PMTK713,%f,%f,0,30000,30000,0,1200,50",ref_lat,ref_lng); + nmea_create_common_mtk_sentence(cmd,p_sentence); + *p_len = GM_strlen((char*)p_sentence); + return true; +} + +bool nmea_creat_mtk_full_cold_start_sentence(U8* p_sentence, U8* p_len) +{ + U8 max_lenth = 64; + char cmd[64] = {0}; + if (NULL == p_sentence || NULL == p_len || *p_len < max_lenth) + { + *p_len = 0; + return false; + } + GM_snprintf(cmd,max_lenth,"PMTK104"); + nmea_create_common_mtk_sentence(cmd,p_sentence); + *p_len = GM_strlen((char*)p_sentence); + return true; +} + +bool nmea_creat_mtk_cold_start_sentence(U8* p_sentence, U8* p_len) +{ + U8 max_lenth = 64; + char cmd[64] = {0}; + if (NULL == p_sentence || NULL == p_len || *p_len < max_lenth) + { + *p_len = 0; + return false; + } + GM_snprintf(cmd,max_lenth,"PMTK103"); + nmea_create_common_mtk_sentence(cmd,p_sentence); + *p_len = GM_strlen((char*)p_sentence); + return true; +} + +bool nmea_creat_high_accuracy_sentence(bool enable,U8* p_sentence, U8* p_len) +{ + U8 max_lenth = 64; + char cmd[64] = {0}; + if (NULL == p_sentence || NULL == p_len || *p_len < max_lenth) + { + *p_len = 0; + return false; + } + GM_snprintf(cmd,max_lenth,"PMTK257,%d",enable); + nmea_create_common_mtk_sentence(cmd,p_sentence); + *p_len = GM_strlen((char*)p_sentence); + return true; +} + +bool nmea_creat_active_interference_cancellation(bool enable,U8* p_sentence, U8* p_len) +{ + U8 max_lenth = 64; + char cmd[64] = {0}; + if (NULL == p_sentence || NULL == p_len || *p_len < max_lenth) + { + *p_len = 0; + return false; + } + GM_snprintf(cmd,max_lenth,"PMTK286,%d",enable); + nmea_create_common_mtk_sentence(cmd,p_sentence); + *p_len = GM_strlen((char*)p_sentence); + return true; +} + + +bool nmea_creat_set_min_snr_sentence(const U8 min_SNR, U8* p_sentence, U8* p_len) +{ + U8 max_lenth = 64; + char cmd[64] = {0}; + if (NULL == p_sentence || NULL == p_len || *p_len < max_lenth) + { + *p_len = 0; + return false; + } + GM_snprintf(cmd,max_lenth,"PMTK306,%d",min_SNR); + nmea_create_common_mtk_sentence(cmd,p_sentence); + *p_len = GM_strlen((char*)p_sentence); + return true; +} + +bool nmea_creat_mtk_epo_sentence(const U16 seg_index, const U8* p_data, const U16 data_len, U8* p_sentence, U16* p_len) +{ + U8 max_lenth = 64; + char cmd[300] = {0}; + int index = 0; + const U32* p_data_u32 = (const U32*)p_data; + if (NULL == p_sentence || NULL == p_len || *p_len < max_lenth) + { + *p_len = 0; + return false; + } + GM_sprintf(cmd,"PMTK721,%X",seg_index); + for(index = 0; index < (data_len/sizeof(U32)); index++) + { + GM_sprintf(cmd + GM_strlen(cmd),",%X",p_data_u32[index]); + } + nmea_create_common_mtk_sentence(cmd,p_sentence); + *p_len = GM_strlen((char*)p_sentence); + return true; +} + +U16 flet_cher_16(const U8* pbuf, U16 len) +{ + U16 cs1 = 0; + U16 cs2 = 0; + while(len--) + { + cs1 += *pbuf++; + cs2 += cs1; + } + return (cs2 << 8) | (cs1 & 0xFF); +} + +static bool nmea_create_td_sentence(const U16 cmd,const U8* p_data,const U16 data_len, U8* p_sentence, U8* p_len) +{ + U8 sentence_index = 0; + U16 check_sum = 0; + U16 head = TD_SENTENCE_HEAD; + U8 oter_len = sizeof(head) + sizeof(cmd) + sizeof(data_len) + sizeof(check_sum); + + + if (NULL == p_sentence || NULL == p_len || *p_len < oter_len + data_len) + { + *p_len = 0; + return false; + } + + //包头2个字节,CPU为小端模式,高字节在高内存地址 + //起始字节0x23 0x3E + GM_memcpy(p_sentence, &head, sizeof(head)); + sentence_index += sizeof(head); + + //命令字 + GM_memcpy(p_sentence + sentence_index, &cmd, sizeof(cmd)); + sentence_index += sizeof(cmd); + + // 数据长度(不算包头和校验) + GM_memcpy(p_sentence + sentence_index, &data_len, sizeof(data_len)); + sentence_index += sizeof(data_len); + + if (NULL != p_data && 0 != data_len) + { + // 数据 + GM_memcpy(p_sentence + sentence_index, p_data, data_len); + sentence_index += data_len; + } + + //校验和从命令字开始 + check_sum = flet_cher_16(p_sentence + sizeof(head),sizeof(cmd) + sizeof(data_len) +data_len); + + GM_memcpy(p_sentence + sentence_index, &check_sum, sizeof(check_sum)); + sentence_index += sizeof(check_sum); + + *p_len = sentence_index; + + return true; + +} + +/** + * Function: 创建泰斗(TD)查询版本号语句 + * Description: + * Input: p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_td_qeury_version_sentence(U8* p_sentence, U8* p_len) +{ + return nmea_create_td_sentence(TD_AID_VER_CMD,NULL,0,p_sentence,p_len); +} + +//文档例子:23 3E 04 02 10 00 20 E1 07 09 14 0C 22 38 00 00 00 00 00 28 6B EE 22 98 +//20 表示闰秒改正数为32 +//E1 07 表示年为2017 年(十六进制07E1 转为十进制) +//09 表示9 月 +//14 表示20 日 +//0C 22 38 00 00 00 00 00 表示UTC 时间为12时34分56秒(小数秒建议固定为0) +bool nmea_creat_td_aid_time_sentence(const ST_Time st_time, const U8 leap_sencond, U8* p_sentence, U8* p_len) +{ + U8 data[SENTENCE_MAX_LENGTH] = {0}; + U8 data_len = 0; + U16 year = st_time.year; + //秒的小数部分 + U32 decimal_seconds = 0; + //时间精度4秒*1000000000 + U32 time_accuracy = (U32)4*pow(10,9); + + if (NULL == p_sentence || NULL == p_len) + { + *p_len = 0; + return false; + } + + data[data_len++] = leap_sencond; + + GM_memcpy(data + data_len, &year, sizeof(year)); + data_len += sizeof(year); + + data[data_len++] = st_time.month; + data[data_len++] = st_time.day; + data[data_len++] = st_time.hour; + data[data_len++] = st_time.minute; + + //考虑从服务器获取时间到现在已经过去了一秒 + data[data_len++] = st_time.second + 1; + + GM_memcpy(data + data_len, &decimal_seconds, sizeof(decimal_seconds)); + data_len += sizeof(decimal_seconds); + + GM_memcpy(data + data_len, &time_accuracy, sizeof(time_accuracy)); + data_len += sizeof(time_accuracy); + + return nmea_create_td_sentence(TD_AID_TIME_CMD,data,data_len,p_sentence,p_len); +} + +bool nmea_creat_td_aid_pos_sentence(const float ref_lat, const float ref_lng, U8* p_sentence, U8* p_len) +{ + U8 data[SENTENCE_MAX_LENGTH] = {0}; + U16 data_len = 0; + S32 lat = ref_lat*10000000; + S32 lng = ref_lng*10000000; + S32 alt = 0; + //辅助位置的精度 + S32 accuracy = 3000; + + if (NULL == p_sentence || NULL == p_len) + { + *p_len = 0; + return false; + } + + GM_memcpy(data + data_len, &lat, sizeof(lat)); + data_len += sizeof(lat); + + GM_memcpy(data + data_len, &lng, sizeof(lng)); + data_len += sizeof(lng); + + GM_memcpy(data + data_len, &alt, sizeof(alt)); + data_len += sizeof(alt); + + GM_memcpy(data + data_len, &accuracy, sizeof(accuracy)); + data_len += sizeof(accuracy); + + return nmea_create_td_sentence(TD_AID_POS_CMD,data,data_len,p_sentence,p_len); +} + +/** + * Function: 创建泰斗(TD)打开VTG语句 + * Description:23 3E 03 51 04 00 07 01 01 01 62 89 + * Input: p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_td_open_vtg_sentence( U8* p_sentence, U8* p_len) +{ + U8 data[SENTENCE_MAX_LENGTH] = {0}; + U8 data_len = 0; + + if (NULL == p_sentence || NULL == p_len) + { + *p_len = 0; + return false; + } + + data[data_len++] = 0x07; + data[data_len++] = 0x01; + data[data_len++] = 0x01; + data[data_len++] = 0x01; + + return nmea_create_td_sentence(TD_OPEN_FUNC_CMD,data,data_len,p_sentence,p_len); +} +/** + * Function: 创建中科微(AT)查询版本号语句 + * Description: + * Input: p_len:最大长度 + * Output: p_sentence:输出的辅助信息语句;p_len:语句长度 + * Return: true——成功;false——失败 + * Others: + */ +bool nmea_creat_at_qeury_version_sentence(U8* p_sentence, U8* p_len) +{ + U8 sentence_ic[SENTENCE_MAX_LENGTH] = {0}; + U8 sentence_sw[SENTENCE_MAX_LENGTH] = {0}; + if (NULL == p_sentence || NULL == p_len) + { + *p_len = 0; + return false; + } + + //查询硬件型号 + GM_snprintf((char*)sentence_ic,SENTENCE_MAX_LENGTH,"$PCAS06,1,*"); + GM_snprintf((char*)sentence_ic + GM_strlen((char*)sentence_ic),SENTENCE_MAX_LENGTH - GM_strlen((char*)sentence_ic),"%02X\r\n",nmea_checksum((char*)sentence_ic)); + + //查询软件版本号 + GM_snprintf((char*)sentence_sw + GM_strlen((char*)sentence_sw),SENTENCE_MAX_LENGTH,"$PCAS06,0,*"); + GM_snprintf((char*)sentence_sw + GM_strlen((char*)sentence_sw),SENTENCE_MAX_LENGTH - GM_strlen((char*)sentence_sw),"%02X\r\n",nmea_checksum((char*)sentence_sw)); + + if (*p_len >= GM_strlen((char*)sentence_ic)) + { + GM_memcpy(p_sentence, sentence_ic, GM_strlen((char*)sentence_ic)); + } + else + { + *p_len = 0; + return false; + } + + if (*p_len >= GM_strlen((char*)sentence_ic) + GM_strlen((char*)sentence_sw)) + { + GM_memcpy(p_sentence + GM_strlen((char*)sentence_ic), sentence_sw, GM_strlen((char*)sentence_sw)); + } + else + { + *p_len = 0; + return false; + } + + *p_len = GM_strlen((char*)sentence_ic) + GM_strlen((char*)sentence_sw); + return true; + +} + + +bool nmea_creat_at_aid_info_sentence(const ST_Time st_time, const U8 leap_sencond, const float ref_lat, const float ref_lng, U8* p_sentence, U8* p_len) +{ + ATAidInfo aid_info = {0}; + U16 head = AT_SENTENCE_HEAD; + U16 cmd = AT_AID_TIMEPOS_CMD; + U8 sentence_index = 0; + U8 pay_load_index = 0; + S32 check_sum = 0; + U16 len = sizeof(aid_info); + U16 sentence_len = sizeof(head) + sizeof(len) + sizeof(cmd) + sizeof(aid_info) + sizeof(check_sum); + + if (NULL == p_sentence || NULL == p_len || *p_len < sentence_len) + { + *p_len = 0; + return false; + } + + //包头6个字节,起始字两个字节,长度两个字节,命令字2个字节《CASIC多模卫星导航接收机协议规范.pdf》 + GM_memcpy(p_sentence + sentence_index, &head, sizeof(head)); + sentence_index += sizeof(head); + + // 数据长度(不算包头和校验) + GM_memcpy(p_sentence + sentence_index, &len, sizeof(len)); + sentence_index += sizeof(len); + + // cmd + GM_memcpy(p_sentence + sentence_index, &cmd, sizeof(cmd)); + sentence_index += sizeof(cmd); + + aid_info.df = 0; + aid_info.lat = ref_lat; + aid_info.lng = ref_lng; + aid_info.alt = 0; + aid_info.f_acc = 0; + aid_info.pos_acc = 0; + aid_info.t_acc = 0; + aid_info.time_source = 0; + aid_info.flags = 0x23; + + util_mtktime_to_gpstime(st_time,leap_sencond,&aid_info.tow,&aid_info.wn); + + GM_memcpy(p_sentence + sentence_index, (char*)(&aid_info), sizeof(aid_info)); + sentence_index += sizeof(aid_info); + check_sum = 0x010B0038; + LOG(DEBUG,"aid_info len:%d,check sum:%x",sizeof(aid_info)/sizeof(S32),check_sum); + for (pay_load_index = 0; pay_load_index < sizeof(aid_info)/sizeof(S32); pay_load_index++) + { + check_sum += *(((S32*)&aid_info) + pay_load_index); + } + + GM_memcpy(p_sentence + sentence_index, (char*)(&check_sum), sizeof(check_sum)); + sentence_index += sizeof(check_sum); + *p_len = sentence_index; + + return true; +} + +time_t nmea_get_utc_time(const NMEADate* p_date, const NMEATime* p_time) +{ + struct tm utc_time = {0}; + + if (NULL == p_date || NULL == p_time || p_date->year == -1 || p_time->hours == -1) + { + return 0; + } + + // (-INFINITY,80) + if (p_date->year < 80) + { + utc_time.tm_year = 2000 + p_date->year - 1900; + } + // [1900,+INFINITY) + else if (p_date->year >= 1900) + { + utc_time.tm_year = p_date->year - 1900; + } + // [80,1900) + else + { + utc_time.tm_year = p_date->year; + } + utc_time.tm_mon = p_date->month - 1; + utc_time.tm_mday = p_date->day; + utc_time.tm_hour = p_time->hours; + utc_time.tm_min = p_time->minutes; + utc_time.tm_sec = p_time->seconds; + return util_mktime(&utc_time); +} + +S32 nmea_rescale(const NMEAFloat* p_fraction, S32 new_scale) +{ + if (p_fraction->scale == 0) + { + return 0; + } + + if (p_fraction->scale == new_scale) + { + return p_fraction->value; + } + + if (p_fraction->scale > new_scale) + { + return (p_fraction->value + ((p_fraction->value > 0) - (p_fraction->value < 0)) * p_fraction->scale/new_scale/2) / (p_fraction->scale/new_scale); + } + else + { + return p_fraction->value * (new_scale/p_fraction->scale); + } +} + + +float nmea_tofloat(const NMEAFloat* p_fraction) +{ + if (p_fraction->scale == 0) + { + return 0; + } + return (float) p_fraction->value / (float) p_fraction->scale; +} + +float nmea_tocoord(const NMEAFloat* p_fraction) +{ + S32 degrees = 0; + S32 minutes = 0; + if (p_fraction->scale == 0) + { + return 0; + } + degrees = p_fraction->value / (p_fraction->scale * 100); + minutes = p_fraction->value % (p_fraction->scale * 100); + return (float) degrees + (float) minutes / (60 * p_fraction->scale); +} + diff --git a/src/protocol.c b/src/protocol.c new file mode 100644 index 0000000..1f3ba37 --- /dev/null +++ b/src/protocol.c @@ -0,0 +1,629 @@ +#include +#include "utility.h" +#include "gm_stdlib.h" +#include "gm_memory.h" +#include "gm_type.h" +#include "gsm.h" +#include "protocol.h" +#include "protocol_goome.h" +#include "protocol_jt808.h" +#include "protocol_concox.h" +#include "log_service.h" +#include "config_service.h" +#include "gps_save.h" +#include "gprs.h" +#include "gm_gprs.h" +#include "system_state.h" + +static bool protocol_msg_skiped_wrong(SocketType *socket, u8 *check, u16 check_len, u8 *head, u16 head_len) +{ + u16 start_idx = 0; + u16 idx = 0; + while(start_idx + check_len <= head_len) + { + bool match = true; + for(idx = 0; idx < check_len; ++idx ) + { + if(head[start_idx + idx] != check[idx]) + { + match = false; + break; + } + } + + if(match) + { + if(start_idx == 0) + { + //继续后面的执行 + return true; + } + else + { + //跳掉错误的消息, 等下次循环读取消息头 + LOG(WARN,"clock(%d) protocol_msg_skiped_wrong skiped(%d).", util_clock(), start_idx); + log_service_print_hex((const char *)head, head_len); + fifo_pop_len(&socket->fifo, start_idx); + return false; + } + } + else + { + start_idx++; + } + } + + //跳掉错误的消息, 等下次循环读取消息头 + LOG(WARN,"clock(%d) protocol_msg_skiped_wrong skiped(%d).", util_clock(), start_idx); + log_service_print_hex((const char *)head, head_len); + fifo_pop_len(&socket->fifo, start_idx); + return false; +} + +static bool alloc_memory_for_socket_msg(u8 **ppdata, u16 msg_len, SocketType *socket) +{ + if(*ppdata) + { + return true; + } + + *ppdata = GM_MemoryAlloc(msg_len); + if(*ppdata == NULL) + { + LOG(INFO,"clock(%d) alloc_memory_for_socket_msg alloc buf failed. len:%d", util_clock(), msg_len); + + //clear fifo and restart socket. + fifo_reset(&socket->fifo); + system_state_set_gpss_reboot_reason("malloc error."); + gm_socket_close_for_reconnect(socket); + return false; + } + return true; +} + + + +static bool get_jt808_message(u8 *pdata, u16 *len_p) +{ + u8 *pend; + if(*pdata != PROTOCOL_HEADER_JT808) + { + LOG(WARN,"clock(%d) get_jt808_message assert first byte failed.", util_clock()); + return false; + } + + pend = pdata + 1; + while((pend - pdata + 1) <= (*len_p)) + { + if(*pend == PROTOCOL_HEADER_JT808) + { + *len_p = (pend - pdata + 1); + return true; + } + pend ++; + } + return false; +} + +void protocol_msg_receive(SocketType *socket) +{ + u8 head[7]; + u32 len = sizeof(head); + u16 msg_len = 0; + u8 *pdata = NULL; + static u32 packet_error_start = 0; + + if(socket->status != SOCKET_STATUS_LOGIN && socket->status != SOCKET_STATUS_WORK) + { + LOG(WARN,"clock(%d) protocol_msg_receive socket->status(%s) error.", util_clock(), gm_socket_status_string((SocketStatus)socket->status)); + return; + } + + /* + goome协议 最短7 + 信息头(0x67 0x67) 2 协议号1 包长度2(下一字节至包尾) 信息序列号2 信息内容 N + + concox协议 最短10 + 起始位 2 包长度(下一字节至错误校验) 1 协议号 1 信息内容 N 信息序列号 2 错误校验 2 停止位 2 + + jt808协议 最短15 + 标志位1(0x7e) 消息头12/14(ID 2 属性2(10位长度) 终端号6 流水2 封装0/4(属性 位13决定)) 消息体N 校验1 标志位1 + 注意0x7e转码 0x7e->0x7d+02 0x7d->0x7d+01 + */ + + if(GM_SUCCESS != fifo_peek(&socket->fifo, head, len)) + { + // no msg + return; + } + + switch(config_service_get_app_protocol()) + { + case PROTOCOL_GOOME: + msg_len = MKWORD(head[3], head[4]); + msg_len = msg_len + 5; + break; + case PROTOCOL_CONCOX: + if(PROTOCOL_HEADER_CONCOX == head[0] && PROTOCOL_HEADER_CONCOX == head[1]) + { + msg_len = head[2]; + msg_len += 5; + } + else if(PROTOCOL_HEADER_CONCOX_NEW == head[0] && PROTOCOL_HEADER_CONCOX_NEW == head[1]) + { + msg_len = MKWORD(head[2], head[3]);; + msg_len += 6; + } + else + { + LOG(WARN,"clock(%d) protocol_msg_receive assert(PROTOCOL_CONCOX protocol(%d) head(%02x)) failed.", + util_clock(), config_service_get_app_protocol(), head[0]); + return; + } + break; + case PROTOCOL_JT808: + { + u8 check[1] = {0x7e}; + u32 msglen; + if(!protocol_msg_skiped_wrong(socket,check,sizeof(check),head,sizeof(head))) + { + return; + } + + /* + jt808 要以0x7e至0x7e 作为消息. + 直接取消息中的长度,会导致消息在有转义时取不全 + */ + msglen = MAX_JT808_MSG_LEN; + if(!alloc_memory_for_socket_msg(&pdata, msglen, socket)) + { + return; + } + if(GM_SUCCESS != fifo_peek_and_get_len(&socket->fifo, pdata, &msglen)) + { + GM_MemoryFree(pdata); + return; + } + msg_len = msglen; + if(!get_jt808_message(pdata, &msg_len)) + { + GM_MemoryFree(pdata); + return; + } + break; + } + default: + LOG(WARN,"clock(%d) protocol_msg_receive assert(protocol(%d) head(%02x)) failed.", + util_clock(), config_service_get_app_protocol(), head[0]); + return; + } + + if(msg_len > MAX_GPRS_MESSAGE_LEN) + { + LOG(WARN,"clock(%d) protocol_msg_receive assert(msg_len(%d)) failed.",util_clock(), msg_len); + //clear fifo and restart socket. + fifo_reset(&socket->fifo); + system_state_set_gpss_reboot_reason("msg_len error."); + gm_socket_close_for_reconnect(socket); + + //actually,for jt808 it is less than MAX_JT808_MSG_LEN,so, will not in this branch + if(pdata) GM_MemoryFree(pdata); + return; + } + + if(!alloc_memory_for_socket_msg(&pdata, msg_len, socket)) + { + return; + } + + if(GM_SUCCESS != fifo_peek(&socket->fifo, pdata, msg_len)) + { + // GM_EMPTY_BUF + GM_MemoryFree(pdata); + + if(packet_error_start == 0) + { + LOG(DEBUG,"clock(%d) protocol_msg_receive get msg failed. len:%d", util_clock(), msg_len); + log_service_print_hex((const char*)head, sizeof(head)); + packet_error_start = util_clock(); + } + else + { + if((util_clock() - packet_error_start) > MAX_GPRS_PART_MESSAGE_TIMEOUT) + { + LOG(WARN,"clock(%d) protocol_msg_receive MAX_GPRS_PART_MESSAGE_TIMEOUT.",util_clock()); + //clear fifo and restart socket. + fifo_reset(&socket->fifo); + system_state_set_gpss_reboot_reason("msg only part."); + gm_socket_close_for_reconnect(socket); + packet_error_start = 0; + } + } + return; + } + fifo_pop_len(&socket->fifo, msg_len); + LOG(DEBUG,"clock(%d) protocol_msg_receive msg len(%d) head(%02x)", util_clock(), msg_len, head[0]); + + switch(config_service_get_app_protocol()) + { + case PROTOCOL_GOOME: // PROTOCOL_HEADER_GOOME + protocol_goome_parse_msg(pdata, msg_len); + break; + case PROTOCOL_CONCOX: + log_service_print_hex((const char *)pdata, msg_len); + protocol_concox_parse_msg(pdata, msg_len); + break; + case PROTOCOL_JT808: + protocol_jt_parse_msg(pdata, msg_len); + break; + default: + LOG(WARN,"clock(%d) protocol_msg_receive assert(app protocol(%d)) failed.", util_clock(), config_service_get_app_protocol()); + break; + } + + GM_MemoryFree(pdata); +} + + + + + + +GM_ERRCODE protocol_send_login_msg(SocketType *socket) +{ + u8 buff[200]; + u16 len = sizeof(buff); + u16 idx = 0; + u8 value_u8 = 0; + + GM_memset(buff, 0x00, sizeof(buff)); + + switch(config_service_get_app_protocol()) + { + case PROTOCOL_GOOME: + protocol_goome_pack_login_msg(buff, &idx, len); //16 bytes + break; + case PROTOCOL_CONCOX: + protocol_concox_pack_login_msg(buff, &idx, len); // PROTOCOL_VER_GT02 22bytes. other 18bytes + break; + case PROTOCOL_JT808: + config_service_get(CFG_JT_ISREGISTERED, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if(value_u8) + { + protocol_jt_pack_auth_msg(buff, &idx, len); // max 115 bytes + LOG(DEBUG,"clock(%d) protocol_send_login_msg PROTOCOL_JT808 auth msg len(%d)).", util_clock(), idx); + } + else + { + protocol_jt_pack_regist_msg(buff, &idx, len); // max 76 byes + LOG(DEBUG,"clock(%d) protocol_send_login_msg PROTOCOL_JT808 regist msg len(%d)).", util_clock(), idx); + } + break; + default: + LOG(WARN,"clock(%d) protocol_send_login_msg assert(app protocol(%d)) failed.", util_clock(), config_service_get_app_protocol()); + return GM_PARAM_ERROR; + } + + len=idx; // idx is msg len + + socket->send_time = util_clock(); + LOG(DEBUG,"clock(%d) protocol_send_login_msg len(%d) protocol(%d).", util_clock(), len, config_service_get_app_protocol()); + if(GM_SUCCESS != gm_socket_send(socket, buff, idx)) + { + system_state_set_gpss_reboot_reason("gm_socket_send login"); + gps_service_destroy_gprs(); + return GM_NET_ERROR; + } + + return GM_SUCCESS; +} + + +GM_ERRCODE protocol_send_device_msg(SocketType *socket) +{ + u8 buff[50]; + u16 len = sizeof(buff); + u16 idx = 0; + + if(socket->status != SOCKET_STATUS_LOGIN && socket->status != SOCKET_STATUS_WORK) + { + LOG(WARN,"clock(%d) protocol_send_device_msg socket->status(%s) error.", util_clock(), gm_socket_status_string((SocketStatus)socket->status)); + return GM_PARAM_ERROR; + } + + switch(config_service_get_app_protocol()) + { + case PROTOCOL_GOOME: + protocol_goome_pack_iccid_msg(buff, &idx, len); //17 bytes + break; + case PROTOCOL_CONCOX: + protocol_concox_pack_device_status_msg(buff, &idx, len); //38bytes + break; + case PROTOCOL_JT808: + protocol_jt_pack_iccid_msg(buff, &idx, len); // max 39 bytes + break; + default: + LOG(WARN,"clock(%d) protocol_send_device_msg assert(app protocol(%d)) failed.", util_clock(), config_service_get_app_protocol()); + return GM_PARAM_ERROR; + } + + len=idx; // idx is msg len + + socket->send_time = util_clock(); + LOG(DEBUG,"clock(%d) protocol_send_device_msg len(%d) protocol(%d).", util_clock(), len, config_service_get_app_protocol()); + if(GM_SUCCESS != gm_socket_send(socket, buff, idx)) + { + system_state_set_gpss_reboot_reason("gm_socket_send devmsg"); + gps_service_destroy_gprs(); + return GM_NET_ERROR; + } + + return GM_SUCCESS; +} + + +GM_ERRCODE protocol_send_heartbeat_msg(SocketType *socket) +{ + u8 buff[20]; + u16 len = sizeof(buff); + u16 idx = 0; + + if(socket->status != SOCKET_STATUS_LOGIN && socket->status != SOCKET_STATUS_WORK) + { + LOG(WARN,"clock(%d) protocol_send_heartbeat_msg socket->status(%s) error.", util_clock(), gm_socket_status_string((SocketStatus)socket->status)); + return GM_PARAM_ERROR; + } + + switch(config_service_get_app_protocol()) + { + case PROTOCOL_GOOME: + protocol_goome_pack_heartbeat_msg(buff, &idx, len); //17 bytes + break; + case PROTOCOL_CONCOX: + protocol_concox_pack_heartbeat_msg(buff, &idx, len); // max 20 bytes + break; + case PROTOCOL_JT808: + protocol_jt_pack_heartbeat_msg(buff, &idx, len); // max 19 bytes + break; + default: + LOG(WARN,"clock(%d) protocol_send_heartbeat_msg assert(app protocol(%d)) failed.", util_clock(), config_service_get_app_protocol()); + return GM_PARAM_ERROR; + } + + len=idx; // idx is msg len + + LOG(DEBUG,"clock(%d) protocol_send_heartbeat_msg len(%d) protocol(%d).", util_clock(), len, config_service_get_app_protocol()); + socket->send_time = util_clock(); + if(GM_SUCCESS != gm_socket_send(socket, buff, idx)) + { + system_state_set_gpss_reboot_reason("gm_socket_send heart"); + gps_service_destroy_gprs(); + return GM_NET_ERROR; + } + return GM_SUCCESS; +} + + + +U32 protocol_send_gps_msg(SocketType *socket) +{ + + LocationSaveData one; + U32 send_counts = 0; + + if(socket->status != SOCKET_STATUS_WORK) + { + LOG(WARN,"clock(%d) protocol_send_gps_msg socket->status(%s) error.", util_clock(), gm_socket_status_string((SocketStatus)socket->status)); + return 0; + } + + + //先发送最新的数据 + while(GM_SUCCESS == gps_service_peek_one(&one, 0)) + { + LOG(DEBUG,"clock(%d) protocol_send_gps_msg len(%d).", util_clock(), one.len); + if(one.len == 0) + { + gps_service_commit_peek(0); + continue; + } + + if(GM_SUCCESS == gps_service_cache_send(one.buf, one.len)) + { + gps_service_commit_peek(0); + send_counts++; + if(send_counts >= MAX_GPS_MSGS_PER_SEND) + { + break; + } + } + else + { + break; + } + } + + return send_counts; +} + + +GM_ERRCODE protocol_send_logout_msg(SocketType *socket) +{ + u8 buff[20]; + u16 len = sizeof(buff); + u16 idx = 0; + + + if(socket->status != SOCKET_STATUS_WORK) + { + LOG(WARN,"clock(%d) protocol_send_logout_msg socket->status(%s) error.", util_clock(), gm_socket_status_string((SocketStatus)socket->status)); + return GM_PARAM_ERROR; + } + + switch(config_service_get_app_protocol()) + { + case PROTOCOL_GOOME: + return GM_SUCCESS; //ignore + case PROTOCOL_CONCOX: + return GM_SUCCESS; //ignore + case PROTOCOL_JT808: + protocol_jt_pack_logout_msg(buff, &idx, len); // 15 bytes + break; + default: + LOG(WARN,"clock(%d) protocol_send_logout_msg assert(app protocol(%d)) failed.", util_clock(), config_service_get_app_protocol()); + return GM_PARAM_ERROR; + } + + len=idx; // idx is msg len + + LOG(DEBUG,"clock(%d) protocol_send_logout_msg len(%d) protocol(%d).", util_clock(), len, config_service_get_app_protocol()); + + socket->send_time = util_clock(); + if(GM_SUCCESS != gm_socket_send(socket, buff, idx)) + { + system_state_set_gpss_reboot_reason("gm_socket_send logout"); + gps_service_destroy_gprs(); + return GM_NET_ERROR; + } + + return GM_SUCCESS; +} + + +GM_ERRCODE protocol_send_remote_ack(SocketType *socket, u8 *pRet, u16 retlen) +{ + u8 *buff; + u16 len = 30 + retlen; //jt808 need 22 bytes + u16 idx = 0; + + if(socket->status != SOCKET_STATUS_LOGIN && socket->status != SOCKET_STATUS_WORK) + { + LOG(WARN,"clock(%d) protocol_send_remote_ack socket->status(%s) error.", util_clock(), gm_socket_status_string((SocketStatus)socket->status)); + return GM_PARAM_ERROR; + } + + buff = GM_MemoryAlloc(len); + if (NULL == buff) + { + LOG(WARN,"clock(%d) protocol_send_remote_ack assert(GM_MemoryAlloc(%d)) failed.", util_clock(), len); + return GM_MEM_NOT_ENOUGH; + } + + switch(config_service_get_app_protocol()) + { + case PROTOCOL_GOOME: + protocol_goome_pack_remote_ack(buff, &idx, len, pRet, retlen); //12+retlen bytes + break; + case PROTOCOL_CONCOX: + protocol_concox_pack_remote_ack(buff, &idx, len, pRet, retlen); // max 18+retlen bytes + break; + case PROTOCOL_JT808: + protocol_jt_pack_remote_ack(buff, &idx, len, pRet, retlen); //22|26 +retlen bytes + break; + default: + LOG(WARN,"clock(%d) protocol_send_remote_ack assert(app protocol(%d)) failed.", util_clock(), config_service_get_app_protocol()); + GM_MemoryFree(buff); + return GM_PARAM_ERROR; + } + + len=idx; // idx is msg len + + socket->send_time = util_clock(); + if(GM_SUCCESS != gm_socket_send(socket, buff, idx)) + { + system_state_set_gpss_reboot_reason("gm_socket_send remote_ack"); + gps_service_destroy_gprs(); + GM_MemoryFree(buff); + return GM_NET_ERROR; + } + GM_MemoryFree(buff); + return GM_SUCCESS; +} + + + +GM_ERRCODE protocol_send_general_ack(SocketType *socket) +{ + u8 buff[50]; + u16 len = sizeof(buff); + u16 idx = 0; + + if(socket->status != SOCKET_STATUS_WORK) + { + LOG(WARN,"clock(%d) protocol_send_remote_ack socket->status(%s) error.", util_clock(), gm_socket_status_string((SocketStatus)socket->status)); + return GM_PARAM_ERROR; + } + + switch(config_service_get_app_protocol()) + { + case PROTOCOL_JT808: + protocol_jt_pack_general_ack(buff, &idx, len); //max 24 bytes + break; + default: + LOG(WARN,"clock(%d) protocol_send_general_ack assert(app protocol(%d)) failed.", util_clock(), config_service_get_app_protocol()); + return GM_PARAM_ERROR; + } + + len=idx; // idx is msg len + LOG(DEBUG,"clock(%d) protocol_send_general_ack len(%d) protocol(%d).", util_clock(), len, config_service_get_app_protocol()); + + socket->send_time = util_clock(); + if(GM_SUCCESS != gm_socket_send(socket, buff, idx)) + { + system_state_set_gpss_reboot_reason("gm_socket_send geneal_ack"); + gps_service_destroy_gprs(); + return GM_NET_ERROR; + } + return GM_SUCCESS; +} + + + +GM_ERRCODE protocol_send_param_get_ack(SocketType *socket) +{ + u8 *buff; + u16 len = 1000; + u16 idx = 0; + + if(socket->status != SOCKET_STATUS_WORK) + { + LOG(WARN,"clock(%d) protocol_send_remote_ack socket->status(%s) error.", util_clock(), gm_socket_status_string((SocketStatus)socket->status)); + return GM_PARAM_ERROR; + } + + + buff = GM_MemoryAlloc(len); + if (NULL == buff) + { + LOG(WARN,"clock(%d) protocol_send_param_get_ack assert(GM_MemoryAlloc(%d)) failed.", util_clock(), len); + return GM_MEM_NOT_ENOUGH; + } + + switch(config_service_get_app_protocol()) + { + case PROTOCOL_JT808: + protocol_jt_pack_param_ack(buff, &idx, len); + break; + default: + LOG(WARN,"clock(%d) protocol_send_param_get_ack assert(app protocol(%d)) failed.", util_clock(), config_service_get_app_protocol()); + GM_MemoryFree(buff); + return GM_PARAM_ERROR; + } + + len=idx; // idx is msg len + LOG(DEBUG,"clock(%d) protocol_send_param_get_ack len(%d) protocol(%d).", util_clock(), len, config_service_get_app_protocol()); + + socket->send_time = util_clock(); + if(GM_SUCCESS != gm_socket_send(socket, buff, idx)) + { + system_state_set_gpss_reboot_reason("gm_socket_send param_ack"); + gps_service_destroy_gprs(); + GM_MemoryFree(buff); + return GM_NET_ERROR; + } + GM_MemoryFree(buff); + return GM_SUCCESS; +} + + + diff --git a/src/protocol_concox.c b/src/protocol_concox.c new file mode 100644 index 0000000..590e2c5 --- /dev/null +++ b/src/protocol_concox.c @@ -0,0 +1,1399 @@ +#include "gps.h" +#include "protocol_concox.h" +#include +#include "applied_math.h" +#include "utility.h" +#include "gm_stdlib.h" +#include "gm_memory.h" +#include "gm_type.h" +#include "gsm.h" +#include "log_service.h" +#include "config_service.h" +#include "hard_ware.h" +#include "protocol.h" +#include "gps.h" +#include "gps_service.h" +#include "sms.h" +#include "system_state.h" +#include "command.h" +#include "g_sensor.h" +#include "agps_service.h" + +typedef enum +{ + PROTOCCOL_CONCOX_LOGIN = 0x01, // 登录包 + PROTOCCOL_CONCOX_LOCAT_GT06 = 0x12, // 位置包 + PROTOCCOL_CONCOX_HEART = 0x13, // 心跳 + PROTOCCOL_CONCOX_STRING_MSG = 0x15, + PROTOCCOL_CONCOX_ALARM_GT06 = 0x16, + PROTOCCOL_CONCOX_CH_LOCAT_ACK = 0x17, //中文地址请求或者报警回复 + PROTOCCOL_CONCOX_REMOTE_MSG = 0x21, + PROTOCCOL_CONCOX_LOCAT = 0x22, + PROTOCCOL_CONCOX_ALARM = 0x26, + PROTOCCOL_CONCOX_ZONE_TIE = 0x27, + PROTOCCOL_CONCOX_FULL_LBS = 0x28, // 多基站数据 + PROTOCCOL_CONCOX_LOCAT_REQ = 0x2A, + PROTOCCOL_CONCOX_HEART_EXPAND = 0x36, //康凯斯扩展心跳 + PROTOCCOL_CONCOX_REMOTE_MSG_REQ = 0x80, + PROTOCCOL_CONCOX_STATUS_MSG = 0x94, //信息传输通用包 + PROTOCCOL_CONCOX_EN_LOCAT_ACK = 0x97, //英文地址请求或者报警回复 +}ProtocolConcoxCmdEnum; + +typedef enum +{ + DEV_STATUS_EX_POWER = 0x00, + DEV_STATUS_SYNC = 0x04, + DEV_STATUS_DOOR = 0x05, + DEV_STATUS_SELF_TEST = 0x08, + DEV_STATUS_FIXED_SAT = 0x09, + DEV_STATUS_ICCID_IMEI = 0x0A, + DEV_STATUS_MAX +}ProtocolConcoxDeviceStatusEnum; + + +/*用于记录发送消息的序列号, 收到消息的序列号等*/ +typedef struct +{ + AlarmTypeEnum last_alarm; //最近一个报警消息 + u16 msg_serial; //上传数据序列号, 每次发消息加一 + u8 msg_flag; // 信息标识, 服务器传过来, 原样传回 + u8 server_id[4]; // 服务器标志 , 服务器传过来, 原样传回 +}ConcoxMsgSave; + +static ConcoxMsgSave s_concox_msg_save = {ALARM_NONE, 0 , }; + +static protocol_concox_pack_head(u8 *pdata, u16 *idx, u16 len, bool new); +static protocol_concox_pack_tail(u8 *pdata, u16 *idx, u16 len); +static void protocol_concox_pack_imei(U8* pdata, u16 *idx, u16 len); +static void protocol_concox_pack_imsi(U8* pdata, u16 *idx, u16 len); +static void protocol_concox_pack_iccid(U8* pdata, u16 *idx, u16 len); +static void protocol_concox_pack_type_id(U8* pdata, u16 *idx, u16 len); +static void protocol_concox_pack_language(U8* pdata, u16 *idx, u16 len); +static void protocol_concox_pack_id_len(U8* pdata, u8 id, u16 len, bool new); +static void protocol_concox_pack_device_status(u8 *pdata, u16 *idx, u16 len); +static void protocol_concox_pack_voltage_status(u8 *pdata, u16 *idx, u16 len); +static void protocol_concox_pack_signal_status(u8 *pdata, u16 *idx, u16 len); +static void protocol_concox_pack_alarm_language(u8 *pdata, u16 *idx, u16 len, AlarmInfo *alarm); +static void protocol_concox_pack_power_volt(u8 *pdata, u16 *idx, u16 len); + +static void protocol_concox_pack_device_status_imei(u8 *pdata, u16 *idx, u16 len); + +static void protocol_concox_parse_login_response(U8* pdata, u16 len, bool new); +static void protocol_concox_parse_ch_locate_ack(U8* pdata, u16 len, bool ucs2); +static void protocol_concox_alarm_sms_ask(U8* pdata, u16 len, bool ucs2); +static void protocol_concox_parse_remote_msg(U8* pdata, u16 len, bool new); +static void protocol_concox_parse_en_locate_ack(U8* pdata, u16 len); + + +static protocol_concox_pack_head(u8 *pdata, u16 *idx, u16 len, bool new) +{ + u8 tag = PROTOCOL_HEADER_CONCOX; + if(new) + { + tag = PROTOCOL_HEADER_CONCOX_NEW; + } + + if((*idx) + 4 > len) + { + LOG(WARN,"protocol_concox_pack_head assert(len(%d)) failed.", len); + return; + } + + pdata[(*idx)++] = tag; + pdata[(*idx)++] = tag; + + if(new) + { + (*idx) = (*idx) + 3; // len 2 id 1 + } + else + { + (*idx) = (*idx) + 2; // len 1 id 1 + } +} + +static protocol_concox_pack_tail(u8 *pdata, u16 *idx, u16 len) +{ + if((*idx) + 6 > len) + { + LOG(WARN,"protocol_concox_pack_tail assert(len(%d)) failed.", len); + return; + } + + ++(s_concox_msg_save.msg_serial); + + pdata[(*idx)++] = BHIGH_BYTE(s_concox_msg_save.msg_serial); + pdata[(*idx)++] = BLOW_BYTE(s_concox_msg_save.msg_serial); + + (*idx) += 2; //checksum + + pdata[(*idx)++] = 0x0D; + pdata[(*idx)++] = 0x0A; +} + +static void protocol_concox_pack_imei(U8* pdata, u16 *idx, u16 len) +{ + GM_ERRCODE ret = GM_SUCCESS; + u8 imei[GM_IMEI_LEN + 1] = {0}; + if(GM_SUCCESS != (ret = gsm_get_imei(imei))) + { + LOG(INFO,"protocol_concox_pack_imei can not get imei, ret:%d.", ret); + } + + if (0 == GM_strlen((const char *)imei)) + { + GM_memset(imei, 0, sizeof(imei)); + } + + if((*idx) + 8 > len) + { + LOG(WARN,"protocol_concox_pack_imei assert(len(%d)) failed.", len); + return; + } + + pdata[(*idx)++] = util_chr(imei[0]); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[1]), util_chr(imei[2])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[3]), util_chr(imei[4])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[5]), util_chr(imei[6])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[7]), util_chr(imei[8])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[9]), util_chr(imei[10])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[11]), util_chr(imei[12])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[13]), util_chr(imei[14])); +} + + +static void protocol_concox_pack_imsi(U8* pdata, u16 *idx, u16 len) +{ + GM_ERRCODE ret = GM_SUCCESS; + u8 imsi[GM_IMSI_LEN + 1] = {0}; + if(GM_SUCCESS != (ret = gsm_get_imsi(imsi))) + { + LOG(INFO,"protocol_concox_pack_imsi can not get imsi, ret:%d.", ret); + } + + if (0 == GM_strlen((const char *)imsi)) + { + GM_memset(imsi, 0, sizeof(imsi)); + } + + if((*idx) + 8 > len) + { + LOG(WARN,"protocol_concox_pack_imsi assert(len(%d)) failed.", len); + return; + } + + pdata[(*idx)++] = util_chr(imsi[0]); + pdata[(*idx)++] = MERGEBCD(util_chr(imsi[1]), util_chr(imsi[2])); + pdata[(*idx)++] = MERGEBCD(util_chr(imsi[3]), util_chr(imsi[4])); + pdata[(*idx)++] = MERGEBCD(util_chr(imsi[5]), util_chr(imsi[6])); + pdata[(*idx)++] = MERGEBCD(util_chr(imsi[7]), util_chr(imsi[8])); + pdata[(*idx)++] = MERGEBCD(util_chr(imsi[9]), util_chr(imsi[10])); + pdata[(*idx)++] = MERGEBCD(util_chr(imsi[11]), util_chr(imsi[12])); + pdata[(*idx)++] = MERGEBCD(util_chr(imsi[13]), util_chr(imsi[14])); +} + +static void protocol_concox_pack_iccid(U8* pdata, u16 *idx, u16 len) +{ + GM_ERRCODE ret = GM_SUCCESS; + u8 iccid[GM_ICCID_LEN + 1] = {0}; + if(GM_SUCCESS != (ret = gsm_get_iccid(iccid))) + { + LOG(INFO,"protocol_concox_pack_iccid can not get iccid, ret:%d.", ret); + } + + if (0 == GM_strlen((const char *)iccid)) + { + GM_memset(iccid, 0, sizeof(iccid)); + } + + if((*idx) + 10 > len) + { + LOG(WARN,"protocol_concox_pack_iccid assert(len(%d)) failed.", len); + return; + } + + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[0]), util_chr(iccid[1])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[2]), util_chr(iccid[3])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[4]), util_chr(iccid[5])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[6]), util_chr(iccid[7])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[8]), util_chr(iccid[9])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[10]), util_chr(iccid[11])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[12]), util_chr(iccid[13])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[14]), util_chr(iccid[15])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[16]), util_chr(iccid[17])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[18]), util_chr(iccid[19])); +} + + +static void protocol_concox_pack_type_id(U8* pdata, u16 *idx, u16 len) +{ + u8 value_u8; + /* + 0x20 0x00 GT02D/GT220 带断油电功能 + 0x20 0x01 GT02D/GT220 不带断油电功能 + */ + + if((*idx) + 2 > len) + { + LOG(WARN,"protocol_concox_pack_type_id assert(len(%d)) failed.", len); + return; + } + + config_service_get(CFG_IS_RELAY_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + pdata[(*idx)++] = 0x20; //固定GT02D + pdata[(*idx)++] = (value_u8) ? 0x00 : 0x01; +} + + +static void protocol_concox_pack_language(U8* pdata, u16 *idx, u16 len) +{ + u16 language = 0; + s8 zone; + u16 zone_data; + u8 value_u8 = 0; + + if((*idx) + 2 > len) + { + LOG(WARN,"protocol_concox_pack_language assert(len(%d)) failed.", len); + return; + } + + zone = config_service_get_zone(); + + zone_data = (zone&0x7F)*100*16; + + pdata[(*idx)++] = BHIGH_BYTE(zone_data); + value_u8 = BLOW_BYTE(zone_data); + value_u8 = value_u8 & 0xF0; + + if (zone & 0x80) + { + SET_BIT3(value_u8); // 西时区 Bit3 0:东时区 1:西时区 + } + + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &language, sizeof(language)); + if (1 == language) + { + SET_BIT1(value_u8); // 10简体中文 + } + else + { + SET_BIT2(value_u8); // 100英文 + } + + pdata[(*idx)++] = value_u8; +} + + +//长度=协议号+信息内容+信息序列号+错误校验 +static void protocol_concox_pack_id_len(U8* pdata, u8 id, u16 len, bool new) +{ + u16 checksum=0; + + if(new) + { + pdata[2] = BHIGH_BYTE(len); + pdata[3] = BLOW_BYTE(len); + pdata[4] = id; + } + else + { + pdata[2] = (u8)len; + pdata[3] = id; + } + + checksum = applied_math_calc_common_crc16(&pdata[2], len-1); + pdata[len + 1] = BHIGH_BYTE(checksum); + pdata[len + 2] = BLOW_BYTE(checksum); +} + + + + +void protocol_concox_pack_login_msg(u8 *pdata, u16 *idx, u16 len) +{ + u8 app_ver; + protocol_concox_pack_head(pdata, idx, len, false); //4bytes 0x78 0x78 len(1) id(1) + protocol_concox_pack_imei(pdata, idx, len); //8bytes + config_service_get(CFG_PROTOCOL_VER, TYPE_BYTE, &app_ver, sizeof(app_ver)); + if(app_ver == PROTOCOL_VER_GT02) + { + protocol_concox_pack_type_id(pdata, idx, len); //2bytes + protocol_concox_pack_language(pdata, idx, len); //2bytes + } + protocol_concox_pack_tail(pdata, idx, len); //6bytes serial(2) checksum(2) stop(2) + + //len not include 0x78 0x78 len(1) stop(2) + protocol_concox_pack_id_len(pdata, PROTOCCOL_CONCOX_LOGIN, (*idx) - 5, false); + + log_service_print_hex((const char *) pdata, *idx); + return; +} + + +static void protocol_concox_pack_device_status_imei(u8 *pdata, u16 *idx, u16 len) +{ + pdata[(*idx)++] = DEV_STATUS_ICCID_IMEI; + protocol_concox_pack_imei(pdata, idx, len); // 8bytes + protocol_concox_pack_imsi(pdata, idx, len); // 8bytes + protocol_concox_pack_iccid(pdata, idx, len); // 10bytes +} + + +void protocol_concox_pack_device_status_msg(u8 *pdata, u16 *idx, u16 len) +{ + protocol_concox_pack_head(pdata, idx, len, true); //5bytes 0x79 0x79 len(2) id(1) + protocol_concox_pack_device_status_imei(pdata, idx, len); // 27bytes + protocol_concox_pack_tail(pdata, idx, len); //6bytes serial(2) checksum(2) stop(2) + + //len not include 0x79 0x79 len(2) stop(2) + protocol_concox_pack_id_len(pdata, PROTOCCOL_CONCOX_STATUS_MSG, (*idx) - 6, true); + + log_service_print_hex((const char *) pdata, *idx); + return; +} + + +static void protocol_concox_pack_device_status(u8 *pdata, u16 *idx, u16 len) +{ + u8 app_ver; + u8 value_u8 = 0; + bool value_bool = false; + u32 sys_state; + + if((*idx) + 1 > len) + { + LOG(WARN,"protocol_concox_pack_device_status assert(len(%d)) failed.", len); + return; + } + + sys_state = system_state_get_status_bits(); + + // 油电状态 + if(SYSBIT_RELAY_STATE & sys_state) + { + SET_BIT7(value_u8); + } + + // 定位状态 + if (gps_is_fixed()) + { + SET_BIT6(value_u8); + } + + + // 充电器插入状态 + if (system_state_get_has_started_charge()) + { + SET_BIT2(value_u8); + } + + if(SYSBIT_ALARM_SPEED & sys_state) + { + config_service_get(CFG_PROTOCOL_VER, TYPE_BYTE, &app_ver, sizeof(app_ver)); + if(app_ver == PROTOCOL_VER_GT02) + { + SET_BIT5(value_u8); + SET_BIT4(value_u8); + } + } + else if (SYSBIT_ALARM_LOW_POWER & sys_state) + { + SET_BIT4(value_u8); + SET_BIT3(value_u8); + } + else if (SYSBIT_ALARM_NO_POWER & sys_state) + { + SET_BIT4(value_u8); + } + else if (SYSBIT_ALARM_SHOCK & sys_state) + { + SET_BIT3(value_u8); + } + + + // ACC状态 + if(GM_SUCCESS != hard_ware_get_acc_level(&value_bool)) + { + LOG(WARN,"protocol_concox_pack_device_status assert(hard_ware_get_acc_level) failed."); + } + + if (value_bool) + { + SET_BIT1(value_u8); + } + else + { + CLR_BIT1(value_u8); + } + + //设防状态 + config_service_get(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &value_bool, sizeof(value_bool)); + if (value_bool) + { + SET_BIT0(value_u8); + } + else + { + CLR_BIT0(value_u8); + } + + + pdata[(*idx)++] = value_u8; +} + + +static void protocol_concox_pack_voltage_status(u8 *pdata, u16 *idx, u16 len) +{ + u8 level = 0; + + if((*idx) + 1 > len) + { + LOG(WARN,"protocol_concox_pack_voltage_status assert(len(%d)) failed.", len); + return; + } + + if(GM_SUCCESS != hard_ware_get_internal_battery_level(&level)) + { + LOG(WARN,"protocol_concox_pack_voltage_status assert(hard_ware_get_power_voltage) failed."); + } + pdata[(*idx)++] = level; +} + + +static void protocol_concox_pack_signal_status(u8 *pdata, u16 *idx, u16 len) +{ + u8 value_u8 = 0; + u8 val; + + if((*idx) + 1 > len) + { + LOG(WARN,"protocol_concox_pack_signal_status assert(len(%d)) failed.", len); + return; + } + + val = gsm_get_csq(); + + if (val < 5) + { + value_u8 = 0; // 0x00: 无信号 + } + else if (val <= 10) + { + value_u8 = 1; // 0x01:信号极弱 + } + else if (val <= 16) + { + value_u8 = 2; // 0x02:信号较弱 + } + else if (val <= 25) + { + value_u8 = 3; // 0x03:信号良好 + } + else if (val <= 31) + { + value_u8 = 4; // 0x04:信号强 + } + else if (val > 31) + { + value_u8 = 0; // 0x00: 无信号 + } + else + { + value_u8 = 0; // 0x00: 无信号 + } + + pdata[(*idx)++] = value_u8; +} + + +static void protocol_concox_pack_alarm_language(u8 *pdata, u16 *idx, u16 len, AlarmInfo *alarm) +{ + u16 language = 0; + u8 value_u8 = 0; + + + if((*idx) + 2 > len) + { + LOG(WARN,"protocol_concox_pack_alarm_language assert(len(%d)) failed.", len); + return; + } + + //每次只能发送一个报警 + value_u8 = 0; + if(alarm) + { + s_concox_msg_save.last_alarm = alarm->type; + switch(alarm->type) + { + case ALARM_POWER_OFF: + value_u8 = 0x02; + break; + case ALARM_SHOCK: + value_u8 = 0x03; + break; + case ALARM_SPEED: + value_u8 = 0x06; + break; + case ALARM_MOVE: + value_u8 = 0x09; + break; + case ALARM_FAKE_CELL: + value_u8 = 0x0A; + break; + case ALARM_BATTERY_LOW: + value_u8 = 0x19; + break; + case ALARM_POWER_HIGH: + value_u8 = 0x40; + break; + case ALARM_COLLISION: + switch(alarm->info) + { + case SLIGHT_COLLISION: + value_u8 = 0x41; + break; + case NORMAL_COLLISION: + value_u8 = 0x42; + break; + case SERIOUS_COLLISION: + value_u8 = 0x43; + break; + default: //just for compatable or error. + value_u8 = 0x42; + break; + } + break; + case ALARM_SPEED_UP: + value_u8 = 0x44; + break; + case ALARM_SPEED_DOWN: + value_u8 = 0x45; + break; + case ALARM_TURN_OVER: + value_u8 = 0x47; + break; + case ALARM_SHARP_TURN: + value_u8 = 0x46; + break; + case ALARM_REMOVE: + value_u8 = 0x0C; + break; + default: + break; + } + } + pdata[(*idx)++] = value_u8; + + value_u8 = 0; + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &language, sizeof(language)); + if (1 == language) + { + SET_BIT0(value_u8); // 10简体中文 + } + else + { + SET_BIT1(value_u8); // 01英文 + } + + pdata[(*idx)++] = value_u8; +} + + + +static void protocol_concox_pack_power_volt(u8 *pdata, u16 *idx, u16 len) +{ + float value_float; + u16 value_u16 = 0; + + if((*idx) + 5 > len) + { + LOG(WARN,"protocol_concox_pack_power_volt assert(len(%d)) failed.", len); + return; + } + + + if(GM_SUCCESS != hard_ware_get_power_voltage(&value_float)) + { + LOG(WARN,"protocol_concox_pack_power_volt assert(hard_ware_get_power_voltage) failed."); + } + + pdata[(*idx)++] = 0x00; + pdata[(*idx)++] = 0x27; + pdata[(*idx)++] = 0x02; + + value_u16 = (u16)(value_float * 100.0f); + pdata[(*idx)++] = (u8)UPPER_BYTE(value_u16); + pdata[(*idx)++] = (u8)LOWER_BYTE(value_u16); +} + + +void protocol_concox_pack_heartbeat_msg(u8 *pdata, u16 *idx, u16 len) +{ + protocol_concox_pack_head(pdata, idx, len, false); //4bytes 0x78 0x78 len(1) id(1) + protocol_concox_pack_device_status(pdata, idx, len); //1bytes + protocol_concox_pack_voltage_status(pdata, idx, len); //1bytes + protocol_concox_pack_signal_status(pdata, idx, len); //1bytes + + //原版本是心跳与LBS数据都报一条报警, 但由于这个版本中报警消息独立上报,这里就不再带alarm了 + protocol_concox_pack_alarm_language(pdata, idx, len, NULL); //2bytes + + if(HEART_EXPAND == config_service_get_heartbeat_protocol()) + { + protocol_concox_pack_power_volt(pdata, idx, len); //5bytes + protocol_concox_pack_tail(pdata, idx, len); //6bytes serial(2) checksum(2) stop(2) + protocol_concox_pack_id_len(pdata, PROTOCCOL_CONCOX_HEART_EXPAND, (*idx) - 5, false); + } + else + { + protocol_concox_pack_tail(pdata, idx, len); //6bytes serial(2) checksum(2) stop(2) + + //len not include 0x78 0x78 len(1) stop(2) + protocol_concox_pack_id_len(pdata, PROTOCCOL_CONCOX_HEART, (*idx) - 5, false); + } + + log_service_print_hex((const char *) pdata, *idx); + + return; +} + + +static void protocol_concox_pack_gps(const GPSData *gps, U8* pdata, u16 *idx, u16 len) +{ + u8 zone = 0, value_u8 = 0; + bool value_bool = false; + + u32 latitudev = 0; + u32 longitudev = 0; + u16 gpsrspeed = 0; + u16 gpsangle = 0; + u16 t_idx = *idx; + + if((*idx) + 18 > len) + { + LOG(WARN,"protocol_concox_pack_gps assert(len(%d)) failed.", len); + return; + } + + //zone = config_service_get_zone(); + util_get_current_local_time(&pdata[(*idx)], NULL, zone); + for(t_idx = *idx; t_idx < (*idx + 6); ++t_idx) + { + pdata[t_idx] = BCD2HEX(pdata[t_idx]); + } + (*idx) += 6; + + pdata[(*idx)] = 0xC0; + pdata[(*idx)++] += gps->satellites; + LOG(DEBUG,"protocol_concox_pack_gps satellites(%d).", gps->satellites); + + // 纬度 + if (gps->lat < 0.0) + { + latitudev = (u32)(gps->lat * (-1800000.0f)); + } + else + { + latitudev = (u32)(gps->lat * 1800000.0f); + } + + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(latitudev)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(latitudev)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(latitudev)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(latitudev)); + + // 经度 + if (gps->lng < 0.0) + { + longitudev = (u32)(gps->lng*(-1800000.0f)); + } + else + { + longitudev = (u32)(gps->lng*1800000.0f); + } + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(longitudev)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(longitudev)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(longitudev)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(longitudev)); + + + // 速度 + gpsrspeed = gps->speed; + if (gpsrspeed > 180) + { + gpsrspeed = 180; + } + pdata[(*idx)++] = (u8)gpsrspeed; + + // 角度 + gpsangle = (u16)gps->course; + if (gpsangle >= 360) + { + gpsangle = 0; + } + + // 纬度 负数为南纬 + value_u8 = 0; + if (gps->lat >= 0.00001f) + { + SET_BIT2(value_u8); //北纬 + } + + // 经度 负数为西经 + if (gps->lng < 0.00001f) + { + SET_BIT3(value_u8); //西经 + } + + switch(gps_get_state()) + { + case GM_GPS_FIX_3D: + SET_BIT4(value_u8); //已定位 + break; + case GM_GPS_FIX_3D_DIFF: + SET_BIT4(value_u8); //已定位 + SET_BIT5(value_u8); //差分定位 + break; + default: + break; + } + + // ACC状态 + if(GM_SUCCESS == hard_ware_get_acc_level(&value_bool)) + { + SET_BIT6(value_u8); // ACC有效 + if (value_bool) + { + SET_BIT7(value_u8); + } + } + + pdata[(*idx)++] = BHIGH_BYTE(gpsangle) | value_u8; + pdata[(*idx)++] = BLOW_BYTE(gpsangle); +} + + + +static void protocol_concox_pack_lbs(U8* pdata, u16 *idx, u16 len) +{ + gm_cell_info_struct lbs; + GM_ERRCODE ret; + + GM_memset(&lbs,0, sizeof(lbs)); + + if((*idx) + 8 > len) + { + LOG(WARN,"protocol_concox_pack_lbs assert(len(%d)) failed.", len); + return; + } + + ret = gsm_get_cell_info(&lbs); + LOG(DEBUG,"clock(%d) protocol_concox_pack_lbs ret(%d) lbs(%d).", util_clock(), ret, lbs.nbr_cell_num); + + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.mcc); // MCC 2 + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.mcc); + + pdata[(*idx)++] = lbs.serv_info.mnc; // MNC + + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.lac); // LAC 2 + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.lac); + + + pdata[(*idx)++] = 0x00; //CI 3 + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.ci); + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.ci); +} + + +static void protocol_concox_pack_acc(GpsDataModeEnum mode, U8* pdata, u16 *idx, u16 len) +{ + bool value_bool = false; + + if((*idx) + 3 > len) + { + LOG(WARN,"protocol_concox_pack_acc assert(len(%d)) failed.", len); + return; + } + + // ACC状态 + if(GM_SUCCESS != hard_ware_get_acc_level(&value_bool)) + { + LOG(WARN,"protocol_concox_pack_acc assert(hard_ware_get_acc_level) failed."); + } + + if (value_bool) + { + pdata[(*idx)++] = 1; + } + else + { + pdata[(*idx)++] = 0; + } + + + // 数据上报模式 + pdata[(*idx)++] = mode; + + // GPS 实时补传 现在还不知道状态, 要实际发送时才知道 , 先打包成实时发送. 补发时再纠正 + // 0x00?实时上传 0x01?补传 + pdata[(*idx)++] = 0; +} + + +void protocol_concox_pack_gps_msg(GpsDataModeEnum mode, const GPSData *gps, u8 *pdata, u16 *idx, u16 len) +{ + u8 app_ver; + protocol_concox_pack_head(pdata, idx, len, false); //4bytes 0x78 0x78 len(1) id(1) + protocol_concox_pack_gps(gps, pdata, idx, len); //18 bytes + protocol_concox_pack_lbs(pdata, idx, len); //8 bytes + + config_service_get(CFG_PROTOCOL_VER, TYPE_BYTE, &app_ver, sizeof(app_ver)); + if(app_ver == PROTOCOL_VER_GT02) + { + protocol_concox_pack_acc(mode, pdata, idx, len); //3 bytes + + protocol_concox_pack_tail(pdata, idx, len); //6bytes serial(2) checksum(2) stop(2) + + //len not include 0x78 0x78 len(1) stop(2) + protocol_concox_pack_id_len(pdata, PROTOCCOL_CONCOX_LOCAT, (*idx) - 5, false); + + } + else + { + protocol_concox_pack_tail(pdata, idx, len); //6bytes serial(2) checksum(2) stop(2) + + //len not include 0x78 0x78 len(1) stop(2) + protocol_concox_pack_id_len(pdata, PROTOCCOL_CONCOX_LOCAT_GT06, (*idx) - 5, false); + } + + log_service_print_hex((const char *) pdata, *idx); + return; +} + + +#if 0 +static void protocol_concox_pack_lbses(U8* pdata, u16 *idx, u16 len) +{ + gm_cell_info_struct lbs; + GM_ERRCODE ret; + u16 k = 0; + u16 num=0; + u16 lbsidx=0; + u8 zone; + + GM_memset(&lbs,0, sizeof(lbs)); + + if((*idx) + 51 > len) + { + LOG(WARN,"protocol_concox_pack_lbses assert(len(%d)) failed.", len); + return; + } + + ret = gsm_get_cell_info(&lbs); + LOG(DEBUG,"clock(%d) protocol_concox_pack_lbses ret(%d) lbs(%d).", util_clock(), ret, lbs.nbr_cell_num); + + zone = config_service_get_zone(); + util_get_current_local_time(&pdata[(*idx)], NULL, zone); + (*idx) += 6; + + //主基站 + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.mcc); // MCC 2 + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.mcc); + + pdata[(*idx)++] = lbs.serv_info.mnc; // MNC + + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.lac); // LAC 2 + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.lac); + + + pdata[(*idx)++] = 0x00; //CI 3 + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.ci); + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.ci); + + pdata[(*idx)++] = lbs.serv_info.rxlev;// 信号强度 + + + if (lbs.nbr_cell_num > 6) + { + num = 6; + } + else + { + num = lbs.nbr_cell_num; + } + + // 剩余6个基站 LAC(2B)+CI(3B)+RSSI(1B) + lbsidx = (*idx); + GM_memset(&pdata[lbsidx], 0, 36); + for (k=0; k len) + { + LOG(WARN,"clock(%d) protocol_concox_parse_remote_msg assert(len(%d) <= %d) failed.", util_clock(),pdata[idx - 5],len); + return; + } + + pOut = GM_MemoryAlloc(CMD_MAX_LEN + 1); + if (NULL == pOut) + { + LOG(WARN,"protocol_concox_parse_remote_msg assert(GM_MemoryAlloc(%d)) failed.", CMD_MAX_LEN + 1); + return; + } + + GM_memset(pOut, 0x00, CMD_MAX_LEN + 1); + + LOG(DEBUG,"clock(%d) protocol_concox_parse_remote_msg start:%d, len:%d.", util_clock(),idx,msg_len); + command_on_receive_data(COMMAND_GPRS, (char *)&pdata[idx], msg_len, (char *)pOut,NULL); + out_len = GM_strlen((char *)pOut); + + if (out_len > 0) + { + gps_service_after_receive_remote_msg(pOut, out_len); + } + + GM_MemoryFree(pOut); + return; +} + + + +void protocol_concox_pack_remote_ack(u8 *pdata, u16 *idx, u16 len, u8 *pRet, u16 retlen) +{ + bool app_new = false; + u16 language; + + protocol_concox_pack_head(pdata, idx, len, app_new); //4|5bytes 0x78 0x78 len(1|2) id(1) + pdata[(*idx) ++ ] = retlen + 4; + GM_memcpy(&pdata[(*idx)], s_concox_msg_save.server_id, sizeof(s_concox_msg_save.server_id)); + (*idx) += sizeof(s_concox_msg_save.server_id); + GM_memcpy(&pdata[(*idx)], pRet, retlen); + (*idx) += retlen; + + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &language, sizeof(language)); + if (1 == language) + { + pdata[(*idx) ++ ] = 00; + pdata[(*idx) ++ ] = 01; // 00 01简体中文 + } + else + { + pdata[(*idx) ++ ] = 00; + pdata[(*idx) ++ ] = 02; // 00 02英文 + } + protocol_concox_pack_tail(pdata, idx, len); //6bytes serial(2) checksum(2) stop(2) + + //len not include 0x78 0x78 len(1) stop(2) + protocol_concox_pack_id_len(pdata, PROTOCCOL_CONCOX_STRING_MSG, (*idx) - 5, app_new); +} + +static void protocol_concox_parse_login_response(U8* pdata, u16 len, bool new) +{ + // 0x78 0x78 0x05 0x01 0x00 0x01 0xD9 0xDC 0x0D 0x0A + // 起始位 长度 协议号 序列号 错误校验 停止位 + + if(len != 10) + { + LOG(WARN,"protocol_concox_parse_login_response assert(len(%d) != 7) failed.", len); + return; + } + + + //发送iccid + gps_service_after_login_response(); + + return; +} + +static void protocol_concox_parse_ch_locate_ack(U8* pdata, u16 len, bool ucs2) +{ + u16 idx = 0; + u8 alarm_flag[10]; + u8 recv_msg[250]; + u16 recv_msg_w[125]; + u8 msg_len = 0; + u8 sms_num[GM_ICCID_LEN + 1]; + + GM_memset(alarm_flag, 0x00, sizeof(alarm_flag)); + GM_memset(recv_msg, 0x00, sizeof(recv_msg)); + GM_memset(sms_num, 0x00, sizeof(sms_num)); + + idx += 9; + + if(len <= idx + 33) // tail 6bytes. && && ## 6bytes phone_number 21bytes + { + LOG(WARN,"clock(%d) protocol_concox_parse_ch_locate_ack assert(len(%d) > %d) failed.", util_clock(), len,idx + 33); + return; + } + if (('#' != pdata[len - 8]) || ('#' != pdata[len - 7])) + { + LOG(WARN,"clock(%d) protocol_concox_parse_ch_locate_ack assert(##) failed.", util_clock()); + return; + } + + + //协议文档中是8个字节,实际是变长 + for (msg_len=0; msg_len<(len-idx - 33); msg_len++) + { + if (('&' == pdata[idx+msg_len]) && ('&' == pdata[idx+msg_len+1])) + { + break; + } + } + + if (('&' != pdata[idx+msg_len]) || ('&' != pdata[idx+msg_len+1]) || msg_len >(sizeof(alarm_flag) - 1)) + { + LOG(WARN,"clock(%d) protocol_concox_parse_ch_locate_ack assert(content&&) failed. msg_len(%d).", util_clock(), msg_len); + return; + } + + GM_memcpy(alarm_flag, &pdata[idx], msg_len); + alarm_flag[msg_len] = 0x00; + idx += msg_len; + + idx += 2; + for (msg_len=0; msg_len<(len-idx - 8); msg_len++) + { + if (('&' == pdata[idx+msg_len]) && ('&' == pdata[idx+msg_len+1])) + { + break; + } + } + + if (('&' != pdata[idx+msg_len]) || ('&' != pdata[idx+msg_len+1]) || msg_len >(sizeof(recv_msg) - 1)) + { + LOG(WARN,"clock(%d) protocol_concox_parse_ch_locate_ack assert(content&&) failed. msg_len(%d).", util_clock(), msg_len); + return; + } + + GM_memcpy(recv_msg, &pdata[idx], msg_len); + recv_msg[msg_len] = 0x00; + + idx = idx + msg_len + 2; + + GM_memcpy(sms_num, &pdata[idx], sizeof(sms_num)); + sms_num[GM_ICCID_LEN] = 0; + idx = idx + sizeof(sms_num); + if (('#' != pdata[idx]) || ('#' != pdata[idx+1])) + { + LOG(WARN,"clock(%d) protocol_concox_parse_ch_locate_ack assert(content##) failed.", util_clock()); + return; + } + + ucs2 = true; //acctually in english, it still use unicode. + if(ucs2) + { + u16 index; + + //把UTF-8转成UNICODE + index = util_utf8_to_unicode(recv_msg, msg_len, recv_msg_w, msg_len); + + //把双字节的UNICODE转成单字节的UNICODE + msg_len = util_ucs2_u16_to_u8(recv_msg_w, index,recv_msg ); + } + + + if (0 == GM_memcmp("ALARMSMS", alarm_flag, GM_strlen((const char* )alarm_flag))) + { + LOG(DEBUG,"clock(%d) protocol_concox_parse_ch_locate_ack alarm_sms_ask msglen(%d).", util_clock(),msg_len); + protocol_concox_alarm_sms_ask((u8 *)recv_msg_w, msg_len, ucs2); + } + else if (0 == GM_memcmp("ADDRESS", &alarm_flag, GM_strlen((const char* )&alarm_flag))) + { + LOG(DEBUG,"clock(%d) protocol_concox_parse_ch_locate_ack msglen(%d) sms_num(%s).", util_clock(),msg_len,sms_num); + sms_send((char*)recv_msg_w, msg_len, (char*)sms_num, (ucs2?GM_UCS2_DCS:GM_8BIT_DCS)); + } + else + { + LOG(WARN,"clock(%d) protocol_concox_parse_ch_locate_ack unknown alarm_flag(%s).", util_clock(),alarm_flag); + } +} + + +static void protocol_concox_parse_en_locate_ack(U8* pdata, u16 len) +{ + protocol_concox_parse_ch_locate_ack(pdata, len, false); +} + + + + +static void protocol_concox_alarm_sms_ask(u8 *pdata, u16 len, bool ucs2) +{ + u8 number[GM_ICCID_LEN + 1]; + u16 number_len = 0; + u16 index; + u8 value_u8; + + if(len <=0) + { + LOG(DEBUG,"clock(%d) protocol_goome_alarm_ask msglen(%d).", util_clock(), len); + return; + } + + switch(s_concox_msg_save.last_alarm) + { + case ALARM_POWER_OFF: + case ALARM_POWER_HIGH: + case ALARM_BATTERY_LOW: + config_service_get(CFG_POWER_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + if(value_u8 != PWRALM_GPRS_SMS || value_u8 != PWRALM_GPRS_SMS_CALL) + { + return ; + } + break; + case ALARM_SHOCK: + config_service_get(CFG_SENSOR_ALARM_MODE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + if(value_u8 != PWRALM_GPRS_SMS || value_u8 != PWRALM_GPRS_SMS_CALL) + { + return ; + } + break; + default: + return; + } + + + for (index=0; index<=3; index++) + { + number_len = config_service_get_sos_number(index, number, sizeof(number)); + number[number_len] = 0; + if (number_len > 0) + { + sms_send((char*)pdata, len, (char*)number, (ucs2?GM_UCS2_DCS:GM_8BIT_DCS)); + } + + if (config_service_is_alarm_sms_to_one()) + { + break; //只发第一个号 + } + } + +} + +void protocol_concox_pack_position_request_msg(u8 *mobile_num, u8 num_len, u8 *command, u8 cmd_len,u8 *pdata, u16 *idx, u16 len) +{ + GPSData gps; + GM_memset(&gps,0,sizeof(gps)); + + gps_get_last_data(&gps); + if(gps.gps_time == (time_t)0) + { + system_state_get_last_gps(&gps); + } + + if(gps.gps_time == (time_t)0) + { + gps.gps_time = util_get_utc_time(); + gps.lat = agps_service_get_unfix_lat(); + gps.lng = agps_service_get_unfix_lng(); + } + + protocol_concox_pack_head(pdata, idx, len, false); //4bytes 0x78 0x78 len(1) id(1) + protocol_concox_pack_gps(&gps, pdata, idx, len); //18 bytes + + + GM_memset(&pdata[(*idx)],0,21); + num_len = num_len < 21?num_len:20; + GM_memcpy(&pdata[(*idx)],mobile_num,num_len); + (*idx)+=21; //21 bytes + + protocol_concox_pack_alarm_language(pdata, idx, len, NULL); //2 bytes + protocol_concox_pack_tail(pdata, idx, len); //6bytes serial(2) checksum(2) stop(2) + + //len not include 0x78 0x78 len(1) stop(2) + protocol_concox_pack_id_len(pdata, PROTOCCOL_CONCOX_LOCAT_REQ, (*idx) - 5, false); +} + + + + diff --git a/src/protocol_goome.c b/src/protocol_goome.c new file mode 100644 index 0000000..05374ff --- /dev/null +++ b/src/protocol_goome.c @@ -0,0 +1,952 @@ +#include +#include "utility.h" +#include "gm_stdlib.h" +#include "gm_memory.h" +#include "gm_type.h" +#include "gsm.h" +#include "log_service.h" +#include "config_service.h" +#include "hard_ware.h" +#include "protocol.h" +#include "gps.h" +#include "protocol_goome.h" +#include "gps_service.h" +#include "sms.h" +#include "system_state.h" +#include "g_sensor.h" +#include "command.h" +#include "applied_math.h" +#include "agps_service.h" + +typedef enum +{ + PROTOCCOL_GOOME_LOGIN = 0x01, // 登录包 + PROTOCCOL_GOOME_LOCAT = 0x02, // 位置包 + PROTOCCOL_GOOME_HEART = 0x03, // 心跳 + PROTOCCOL_GOOME_ALARM = 0x04, // 报警 + PROTOCCOL_GOOME_STRING_MSG = 0x05, // 采集数据包 谷米暂无 + PROTOCCOL_GOOME_SMS_MSG = 0x06, // 短信指令上传数据包 + PROTOCCOL_GOOME_HEART_EXPAND = 0x07, // 扩展心跳数据包 + PROTOCCOL_GOOME_TIME_CALIB = 0x08, // 时间校准包 谷米暂无 + PROTOCCOL_GOOME_ICCID_MSG = 0x09, + PROTOCCOL_GOOME_REMOTE_MSG = 0x80, + PROTOCCOL_GOOME_GENERAL_MSG = 0x81, // 普通消息下发数据包 + PROTOCCOL_GOOME_FULL_LBS = 0x91, // 多基站数据 + PROTOCCOL_GOOME_STATUS_MSG = 0x94, //信息传输通用包 +}ProtocolGoomeCmdEnum;; + + +/*用于记录发送消息的序列号, 收到消息的序列号等*/ +typedef struct +{ + u16 msg_serial; //上传数据序列号, 每次发消息加一 + u8 msg_flag; // 信息标识, 服务器传过来, 原样传回 + u8 server_id[4]; // 服务器标志 , 服务器传过来, 原样传回 +}GoomeMsgSave; + +static GoomeMsgSave s_msg_save = {0, }; + +static void protocol_goome_pack_head(U8* pdata, u16 *idx, u16 len); +static void protocol_goome_pack_imei(U8* pdata, u16 *idx, u16 len); +static void protocol_goome_pack_language(U8* pdata, u16 *idx, u16 len); +static void protocol_goome_pack_id_len(U8* pdata, u8 id, u16 len); +static void protocol_goome_pack_iccid(U8* pdata, u16 *idx, u16 len); +static void protocol_goome_pack_lbs(U8* pdata, u16 *idx, u16 len); +static void protocol_goome_pack_lbses(U8* pdata, u16 *idx, u16 len); +static void protocol_goome_pack_locate_status(U8* pdata, u16 *idx, u16 len); +static void protocol_goome_pack_alarm(AlarmInfo *alarm,U8* pdata, u16 *idx, u16 len); +static void protocol_goome_pack_csq(U8* pdata, u16 *idx, u16 len); +static void protocol_goome_pack_power_voltage(U8* pdata, u16 *idx, u16 len); +static void protocol_goome_pack_gps_signal_quality(U8* pdata, u16 *idx, u16 len); + +static void protocol_goome_parse_login_response(U8* pdata, u16 len); +static void protocol_goome_parse_remote_msg(U8* pdata, u16 len); + + +static void protocol_goome_pack_iccid(U8* pdata, u16 *idx, u16 len) +{ + GM_ERRCODE ret = GM_SUCCESS; + u8 iccid[GM_ICCID_LEN + 1] = {0}; + if(GM_SUCCESS != (ret = gsm_get_iccid(iccid))) + { + LOG(INFO,"clock(%d) protocol_goome_pack_iccid can not get iccid, ret:%d.", util_clock(), ret); + } + + if (0 == GM_strlen((const char *)iccid)) + { + GM_memset(iccid, 0, sizeof(iccid)); + } + + if((*idx) + 10 > len) + { + LOG(WARN,"clock(%d) protocol_goome_pack_iccid assert(len(%d)) failed.", util_clock(), len); + return; + } + + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[0]), util_chr(iccid[1])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[2]), util_chr(iccid[3])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[4]), util_chr(iccid[5])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[6]), util_chr(iccid[7])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[8]), util_chr(iccid[9])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[10]), util_chr(iccid[11])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[12]), util_chr(iccid[13])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[14]), util_chr(iccid[15])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[16]), util_chr(iccid[17])); + pdata[(*idx)++] = MERGEBCD(util_chr(iccid[18]), util_chr(iccid[19])); + +} + + +static void protocol_goome_pack_imei(U8* pdata, u16 *idx, u16 len) +{ + GM_ERRCODE ret = GM_SUCCESS; + u8 imei[GM_IMEI_LEN + 1] = {0}; + if(GM_SUCCESS != (ret = gsm_get_imei(imei))) + { + LOG(INFO,"clock(%d) protocol_goome_pack_imei can not get imei, ret:%d.", util_clock(), ret); + } + + if (0 == GM_strlen((const char *)imei)) + { + GM_memset(imei, 0, sizeof(imei)); + } + + if((*idx) + 8 > len) + { + LOG(WARN,"clock(%d) protocol_goome_pack_imei assert(len(%d)) failed.", util_clock(), len); + return; + } + + pdata[(*idx)++] = util_chr(imei[0]); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[1]), util_chr(imei[2])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[3]), util_chr(imei[4])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[5]), util_chr(imei[6])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[7]), util_chr(imei[8])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[9]), util_chr(imei[10])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[11]), util_chr(imei[12])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[13]), util_chr(imei[14])); + +} + + +static void protocol_goome_pack_head(U8* pdata, u16 *idx, u16 len) +{ + if((*idx) + 7 > len) + { + LOG(WARN,"clock(%d) protocol_goome_pack_head assert(len(%d)) failed.", util_clock(), len); + return; + } + + pdata[(*idx)++] = PROTOCOL_HEADER_GOOME; + pdata[(*idx)++] = PROTOCOL_HEADER_GOOME; + (*idx) = (*idx) + 3; // id 1 , len 2 + + ++(s_msg_save.msg_serial); + + pdata[(*idx)++] = BHIGH_BYTE(s_msg_save.msg_serial); + pdata[(*idx)++] = BLOW_BYTE(s_msg_save.msg_serial); + +} + +static void protocol_goome_pack_language(U8* pdata, u16 *idx, u16 len) +{ + u16 language = 0; + + if((*idx) + 1 > len) + { + LOG(WARN,"clock(%d) protocol_goome_pack_language assert(len(%d)) failed.", util_clock(), len); + return; + } + + config_service_get(CFG_LANGUAGE, TYPE_SHORT, &language, sizeof(language)); + pdata[(*idx)++] = (1 == language) ? 0x00 : 0x01; // 00简体中文 01英文 +} + +static void protocol_goome_pack_id_len(U8* pdata, u8 id, u16 len) +{ + pdata[2] = id; + len -= 5; + pdata[3] = BHIGH_BYTE(len); + pdata[4] = BLOW_BYTE(len); +} + +static void protocol_goome_pack_power_voltage(U8* pdata, u16 *idx, u16 len) +{ + U8 percent = 0.0; + hard_ware_get_internal_battery_percent(&percent); + pdata[(*idx)++] = percent; +} + +static void protocol_goome_pack_csq(U8* pdata, u16 *idx, u16 len) +{ + u8 csq; + csq = gsm_get_csq(); + + if (csq < 5) + { + pdata[(*idx)++] = 0; // 0x00: 无信号 + } + else if (csq <= 10) + { + pdata[(*idx)++] = 1; // 0x01:信号极弱 + } + else if (csq <= 16) + { + pdata[(*idx)++] = 2; // 0x02:信号较弱 + } + else if (csq <= 25) + { + pdata[(*idx)++] = 3; // 0x03:信号良好 + } + else if (csq <= 31) + { + pdata[(*idx)++] = 4; // 0x04:信号强 + } + else if (csq > 31) + { + pdata[(*idx)++] = 0; // 0x00: 无信号 + } + else + { + pdata[(*idx)++] = 0; // 0x00: 无信号 + } +} + +static void protocol_goome_pack_extern_power(U8* pdata, u16 *idx, u16 len) +{ + U8 percent = 0.0; + float voltage = 0.0; + u8 value_u8; + u16 value_u16; + + config_service_get(CFG_BATTUPLOAD_DISABLE, TYPE_BYTE, &value_u8, sizeof(value_u8)); + if(0 == value_u8) + { + hard_ware_get_extern_battery_percent(&percent); + pdata[(*idx)++] = (u8)percent; + + hard_ware_get_power_voltage(&voltage); + value_u16 = (u16)voltage*100; + pdata[(*idx)++] = BHIGH_BYTE(value_u16); + pdata[(*idx)++] = BLOW_BYTE(value_u16); + } + else + { + pdata[(*idx)++] = 0x00; + pdata[(*idx)++] = 0x00; + pdata[(*idx)++] = 0x00; + } +} + +static void protocol_goome_pack_gps_signal_quality(U8* pdata, u16 *idx, u16 len) +{ + GPSData gps; + GM_memset(&gps,0,sizeof(gps)); + gps_get_last_data(&gps); + pdata[(*idx)++] = gps.signal_intensity_grade; +} + + +//6767 07 000B 0003 02EE 043700000F0000 +static void protocol_goome_pack_status(U8* pdata, u16 *idx, u16 len) +{ + u16 data = 0; + u8 value_u8; + bool acc_on; + ConfigHearUploadEnum heart_mode; + + if((*idx) + 2 > len) + { + LOG(WARN,"clock(%d) protocol_goome_pack_status assert(len(%d)) failed.", util_clock(), len); + return; + } + + if (gps_is_fixed()) + { + SET_BIT0(data); + } + + if (GM_SUCCESS == hard_ware_get_acc_level(&acc_on)) + { + if(acc_on) + { + SET_BIT1(data); + SET_BIT2(data); + } + else + { + SET_BIT1(data); + } + } + + config_service_get(CFG_IS_MANUAL_DEFENCE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if(value_u8) + { + SET_BIT3(data); + SET_BIT4(data); + } + else + { + SET_BIT3(data); + } + + config_service_get(CFG_IS_RELAY_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + if(value_u8) + { + if (system_state_get_device_relay_state()) + { + //油电断开 + SET_BIT5(data); + } + else + { + SET_BIT5(data); + SET_BIT6(data); + } + } + //else 无断油电功能 + + if(system_state_get_has_started_charge()) + { + SET_BIT7(data); + SET_BIT8(data); + } + else + { + SET_BIT7(data); + } + + switch( system_state_get_vehicle_state()) + { + case VEHICLE_STATE_RUN: + SET_BIT9(data); + SET_BIT10(data); + break; + case VEHICLE_STATE_STATIC: + SET_BIT9(data); + break; + default: + SET_BIT10(data); + break; + } + + pdata[(*idx)++] = BHIGH_BYTE(data); + pdata[(*idx)++] = BLOW_BYTE(data); + + + heart_mode = config_service_get_heartbeat_protocol(); + if (HEART_EXPAND == heart_mode) + { + protocol_goome_pack_csq(pdata, idx, len); //1byte + protocol_goome_pack_power_voltage(pdata, idx, len); //1byte + protocol_goome_pack_extern_power(pdata, idx, len); //3bytes + pdata[(*idx)++] = g_sensor_get_angle(); + protocol_goome_pack_gps_signal_quality(pdata, idx, len); + + //上电时间大于配置时间则不显示 + config_service_get(CFG_SEN_ANGLE_SHOW_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + if(system_state_get_start_time() > value_u8*SECONDS_PER_MIN || 0xFF == value_u8) + { + //APP不显示姿态,注意0是显示,1是不显示 + pdata[(*idx)++] = 1; + } + else + { + + //APP显示姿态,注意0是显示,1是不显示 + pdata[(*idx)++] = 0; + } + } +} + + +static void protocol_goome_pack_gps(const GPSData *gps, U8* pdata, u16 *idx, u16 len) +{ + u32 curtime = 0; + u32 latitudev = 0; + u32 longitudev = 0; + u16 gps_speed = 0; + u16 gps_angle = 0; + + if((*idx) + 15 > len) + { + LOG(WARN,"clock(%d) protocol_goome_pack_gps assert(len(%d)) failed.", util_clock(), len); + return; + } + + if (!gps_is_fixed()) + { + curtime = util_get_utc_time(); + } + else + { + curtime = gps->gps_time; + } + + // 占用4个字节 ,即卫星时间的UTC秒数 + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(curtime)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(curtime)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(curtime)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(curtime)); + + // 纬度 + if(gps->gps_time == 0) + { + s32 tmpval = agps_service_get_unfix_lat() * 1800000.0f; + latitudev = (u32)tmpval; + } + else + { + // latitudev = (u32)(gps->lat * 1800000.0f); latitudev会得到0 + s32 tmpval = gps->lat * 1800000.0f; + latitudev = (u32)tmpval; + } + + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(latitudev)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(latitudev)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(latitudev)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(latitudev)); + + // 经度 + if(gps->gps_time == 0) + { + s32 tmpval = agps_service_get_unfix_lng() * 1800000.0f; + longitudev = (u32)tmpval; + } + else + { + s32 tmpval = gps->lng*1800000.0f; + longitudev = (u32)tmpval; + } + + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(longitudev)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(longitudev)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(longitudev)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(longitudev)); + + + // 速度 + gps_speed = gps->speed; + if (gps_speed > 180) + { + gps_speed = 180; + } + pdata[(*idx)++] = (u8)gps_speed; + + // 角度 + gps_angle = (u16)gps->course; + if (gps_angle >= 360) + { + gps_angle = 0; + } + + pdata[(*idx)++] = BHIGH_BYTE(gps_angle); + pdata[(*idx)++] = BLOW_BYTE(gps_angle); +} + + + +static void protocol_goome_pack_lbs(U8* pdata, u16 *idx, u16 len) +{ + gm_cell_info_struct lbs; + GM_ERRCODE ret; + + GM_memset(&lbs,0, sizeof(lbs)); + + if((*idx) + 9 > len) + { + LOG(WARN,"clock(%d) protocol_goome_pack_lbs assert(len(%d)) failed.", util_clock(), len); + return; + } + + ret = gsm_get_cell_info(&lbs); + LOG(DEBUG,"clock(%d) protocol_goome_pack_lbs ret(%d) lbs(%d).", util_clock(), ret, lbs.nbr_cell_num); + + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.mcc); // MCC 2 + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.mcc); + + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.mnc); // MNC 2 + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.mnc); + + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.lac); // LAC 2 + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.lac); + + + pdata[(*idx)++] = 0x00; //CI 3 + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.ci); + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.ci); + +} + + +void protocol_goome_pack_login_msg(U8* pdata, u16 *idx, u16 len) +{ + protocol_goome_pack_head(pdata, idx, len); //7 bytes + + protocol_goome_pack_imei(pdata, idx, len); //8bytes + + protocol_goome_pack_language(pdata, idx, len); //1bytes + + protocol_goome_pack_id_len(pdata, PROTOCCOL_GOOME_LOGIN, *idx); +} + + + +void protocol_goome_pack_heartbeat_msg(U8* pdata, u16 *idx, u16 len) +{ + protocol_goome_pack_head(pdata, idx, len); //7 bytes + + protocol_goome_pack_status(pdata, idx, len); // 2|10 bytes + + if(HEART_NORMAL == config_service_get_heartbeat_protocol()) + { + protocol_goome_pack_id_len(pdata, PROTOCCOL_GOOME_HEART, *idx); + } + else + { + protocol_goome_pack_id_len(pdata, PROTOCCOL_GOOME_HEART_EXPAND, *idx); + } +} + +static void protocol_goome_pack_locate_status(U8* pdata, u16 *idx, u16 len) +{ + bool acc_on = false; + + if (gps_is_fixed()) + { + SET_BIT0(pdata[(*idx)]); + } + else + { + CLR_BIT0(pdata[(*idx)]); + } + + if (GM_SUCCESS == hard_ware_get_acc_level(&acc_on) && acc_on) + { + SET_BIT1(pdata[(*idx)]); + } + else + { + CLR_BIT1(pdata[(*idx)]); + } + + (*idx)++; +} + + +void protocol_goome_pack_gps_msg(GpsDataModeEnum mode, const GPSData *gps, U8* pdata, u16 *idx, u16 len) +{ + protocol_goome_pack_head(pdata, idx, len); //7 bytes + protocol_goome_pack_gps(gps, pdata, idx, len); //15 bytes + protocol_goome_pack_lbs(pdata, idx, len); //9 bytes + protocol_goome_pack_locate_status(pdata, idx, len); //1 bytes + + protocol_goome_pack_id_len(pdata, PROTOCCOL_GOOME_LOCAT, *idx); +} + + +static void protocol_goome_pack_lbses(U8* pdata, u16 *idx, u16 len) +{ + gm_cell_info_struct lbs; + u32 cur_time; + u16 k = 0; + u16 num=0; + u16 lbsidx=0; + GM_ERRCODE ret; + + GM_memset(&lbs,0, sizeof(lbs)); + + if((*idx) + 39 > len) + { + LOG(WARN,"clock(%d) protocol_goome_pack_lbses assert(len(%d)) failed.", util_clock(), len); + return; + } + + ret = gsm_get_cell_info(&lbs); + LOG(DEBUG,"clock(%d) protocol_goome_pack_lbses ret(%d) lbs(%d).", util_clock(), ret, lbs.nbr_cell_num); + + //日期时间 + cur_time = util_get_utc_time(); + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(cur_time)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(cur_time)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(cur_time)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(cur_time)); + + if (lbs.nbr_cell_num > 4) + { + num = 4; + } + else + { + num = lbs.nbr_cell_num; + } + + // TA(1B) + MCC(2B) + MNC(1B) + 基站数(1B) + pdata[(*idx)++] = 0xFF; + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.mcc); // MCC + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.mcc); + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.mnc); // MNC + pdata[(*idx)++] = num+1; // 基站数 + + + // 主服务基站信息 LAC(2B)+CI(3B)+RSSI(1B) + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.lac); // LAC + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.lac); + pdata[(*idx)++] = 0x00; // CELL ID + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.ci); // CELL ID + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.ci); + pdata[(*idx)++] = lbs.serv_info.rxlev;// 信号强度 RSSI + + + // 剩余4个基站 LAC(2B)+CI(3B)+RSSI(1B) + lbsidx = (*idx); + GM_memset(&pdata[lbsidx], 0, 24); + for (k=0; k len) + { + LOG(WARN,"clock(%d) protocol_goome_pack_alarm assert(len(%d)) failed.", util_clock(), len); + return; + } + + pdata[(*idx)++] = alarm->type; + pdata[(*idx)++] = BHIGH_BYTE(alarm->info); + pdata[(*idx)++] = BLOW_BYTE(alarm->info); +} + +void protocol_goome_pack_alarm_msg(AlarmInfo *alarm,U8* pdata, u16 *idx, u16 len) +{ + GPSData gps; + GM_memset(&gps,0,sizeof(gps)); + + gps_get_last_data(&gps); + if(gps.gps_time == 0) + { + system_state_get_last_gps(&gps); + } + + protocol_goome_pack_head(pdata, idx, len); //7 bytes + protocol_goome_pack_gps(&gps, pdata, idx, len); //15 bytes + protocol_goome_pack_lbs(pdata, idx, len); //9 bytes + protocol_goome_pack_locate_status(pdata, idx, len); //1 bytes + protocol_goome_pack_alarm(alarm, pdata, idx, len); //3 bytes + + protocol_goome_pack_id_len(pdata, PROTOCCOL_GOOME_ALARM, *idx); + return; +} + + +static void protocol_goome_parse_login_response(U8* pdata, u16 len) +{ + if(len != 7) + { + LOG(WARN,"clock(%d) protocol_goome_parse_login_response assert(len(%d) != 7) failed.", util_clock(), len); + return; + } + + //发送iccid + gps_service_after_login_response(); + + return; +} + + + +void protocol_goome_parse_msg(U8* pdata, u16 len) +{ + if(PROTOCOL_HEADER_GOOME != pdata[0] || PROTOCOL_HEADER_GOOME != pdata[1]) + { + LOG(WARN,"clock(%d) protocol_goome_parse_msg assert(head(%02x %02x)) failed.", util_clock(), pdata[0],pdata[1]); + return; + } + + //协议号 + switch(pdata[2]) + { + case PROTOCCOL_GOOME_LOGIN: + LOG(DEBUG,"clock(%d) protocol_goome_parse_msg(PROTOCCOL_GOOME_LOGIN).", util_clock()); + protocol_goome_parse_login_response(pdata,len); + break; + case PROTOCCOL_GOOME_ICCID_MSG: + LOG(DEBUG,"clock(%d) protocol_goome_parse_msg(PROTOCCOL_GOOME_ICCID_MSG).", util_clock()); + break; + case PROTOCCOL_GOOME_HEART: + LOG(DEBUG,"clock(%d) protocol_goome_parse_msg(PROTOCCOL_GOOME_HEART).", util_clock()); + gps_service_after_receive_heartbeat(); + break; + case PROTOCCOL_GOOME_HEART_EXPAND: + LOG(DEBUG,"clock(%d) protocol_goome_parse_msg(PROTOCCOL_GOOME_HEART_EXPAND).", util_clock()); + gps_service_after_receive_heartbeat(); + break; + case PROTOCCOL_GOOME_LOCAT: //定位也相当于有心跳 + LOG(DEBUG,"clock(%d) protocol_goome_parse_msg(PROTOCCOL_GOOME_LOCAT).", util_clock()); + gps_service_after_receive_heartbeat(); + break; + case PROTOCCOL_GOOME_ALARM: + LOG(DEBUG,"clock(%d) protocol_goome_parse_msg(PROTOCCOL_GOOME_ALARM).", util_clock()); + protocol_goome_alarm_ask(pdata, len); + break; + case PROTOCCOL_GOOME_SMS_MSG: + LOG(DEBUG,"clock(%d) protocol_goome_parse_msg(PROTOCCOL_GOOME_SMS_MSG).", util_clock()); + protocol_goome_sms_ask(&pdata[7], len-7); + break; + case PROTOCCOL_GOOME_REMOTE_MSG: + LOG(DEBUG,"clock(%d) protocol_goome_parse_msg(PROTOCCOL_GOOME_REMOTE_MSG).", util_clock()); + protocol_goome_parse_remote_msg(pdata, len); + break; + case PROTOCCOL_GOOME_GENERAL_MSG: + LOG(DEBUG,"clock(%d) protocol_goome_parse_msg(PROTOCCOL_GOOME_GENERAL_MSG).", util_clock()); + break; + default: + LOG(WARN,"clock(%d) protocol_goome_parse_msg assert(msgid(%d)) failed.", util_clock(), pdata[2]); + break; + } + return; +} + + +void protocol_goome_pack_iccid_msg(U8* pdata, u16 *idx, u16 len) +{ + protocol_goome_pack_head(pdata, idx, len); //7 bytes + + protocol_goome_pack_iccid(pdata, idx, len); //10bytes + + protocol_goome_pack_id_len(pdata, PROTOCCOL_GOOME_ICCID_MSG, *idx); +} + + +void protocol_goome_alarm_ask(U8* pdata, u16 len) +{ + U8* recv_msg = NULL; + u16 *recv_msg_w = NULL; + u8 number[24]; + u16 number_len = 0; + u16 index; + u16 msg_len = 0; + + if(len <=7) + { + LOG(DEBUG,"clock(%d) protocol_goome_alarm_ask msglen(%d).", util_clock(), len); + return; + } + + recv_msg = GM_MemoryAlloc(CMD_MAX_LEN+1); + if (recv_msg == NULL) + { + LOG(WARN,"clock(%d) protocol_goome_alarm_ask assert(GM_MemoryAlloc(%d)) failed.", util_clock(), CMD_MAX_LEN+1); + return; + } + recv_msg_w = GM_MemoryAlloc(CMD_MAX_LEN/2+1); + if (recv_msg_w == NULL) + { + GM_MemoryFree(recv_msg); + LOG(WARN,"clock(%d) protocol_goome_alarm_ask assert(GM_MemoryAlloc(%d)) failed.", util_clock(), CMD_MAX_LEN/2+1); + return; + } + + GM_memset(recv_msg, 0x00, CMD_MAX_LEN+1); + GM_memset(recv_msg_w, 0x00, CMD_MAX_LEN/2+1); + + //把UTF-8转成UNICODE + index = util_utf8_to_unicode(&pdata[7], len-7, recv_msg_w, CMD_MAX_LEN/2); + + //把双字节的UNICODE转成单字节的UNICODE + msg_len = util_ucs2_u16_to_u8(recv_msg_w, index,recv_msg ); + + for (index=0; index<=3; index++) + { + number_len = config_service_get_sos_number(index, number, sizeof(number)); + number[number_len] = 0; + if (number_len > 0) + { + sms_send((char*)recv_msg, msg_len, (char*)number, GM_UCS2_DCS); + } + + if (config_service_is_alarm_sms_to_one()) + { + break; //只发第一个号 + } + } + + GM_MemoryFree(recv_msg); + GM_MemoryFree(recv_msg_w); + +} + + +/* +设备接收到123短信,上发到服务器, 收到时间经纬度和短信内容后, 通过短信发给源发送方 +676706 0033 0026 57E4DFC7 026DDEC0 0C3BFEF0 000154 01CC0000262C000EBA 01 313036343839393038303031380000000000000000 313233 SMS指令数据 + +6767 +06 +0081 +6FBE +000000000000000031303634383939313932363435 +E4BD8DE7BDAE3AE5B9BFE4B89CE79C812EE6B7B1E59CB3E5B8822EE58D97E5B1B1E58CBA2EE7A791E68A80E58D97E58D81E4BA8CE8B7AF2EE7A6BBE4B8ADE59BBDE993B6E8A18C28E7A791E68A80E58D97E694AFE8A18C2928E8A5BFE58C9729E7BAA6313330E7B1B32E +平台下发位置: +设备把下发内容转给短信发送者 +*/ +void protocol_goome_sms_ask(U8* pdata, u16 len) +{ + U8* recv_msg = NULL; + u16 *recv_msg_w = NULL; + u8 number[24]; + u16 number_len = 0; + u16 index; + + if(len < 21) + { + LOG(DEBUG,"clock(%d) protocol_goome_sms_ask msglen(%d).", util_clock(), len); + return; + } + + GM_strncpy((char *)number, (const char *)pdata, 21); + number[20] = 0; + number_len = GM_strlen((const char *)number); + if(number_len == 0) + { + LOG(INFO,"clock(%d) protocol_goome_sms_ask number_len(%d).", util_clock(), number_len); + return; + } + + recv_msg = GM_MemoryAlloc(CMD_MAX_LEN+1); + if (recv_msg == NULL) + { + LOG(WARN,"clock(%d) protocol_goome_sms_ask assert(GM_MemoryAlloc(%d)) failed.", util_clock(), CMD_MAX_LEN+1); + return; + } + recv_msg_w = GM_MemoryAlloc(CMD_MAX_LEN/2+1); + if (recv_msg_w == NULL) + { + GM_MemoryFree(recv_msg); + LOG(WARN,"clock(%d) protocol_goome_sms_ask assert(GM_MemoryAlloc(%d)) failed.", util_clock(), CMD_MAX_LEN/2+1); + return; + } + + GM_memset(recv_msg, 0x00, CMD_MAX_LEN+1); + GM_memset(recv_msg_w, 0x00, CMD_MAX_LEN/2+1); + + //把UTF-8转成UNICODE + index = util_utf8_to_unicode(&pdata[21], len-21, recv_msg_w, CMD_MAX_LEN/2); + + //把双字节的UNICODE 字节序转换 + index = util_ucs2_u16_to_u8(recv_msg_w, index, recv_msg); + + LOG(DEBUG,"clock(%d) protocol_goome_sms_ask send sms to(%s)) len(%d).", util_clock(), number, index); + sms_send((char*)recv_msg, index, (char*)number, GM_UCS2_DCS); + + GM_MemoryFree(recv_msg); + GM_MemoryFree(recv_msg_w); +} + + +//信息头(67 67) + 协议号(1B) + 包长度(2B) + 序列号(2B) + 内容(NB) +//6767 80 000D FFFF 01 00736F69 574845524523 +//6767 80 000D FFFF 01 00736FD5 574845524523 +// 1B:信息标示 0x01:指令 0x02:互动指令 +// 4B:服务器标示 +static void protocol_goome_parse_remote_msg(U8* pdata, u16 len) +{ + U8* pOut = NULL; + u16 out_len = 0; + u8 idx = 0; + u16 index = 0; + u16 msg_len = 0; + + idx = 7; + s_msg_save.msg_flag = pdata[idx++]; // 信息标识 + GM_memcpy(s_msg_save.server_id, &pdata[idx], sizeof(s_msg_save.server_id)); // 服务器标志 + idx += 4; + msg_len = len - idx; + + pOut = GM_MemoryAlloc(CMD_MAX_LEN + 1); + if (NULL == pOut) + { + LOG(WARN,"clock(%d) protocol_goome_parse_remote_msg assert(GM_MemoryAlloc(%d)) failed.", util_clock(), CMD_MAX_LEN + 1); + return; + } + + GM_memset(pOut, 0x00, CMD_MAX_LEN + 1); + + for (index=0; index< msg_len; index++) + { + if ((',' == pdata[idx+index]) || ('#' == pdata[idx+index]) || ('*' == pdata[idx+index])) + { + break; + } + } + //LOG(INFO,"Receive server command:%s",&pdata[idx]); + command_on_receive_data(COMMAND_GPRS, (char *)&pdata[idx], msg_len, (char *)pOut,NULL); + out_len = GM_strlen((char *)pOut); + if (out_len > 0) + { + gps_service_after_receive_remote_msg(pOut, out_len); + } + + GM_MemoryFree(pOut); + return; +} + + +void protocol_goome_pack_remote_ack(U8* pdata, u16 *idx, u16 len, U8* pRet, u16 retlen) +{ + protocol_goome_pack_head(pdata, idx, len); //7 bytes + pdata[(*idx)++] = s_msg_save.msg_flag; + GM_memcpy(&pdata[(*idx)], s_msg_save.server_id, sizeof(s_msg_save.server_id)); + (*idx) += sizeof(s_msg_save.server_id); + GM_memcpy(&pdata[(*idx)], pRet, retlen); + (*idx) += retlen; + protocol_goome_pack_id_len(pdata, PROTOCCOL_GOOME_REMOTE_MSG, *idx); +} + + +void protocol_goome_pack_position_request_msg(u8 *mobile_num, u8 num_len, u8 *command, u8 cmd_len,u8 *pdata, u16 *idx, u16 len) +{ + GPSData gps; + GM_memset(&gps,0,sizeof(gps)); + + gps_get_last_data(&gps); + if(gps.gps_time == 0) + { + system_state_get_last_gps(&gps); + } + + protocol_goome_pack_head(pdata, idx, len); //7 bytes + protocol_goome_pack_gps(&gps, pdata, idx, len); //15 bytes + protocol_goome_pack_lbs(pdata, idx, len); //9 bytes + protocol_goome_pack_locate_status(pdata, idx, len); //1 bytes + GM_memset(&pdata[(*idx)],0,21); + num_len = num_len < 21?num_len:20; + GM_memcpy(&pdata[(*idx)],mobile_num,num_len); + (*idx)+=21; //21 bytes + GM_memcpy(&pdata[(*idx)],command,cmd_len); + (*idx) += cmd_len; + protocol_goome_pack_id_len(pdata, PROTOCCOL_GOOME_SMS_MSG, *idx); +} + diff --git a/src/protocol_jt808.c b/src/protocol_jt808.c new file mode 100644 index 0000000..c37e5a9 --- /dev/null +++ b/src/protocol_jt808.c @@ -0,0 +1,1845 @@ +#include +#include "utility.h" +#include "gm_stdlib.h" +#include "gm_memory.h" +#include "gm_type.h" +#include "gsm.h" +#include "log_service.h" +#include "config_service.h" +#include "hard_ware.h" +#include "protocol.h" +#include "gps.h" +#include "protocol_jt808.h" +#include "gps_service.h" +#include "sms.h" +#include "system_state.h" +#include "hard_ware.h" +#include "command.h" +#include "agps_service.h" + +#define JT_DATA_DEPART_FLAG 0x2000 //分包标志 0010 0000 0000 0000 +#define JT_DATA_SEC_FLAG 0x1C00 //加密标志 0001 1100 0000 0000 + +typedef enum +{ + AT_TYPE_STANDARD = 0, //标准 + AT_TYPE_CUSTOM = 1 //补充 +} Jt08AtTypeEnum; + +typedef enum +{ + JT_CMD_TERM_ACK = 0x0001, //终端通用应答 + JT_CMD_HEART_BEAT = 0x0002, //终端心跳 + JT_CMD_UNREGISTER = 0x0003, //注销 + JT_CMD_PLAT_ACK = 0x8001, //平台通用应答 + JT_CMD_REGISTER = 0x0100, //终端注册 + JT_CMD_REGISTER_ACK = 0x8100, //终端注册应答 + JT_CMD_ICCID = 0x0120, //终端上报iccid + JT_CMD_AUTH = 0x0102, //终端鉴权 + JT_CMD_SET_PARAM = 0x8103, //设置终端参数 + JT_CMD_GET_PARAM = 0x8104, //查询终端参数 + JT_CMD_TERM_CTL = 0x8105, //终端控制 + JT_CMD_GET_PARAM_ACK = 0x0104, //查询终端参数应答 + JT_CMD_LOCATE = 0x0200, //位置信息汇报 + JT_CMD_LOCATE_REQ = 0x8201, //位置信息查询 + JT_CMD_LOCATE_REQ_ACK = 0x0201, //位置信息查询应答 + JT_CMD_LOCATE_MULTI = 0x704, //定位数据批量上传 + JT_CMD_TEXT_RESULT = 0x6006, // 终端文本数据上报 + JT_CMD_CONFIRM_ALARM = 0x8203, //确认紧急报警 + JT_CMD_TEXT = 0x8300 //文本信息下发 +}Jt08CmdType; + +typedef enum +{ + JT_PARAM_HEART_INTERVAL = 0x0001, //终端心跳发送间隔,单位为(s) + JT_PARAM_APN = 0x0010, //主服务器 APN,无线通信拨号访问点。 + JT_PARAM_APN_USR = 0x0011, //主服务器 APN 拨号用户名 + JT_PARAM_APN_PWD = 0x0012, //主服务器 APN,拨号密码 + JT_PARAM_IP = 0x0013, //主服务器地址,IP 或域名 + JT_PARAM_IP_BAK = 0x0017, //备份服务器地址,IP 或域名 + JT_PARAM_PORT = 0x0018, //服务器 TCP 端口 + JT_PARAM_LOCATE_TYPE = 0x0020, //位置汇报策略,0:定时汇报;1:定距汇报;2:定时和定距汇报 + JT_PARAM_HEART_LOCATE_INTERVAL = 0x0027, //休眠时汇报时间间隔,单位为秒(s),>0 + JT_PARAM_TIME_INTERVAL = 0x0029, //缺省时间汇报间隔,单位为秒(s),>0 + JT_PARAM_DISTANCE_INTERVAL = 0x002C, //缺省距离汇报间隔,单位为米(m),>0 + JT_PARAM_TURN_ANGLE = 0x0030, //拐点补传角度,<180 + JT_PARAM_MAX_SPEED = 0x0055, //最高速度,单位为千米每小时(km/h) + JT_PARAM_EXCEED_SPEED_TIME = 0x0056, //超速持续时间,单位为秒(s) + JT_PARAM_MILIAGE = 0x0080, //车辆里程表读数,1/10km + JT_PARAM_PROVINCE = 0x0081, //车辆所在的省域 ID,1~255 + JT_PARAM_CITY = 0x0082, //车辆所在的市域 ID,1~255 + JT_PARAM_BRAND = 0x0083, //公安交通同管理部门颁发的机劢车号牌 + JT_PARAM_BRAND_COLOR = 0x0084, //车牌颜色,按照 JT/T415—2006 中 5.4.12 的规定 +}Jt08ParamType; + + +/*用于记录发送消息的序列号, 收到消息的序列号等*/ +typedef struct +{ + u16 msg_serial; //上传数据序列号, 每次发消息加一 + bool last_gps_ok; //上一次的gps有数据 + GPSData last_gps; //上一次的gps + + u16 server_serial; //数据序列号 + u16 msg_id; // 消息号 + u8 msg_result; // 消息号0:成功/确认;1:失败;2:消息有误;3:不支持; 4:报警处理确认 +}Jt08MsgSave; + +static Jt08MsgSave s_jt_msg_save = {0, 0, }; + +static void protocol_jt_pack_escape(u8 *src, u16 src_len, u8 *dest, u16 *dest_len); +static GM_ERRCODE protocol_jt_pack_unescape(u8 *src, u16 *src_len); +static void protocol_jt_pack_head(u8 *pdata, u16 *idx, u16 len, u16 total, u16 part_num ); +static void protocol_jt_pack_id_len(u8 *pdata, u16 *idx, u16 cmd, u16 len, u8 sec, bool depart); + +static void protocol_jt_pack_register_info(u8 *pdata, u16 *idx, u16 len, u16 *return_len); +static void protocol_jt_pack_auth_code(u8 *pdata, u16 *idx, u16 len, u16 *return_len); +static void protocol_jt_pack_iccid(u8 *pdata, u16 *idx, u16 len, u16 *return_len); +static void protocol_jt_pack_gps_info(GpsDataModeEnum mode, const GPSData *gps, u8 *pdata, u16 *idx, u16 len, u16 *return_len); +static void protocol_jt_parse_general_msg(U8* pdata, u16 len); +static void protocol_jt_pack_additional_mileage(u8 *pdata, u16 *idx, u16 len, u16 *return_len); +static void protocol_jt_pack_device_status(u8 *pdata, u16 *idx, u16 len, u16 *return_len,GPSData* p_data); +static void protocol_jt_pack_alarm_status(u8 *pdata, u16 *idx, u16 len, u16 *return_len); +static void protocol_jt_pack_additional_lbs(u8 *pdata, u16 *idx, u16 len, u16 *return_len); +static void protocol_jt_pack_server_info(u8 *pdata, u16 *idx, u16 len, u16 *return_len); +static void protocol_jt_pack_param_info(u8 *pdata, u16 *idx, u16 len, u16 *return_len); +static void protocol_jt_pack_item_num(u8 *pdata, u16 *idx, u32 item, u32 value, u8 item_len); +static void protocol_jt_pack_item_string(u8 *pdata, u16 *idx, u32 item, u8 *pitem, u8 item_len); + + +static void protocol_jt_parse_text(U8* pdata, u16 len); +static void protocol_jt_parse_gps_req(U8* pdata, u16 len); +static void protocol_jt_parse_terminal_control(U8* pdata, u16 len); +static void protocol_jt_parse_get_param(U8* pdata, u16 len); +static void protocol_jt_parse_set_param(U8* pdata, u16 len); +static void protocol_jt_parse_register_ack(U8* pdata, u16 len); +static void protocol_jt_parse_plat_ack(U8* pdata, u16 len); +static u32 get_value_by_length(u8 *p,u8 l); + +static u32 get_value_by_length(u8 *p,u8 l) +{ + if(l==4) + { + return( ((u32)p[0]<<24)+((u32)p[1]<<16)+((u16)p[2]<<8)+p[3]); + } + else if(l==3) + { + return(((u32)p[0]<<16)+((u16)p[1]<<8)+p[2]); + } + else if(l==2) + { + return(((u16)p[0]<<8)+p[1]); + } + else + { + return(p[0]); + } +} + + +static void protocol_jt_pack_escape(u8 *src, u16 src_len, u8 *dest, u16 *dest_len) +{ + u16 i = 0, j = 0; + + //首字节是 PROTOCOL_HEADER_JT808 + if((*dest_len) < j + 1) + { + LOG(INFO,"clock(%d) protocol_jt_pack_escape assert(dest_len(%d) >= %d) failed.", util_clock(), *dest_len, j + 1); + return; + } + dest[j] = src[i]; + j++; + + // 最后一个字节也是 PROTOCOL_HEADER_JT808 + for(i = 1; i= %d) failed.", util_clock(), *dest_len, j + 2); + return; + } + + dest[j++] = PROTOCOL_HEADER_ESCAPE; + dest[j++] = 0x02; + } + else if(src[i] == PROTOCOL_HEADER_ESCAPE) + { + if((*dest_len) < j + 2) + { + LOG(INFO,"clock(%d) protocol_jt_pack_escape assert(dest_len(%d) >= %d) failed.", util_clock(), *dest_len, j + 2); + return; + } + + dest[j++] = PROTOCOL_HEADER_ESCAPE; + dest[j++] = 0x01; + } + else + { + if((*dest_len) < j + 1) + { + LOG(INFO,"clock(%d) protocol_jt_pack_escape assert(dest_len(%d) >= %d) failed.", util_clock(), *dest_len, j + 1); + return; + } + + dest[j++] = src[i]; + } + } + + dest[j++] = src[i++]; //last byte 0x7e + (*dest_len) = j; +} + + + +static GM_ERRCODE protocol_jt_pack_unescape(u8 *src, u16 *src_len) +{ + u16 i = 0, j = 0; + + //首,尾字节是0x7e + + //其余字节 + for(i = 1,j=1; i< (*src_len - 1); ++i,++j) + { + if(src[i] == PROTOCOL_HEADER_ESCAPE) + { + if(src[i + 1] == 0x01) + { + src[j] = PROTOCOL_HEADER_ESCAPE; + i++; + } + else if(src[i + 1] == 0x02) + { + src[j] = PROTOCOL_HEADER_JT808; + i++; + } + else + { + LOG(INFO,"clock(%d) protocol_jt_pack_unescape assert(%02x after 0x7d) failed.", util_clock(), src[i + 1]); + return GM_PARAM_ERROR; + } + } + else + { + if(i != j) + { + src[j] = src[i]; + } + } + } + src[j++] = src[i++]; //last byte 0x7e + (*src_len) = j; + return GM_SUCCESS; +} + +static void protocol_jt_pack_head(u8 *pdata, u16 *idx, u16 len, u16 total, u16 part_num ) +{ + GM_ERRCODE ret = GM_SUCCESS; + u8 imei[GM_IMEI_LEN + 1] = {0}; + u8 app_ver; + + if((*idx) + 13 > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_head assert(len(%d)) failed.", util_clock(), len); + return; + } + + pdata[(*idx)++]=PROTOCOL_HEADER_JT808; // 1 bytes + (*idx) += 4; //id 2 len 2 total 4 bytes + + if(GM_SUCCESS != (ret = gsm_get_imei(imei))) + { + LOG(INFO,"clock(%d) protocol_jt_pack_head can not get imei, ret:%d.", util_clock(), ret); + } + + if (0 == GM_strlen((const char *)imei)) + { + GM_memset(imei, 0, sizeof(imei)); + } + + + config_service_get(CFG_PROTOCOL_VER, TYPE_BYTE, &app_ver, sizeof(app_ver)); + //四川移动 取imei号 3~14位 + if(app_ver == PROTOCOL_VER_CMCC_JT808) + { + pdata[(*idx)++] = MERGEBCD(util_chr(imei[2]), util_chr(imei[3])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[4]), util_chr(imei[5])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[6]), util_chr(imei[7])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[8]), util_chr(imei[9])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[10]), util_chr(imei[11])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[12]), util_chr(imei[13])); + } + else //取imei号后10位, 前面加"1"(0x31) + { + pdata[(*idx)++] = MERGEBCD(0, 0x31); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[5]), util_chr(imei[6])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[7]), util_chr(imei[8])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[9]), util_chr(imei[10])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[11]), util_chr(imei[12])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[13]), util_chr(imei[14])); + } + + // 6 bytes + + + //消息流水号 + ++(s_jt_msg_save.msg_serial); + pdata[(*idx)++] = BHIGH_BYTE(s_jt_msg_save.msg_serial); + pdata[(*idx)++] = BLOW_BYTE(s_jt_msg_save.msg_serial); + // 2 bytes + + if(total > 1) // 此时 protocol_jt_pack_id_len的参数depart值应为true + { + if((*idx) + 4 > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_head assert(len(%d)) failed.", util_clock(), len); + return; + } + + pdata[(*idx)++] = BHIGH_BYTE(total); + pdata[(*idx)++] = BLOW_BYTE(total); + pdata[(*idx)++] = BHIGH_BYTE(part_num); + pdata[(*idx)++] = BLOW_BYTE(part_num); + } +} + +static void protocol_jt_pack_id_len(u8 *pdata, u16 *idx, u16 cmd, u16 len, u8 sec, bool depart) +{ + u8 check_sum=0; + u16 j; + u16 attribute = 0; + + // msg id 2 bytes + pdata[1] = BHIGH_BYTE(cmd); + pdata[2] = BLOW_BYTE(cmd); + + if(depart) + { + depart = 1; + } + else + { + depart = 0; + } + + // len 2 bytes + // 保留(15 14) 分包(13) 加密(12 11 10) 长度(9-0) + attribute = len & 0x3FF + (((u16)depart) << 13) + (((u16)(sec & 0x7)) << 10); + pdata[3] = BHIGH_BYTE(attribute); + pdata[4] = BLOW_BYTE(attribute); + + check_sum = 0; + for (j=1; j<(*idx); j++) + { + check_sum ^= pdata[j]; + } + pdata[(*idx)++] = check_sum; + pdata[(*idx)++] = PROTOCOL_HEADER_JT808; +} + + +static void protocol_jt_pack_register_info(u8 *pdata, u16 *idx, u16 len, u16 *return_len) +{ + u8 value_u8; + u16 value_u16; + u8 at_type; + u8 copy_len; + u16 orginal_idx = *idx; + u8 value_string[20]; + u8 app_ver; + + config_service_get(CFG_JT_AT_TYPE, TYPE_BYTE, &at_type, sizeof(at_type)); + + //省域ID=2byte + config_service_get(CFG_JT_PROVINCE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + pdata[(*idx)++] = BHIGH_BYTE(value_u16); + pdata[(*idx)++] = BLOW_BYTE(value_u16); + + //市域ID=2byte + config_service_get(CFG_JT_CITY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + pdata[(*idx)++] = BHIGH_BYTE(value_u16); + pdata[(*idx)++] = BLOW_BYTE(value_u16); + + //制造商ID=5byte + copy_len = 5; + GM_memset(value_string, 0 , copy_len); + config_service_get(CFG_JT_OEM_ID, TYPE_STRING, value_string, sizeof(value_string)); + GM_memcpy(&pdata[(*idx)], value_string, copy_len); + (*idx) += copy_len; + + //四川移动 终端型号固定用20byte + config_service_get(CFG_PROTOCOL_VER, TYPE_BYTE, &app_ver, sizeof(app_ver)); + //终端型号=8byte + config_service_get(CFG_DEVICETYPE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + if((at_type == AT_TYPE_CUSTOM) || (app_ver == PROTOCOL_VER_CMCC_JT808)) + { + copy_len = 20; + GM_memset(&pdata[(*idx)], 0 , copy_len); + GM_strncpy((char *)&pdata[(*idx)],config_service_get_device_type(value_u16), copy_len); + (*idx) += copy_len; + } + else + { + copy_len = 8; + GM_memset(&pdata[(*idx)], 0 , copy_len); + GM_strncpy((char *)&pdata[(*idx)],config_service_get_device_type(value_u16), copy_len); + (*idx) += copy_len; + } + + + //终端ID=7byte + copy_len = 7; + GM_memset(value_string, 0 , copy_len); + config_service_get(CFG_JT_DEVICE_ID, TYPE_STRING, value_string, sizeof(value_string)); + GM_memcpy(&pdata[(*idx)], value_string, copy_len); + (*idx) += copy_len; + + //车身颜色 + config_service_get(CFG_JT_VEHICLE_COLOR, TYPE_BYTE, &value_u8, sizeof(value_u8)); + pdata[(*idx)++] = value_u8; + + + //车牌号码=nbyte //default 8bytes + config_service_get(CFG_JT_VEHICLE_NUMBER, TYPE_STRING, value_string, sizeof(value_string)); + copy_len = util_remove_char(value_string, GM_strlen((const char *)value_string),' '); + GM_memcpy(&pdata[(*idx)], value_string, copy_len); + (*idx) += copy_len; + + *return_len = (*idx) - orginal_idx; +} + +void protocol_jt_pack_regist_msg(u8 *pdata, u16 *idx, u16 len) +{ + u8 *send; + u16 send_len = 0; + u16 content_len = 0; + send = (u8 *) GM_MemoryAlloc(len); + if (send == NULL) + { + LOG(INFO,"clock(%d) protocol_jt_pack_regist_msg assert(GM_MemoryAlloc(%d)) failed.", util_clock(), len); + return; + } + + + protocol_jt_pack_head(send, &send_len, len, 1, 0); // 13bytes + protocol_jt_pack_register_info(send, &send_len, len, &content_len); // max 57 bytes; default 33 + if((send_len + 2) > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_regist_msg assert(len(%d)) failed.", util_clock(), len); + GM_MemoryFree(send); + return; + } + protocol_jt_pack_id_len(send, &send_len, JT_CMD_REGISTER, content_len, 0, false); // 2bytes + + *idx = len; + protocol_jt_pack_escape(send, send_len, pdata, idx); + + GM_MemoryFree(send); +} + + +static void protocol_jt_pack_auth_code(u8 *pdata, u16 *idx, u16 len, u16 *return_len) +{ + u8 content_len; + u8 auth_code[100]; + + GM_memset(auth_code, 0x00, sizeof(auth_code)); + config_service_get(CFG_JT_AUTH_CODE, TYPE_STRING, &auth_code, sizeof(auth_code)); + + //鉴权码=nbyte + content_len = auth_code[0]; + if (content_len > 100) + { + auth_code[0] = 0; + content_len = 0; + } + + if((*idx) + content_len > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_auth_code assert(len(%d)) failed.", util_clock(), content_len); + return; + } + + GM_memcpy(&pdata[*idx], &auth_code[1], content_len); + (*idx) += content_len; + *return_len = content_len; +} + +void protocol_jt_pack_auth_msg(u8 *pdata, u16 *idx, u16 len) +{ + u8 *send; + u16 send_len = 0; + u16 content_len = 0; + send = (u8 *) GM_MemoryAlloc(len); + if (send == NULL) + { + LOG(INFO,"clock(%d) protocol_jt_pack_auth_msg assert(GM_MemoryAlloc(%d)) failed.", util_clock(), len); + return; + } + + + protocol_jt_pack_head(send, &send_len, len, 1, 0); // 13bytes | 17bytes + protocol_jt_pack_auth_code(send, &send_len, len, &content_len); + if((send_len + 2) > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_auth_msg assert(len(%d)) failed.", util_clock(), len); + GM_MemoryFree(send); + return; + } + protocol_jt_pack_id_len(send, &send_len, JT_CMD_AUTH, content_len, 0, false); // 2bytes + + *idx = len; + protocol_jt_pack_escape(send, send_len, pdata, idx); + + GM_MemoryFree(send); + return; +} + + +static void protocol_jt_pack_iccid(u8 *pdata, u16 *idx, u16 len, u16 *return_len) +{ + GM_ERRCODE ret = GM_SUCCESS; + u8 iccid[GM_ICCID_LEN + 1] = {0}; + u16 content_len = 0; + + if(GM_SUCCESS != (ret = gsm_get_iccid(iccid))) + { + LOG(INFO,"clock(%d) protocol_jt_pack_iccid can not get iccid, ret:%d.", util_clock(), ret); + } + content_len = GM_strlen((const char *)iccid); + if (0 == content_len) + { + GM_memset(iccid, 0, sizeof(iccid)); + } + + if((*idx) + content_len > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_iccid assert(len(%d)) failed.", util_clock(), content_len); + return; + } + + GM_memcpy(&pdata[*idx], &iccid[0], content_len); + (*idx) += content_len; + *return_len = content_len; +} + + + +void protocol_jt_pack_iccid_msg(u8 *pdata, u16 *idx, u16 len) +{ + u8 *send; + u16 send_len = 0; + u16 content_len = 0; + send = (u8 *) GM_MemoryAlloc(len); + if (send == NULL) + { + LOG(INFO,"clock(%d) protocol_jt_pack_iccid_msg assert(GM_MemoryAlloc(%d)) failed.", util_clock(), len); + return; + } + + + protocol_jt_pack_head(send, &send_len, len, 1, 0); // 13bytes | 17bytes + protocol_jt_pack_iccid(send, &send_len, len, &content_len); //20 bytes + if((send_len + 2) > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_iccid_msg assert(len(%d)) failed.", util_clock(), len); + GM_MemoryFree(send); + return; + } + protocol_jt_pack_id_len(send, &send_len, JT_CMD_ICCID, content_len, 0, false); // 2bytes + *idx = len; + protocol_jt_pack_escape(send, send_len, pdata, idx); + + GM_MemoryFree(send); + return; +} + + + +void protocol_jt_pack_logout_msg(u8 *pdata, u16 *idx, u16 len) +{ + u8 *send; + u16 send_len = 0; + u16 content_len = 0; + send = (u8 *) GM_MemoryAlloc(len); + if (send == NULL) + { + LOG(INFO,"clock(%d) protocol_jt_pack_logout_msg assert(GM_MemoryAlloc(%d)) failed.", util_clock(), len); + return; + } + + + protocol_jt_pack_head(send, &send_len, len, 1, 0); // 13bytes | 17bytes + if((send_len + 2) > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_logout_msg assert(len(%d)) failed.", util_clock(), len); + GM_MemoryFree(send); + return; + } + protocol_jt_pack_id_len(send, &send_len, JT_CMD_UNREGISTER, content_len, 0, false); // 2bytes + *idx = len; + protocol_jt_pack_escape(send, send_len, pdata, idx); + + GM_MemoryFree(send); + return; +} + +void protocol_jt_pack_heartbeat_msg(u8 *pdata, u16 *idx, u16 len) +{ + u8 *send; + u16 send_len = 0; + u16 content_len = 0; + send = (u8 *) GM_MemoryAlloc(len); + if (send == NULL) + { + LOG(INFO,"clock(%d) protocol_jt_pack_heartbeat_msg assert(GM_MemoryAlloc(%d)) failed.", util_clock(), len); + return; + } + + + protocol_jt_pack_head(send, &send_len, len, 1, 0); // 13bytes | 17bytes + if((send_len + 2) > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_heartbeat_msg assert(len(%d)) failed.", util_clock(), len); + GM_MemoryFree(send); + return; + } + protocol_jt_pack_id_len(send, &send_len, JT_CMD_HEART_BEAT, content_len, 0, false); // 2bytes + *idx = len; + protocol_jt_pack_escape(send, send_len, pdata, idx); + + GM_MemoryFree(send); + return; +} + + +static void protocol_jt_pack_gps_info(GpsDataModeEnum mode, const GPSData *gps, u8 *pdata, u16 *idx, u16 len, u16 *return_len) +{ + u16 orginal_idx = *idx; + u32 latitudev = 0; + u32 longitudev = 0; + u16 gps_speed = 0; + u16 gps_angle = 0; + u16 gps_hightv = 0; + u8 bcd_tim[6]; + u8 zone; + time_t gps_time; + u8 i; + + latitudev = (gps->lat > 0) ? (gps->lat*1000000) : (gps->lat*(-1)*1000000); + longitudev = (gps->lng > 0) ? (gps->lng*1000000) : (gps->lng*(-1)*1000000); + gps_hightv = (gps->alt >= 8000)? 0:(gps->alt); + gps_speed = ((u16)gps->speed > 180) ? 180 : ((u16)gps->speed); + gps_angle = ((u16)gps->course > 360) ? 0 : ((u16)gps->course); + gps_time = gps->gps_time; + zone = config_service_get_zone(); + util_utc_sec_to_bcdtime_base2000(gps_time, bcd_tim, zone); + + LOG(DEBUG,"clock(%d) protocol_jt_pack_gps_info (%d , %d) gps_time(%d:%d:%d) (%02x-%02x-%02x %02x:%02x:%02x).", util_clock(), + longitudev, latitudev, gps->gps_time, gps_time,util_get_utc_time(), bcd_tim[0],bcd_tim[1],bcd_tim[2],bcd_tim[3],bcd_tim[4],bcd_tim[5]); + + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(latitudev)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(latitudev)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(latitudev)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(latitudev)); + + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(longitudev)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(longitudev)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(longitudev)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(longitudev)); + + pdata[(*idx)++] = BHIGH_BYTE(gps_hightv); + pdata[(*idx)++] = BLOW_BYTE(gps_hightv); + + gps_speed = gps_speed * 10; + pdata[(*idx)++] = BHIGH_BYTE(gps_speed); + pdata[(*idx)++] = BLOW_BYTE(gps_speed); + + pdata[(*idx)++] = BHIGH_BYTE(gps_angle); + pdata[(*idx)++] = BLOW_BYTE(gps_angle); + + for(i = 0; i < sizeof(bcd_tim); ++i) + { + pdata[(*idx)++] = bcd_tim[i]; + } + + *return_len = (*idx) - orginal_idx; +} + + +static void protocol_jt_pack_additional_mileage(u8 *pdata, u16 *idx, u16 len, u16 *return_len) +{ + u32 dwtmp; + + pdata[(*idx)++] = 0x01; + pdata[(*idx)++] = 0x04; + dwtmp = system_state_get_mileage() / 100; //lzTODO 实现里程统计 + + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(dwtmp)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(dwtmp)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(dwtmp)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(dwtmp)); + + *return_len = 6; +} + + +static void protocol_jt_pack_additional_auth_code(u8 *pdata, u16 *idx, u16 len, u16 *return_len) +{ + u8 index; + u16 content_len; + + pdata[(*idx)++] = 0x40; + index = *idx; + pdata[(*idx)++] = 0x00; + + protocol_jt_pack_auth_code(pdata, idx, len, &content_len); + pdata[index] = content_len; + *return_len = content_len + 2; +} + + +static void protocol_jt_pack_additional_imsi(u8 *pdata, u16 *idx, u16 len, u16 *return_len) +{ + GM_ERRCODE ret = GM_SUCCESS; + u8 imsi[GM_IMSI_LEN + 1] = {0}; + u16 content_len = 0; + + if(GM_SUCCESS != (ret = gsm_get_imsi(imsi))) + { + LOG(INFO,"clock(%d) protocol_jt_pack_imsi can not get imsi, ret:%d.", util_clock(), ret); + } + content_len = GM_strlen((const char *)imsi); + if (0 == content_len) + { + GM_memset(imsi, 0, sizeof(imsi)); + } + + if((*idx) + content_len > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_imsi assert(len(%d)) failed.", util_clock(), content_len); + return; + } + + pdata[(*idx)++] = 0x41; + pdata[(*idx)++] = content_len; + GM_memcpy(&pdata[*idx], &imsi[0], content_len); + (*idx) += content_len; + *return_len = content_len + 2; +} + + + +static void protocol_jt_pack_device_status(u8 *pdata, u16 *idx, u16 len, u16 *return_len, GPSData* p_data) +{ + bool value_bool; + u32 device_status = 0; + + if(GM_SUCCESS != hard_ware_get_acc_level(&value_bool)) + { + LOG(WARN,"clock(%d) protocol_jt_pack_device_status assert(hard_ware_get_acc_level) failed.", util_clock()); + } + if (value_bool) + { + SET_BIT0(device_status); + } + + + + if (p_data->gps_time != 0) + { + SET_BIT1(device_status); + } + + // 纬度 负数为南纬 + if (p_data->lat < 0.0f) + { + SET_BIT2(device_status); //南纬 + } + + // 经度 负数为西经 + if (p_data->lng < 0.0f) + { + SET_BIT3(device_status); //西经 + } + + if (system_state_get_device_relay_state()) + { + SET_BIT10(device_status); + } + + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(device_status)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(device_status)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(device_status)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(device_status)); + + *return_len = 4; +} + +static void protocol_jt_pack_alarm_status(u8 *pdata, u16 *idx, u16 len, u16 *return_len) +{ + u32 sys_state; + u32 alarm_state = 0; + + if((*idx) + 4 > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_alarm_status assert(len(%d)) failed.", util_clock(), len); + return; + } + + sys_state = system_state_get_status_bits(); + + + if(sys_state & SYSBIT_ALARM_SPEED) + { + SET_BIT1(alarm_state); + } + + if(sys_state & SYSBIT_ALARM_LOW_POWER) + { + SET_BIT7(alarm_state); + } + + if(sys_state & SYSBIT_ALARM_NO_POWER) + { + SET_BIT8(alarm_state); + } + + if(sys_state & SYSBIT_ALARM_COLLIDE) + { + SET_BIT16(alarm_state); + } + + if(sys_state & SYSBIT_ALARM_SPEED_UP) + { + SET_BIT17(alarm_state); + } + + if(sys_state & SYSBIT_ALARM_TURN_OVER) + { + SET_BIT29(alarm_state); + } + + if(sys_state & SYSBIT_ALARM_SPEED_DOWN) + { + SET_BIT30(alarm_state); + } + + if(sys_state & SYSBIT_ALARM_SHARP_TURN) + { + SET_BIT31(alarm_state); + } + + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(alarm_state)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(alarm_state)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(alarm_state)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(alarm_state)); + *return_len = 4; +} + +void protocol_jt_pack_gps_msg(GpsDataModeEnum mode, const GPSData *gps, u8 *pdata, u16 *idx, u16 len) +{ + u8 *send; + u16 send_len = 0; + u16 content_len = 0; + u16 content_all = 0; + GPSData tmp_gps; + u8 app_ver; + + send = (u8 *) GM_MemoryAlloc(len); + if (send == NULL) + { + LOG(INFO,"clock(%d) protocol_jt_pack_gps_msg assert(GM_MemoryAlloc(%d)) failed.", util_clock(), len); + return; + } + + GM_memcpy(&tmp_gps, gps, sizeof(tmp_gps)); + if(tmp_gps.gps_time == 0) + { + system_state_get_last_gps(&tmp_gps); + } + + if(tmp_gps.gps_time == (time_t)0) + { + tmp_gps.gps_time = util_get_utc_time(); + tmp_gps.lat = agps_service_get_unfix_lat(); + tmp_gps.lng = agps_service_get_unfix_lng(); + } + + protocol_jt_pack_head(send, &send_len, len, 1, 0); // 13bytes | 17bytes + protocol_jt_pack_alarm_status(send, &send_len, len, &content_len); //4 bytes + content_all += content_len; + protocol_jt_pack_device_status(send, &send_len, len, &content_len, &tmp_gps); //4 bytes + content_all += content_len; + protocol_jt_pack_gps_info(mode, &tmp_gps, send, &send_len, len, &content_len); //20 bytes + content_all += content_len; + protocol_jt_pack_additional_mileage(send, &send_len, len, &content_len); //6 bytes + content_all += content_len; + + config_service_get(CFG_PROTOCOL_VER, TYPE_BYTE, &app_ver, sizeof(app_ver)); + //四川移动 固定增加鉴权码及IMSI + if(app_ver == PROTOCOL_VER_CMCC_JT808) + { + protocol_jt_pack_additional_auth_code(send, &send_len, len, &content_len); //max 102byte + content_all += content_len; + protocol_jt_pack_additional_imsi(send, &send_len, len, &content_len); //17byte + content_all += content_len; + } + + if((send_len + 2) > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_gps_msg assert(len(%d)) failed.", util_clock(), len); + GM_MemoryFree(send); + return; + } + protocol_jt_pack_id_len(send, &send_len, JT_CMD_LOCATE, content_all, 0, false); // 2bytes + *idx = len; + protocol_jt_pack_escape(send, send_len, pdata, idx); + + GM_MemoryFree(send); + return; +} + + +static void protocol_jt_pack_additional_lbs(u8 *pdata, u16 *idx, u16 len, u16 *return_len) +{ + u16 orginal_idx = *idx; + u16 k,num=0; + GM_ERRCODE ret; + + gm_cell_info_struct lbs; + GM_memset(&lbs,0, sizeof(lbs)); + + if((*idx) + 9 > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_additional_lbs assert(len(%d)) failed.", util_clock(), len); + return; + } + + ret = gsm_get_cell_info(&lbs); + LOG(DEBUG,"clock(%d) protocol_jt_pack_additional_lbs ret(%d) lbs(%d).", util_clock(), ret, lbs.nbr_cell_num); + + num = (lbs.nbr_cell_num > 5) ? 5: lbs.nbr_cell_num; + pdata[(*idx)++] = 0x53;//基站信息 + pdata[(*idx)++] = 1+8*(num + 1);//数据长度 + pdata[(*idx)++] = (num + 1);//基站个数 + + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.mcc); + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.mcc); + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.mnc); + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.lac); + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.lac); + pdata[(*idx)++] = BHIGH_BYTE(lbs.serv_info.ci); + pdata[(*idx)++] = BLOW_BYTE(lbs.serv_info.ci); + pdata[(*idx)++] = lbs.serv_info.rxlev;// 信号强度 + + GM_memset(&pdata[(*idx)], 0, 40); + for (k=0; k len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_lbs_msg assert(len(%d)) failed.", util_clock(), len); + GM_MemoryFree(send); + return; + } + protocol_jt_pack_id_len(send, &send_len, JT_CMD_LOCATE, content_all, 0, false); // 2bytes + *idx = len; + protocol_jt_pack_escape(send, send_len, pdata, idx); + + GM_MemoryFree(send); + return; +} + +void protocol_jt_pack_gps_msg2(u8 *pdata, u16 *idx, u16 len) +{ + GPSData gps; + + GM_memset(&gps,0,sizeof(gps)); + gps_get_last_data(&gps); + + //use current time. + gps.gps_time = util_get_utc_time(); + + protocol_jt_pack_gps_msg(GPS_MODE_FIX_TIME, &gps, pdata, idx, len); + + return; +} + +void protocol_jt_parse_msg(u8 *pdata, u16 len) +{ + u16 j; + u8 check_sum=0; + u16 cmd; + + //log_service_print_hex((const char *)pdata,len); + if(GM_SUCCESS != protocol_jt_pack_unescape(pdata, &len)) + { + return; + } + + // check_sum 1byte end_tag 1byte + for(j=1;j<(len-2);j++) + { + check_sum ^= pdata[j]; + } + + if(check_sum != pdata[len-2]) + { + LOG(WARN,"clock(%d) protocol_jt_parse_msg assert(checksum(%02x=%02x, %02x, %02x)) failed.", util_clock(), check_sum, pdata[len-3], pdata[len-2], pdata[len-1]); + return; + } + + cmd=((u16)pdata[1]<<8)+pdata[2]; + switch(cmd) + { + case JT_CMD_PLAT_ACK: + LOG(DEBUG,"clock(%d) protocol_jt_parse_msg(JT_CMD_PLAT_ACK).", util_clock()); + protocol_jt_parse_plat_ack(pdata,len); + break; + case JT_CMD_REGISTER_ACK: + LOG(DEBUG,"clock(%d) protocol_jt_parse_msg(JT_CMD_REGISTER_ACK).", util_clock()); + protocol_jt_parse_register_ack(pdata,len); + break; + case JT_CMD_SET_PARAM: + LOG(DEBUG,"clock(%d) protocol_jt_parse_msg(JT_CMD_SET_PARAM).", util_clock()); + protocol_jt_parse_set_param(pdata,len); + break; + case JT_CMD_GET_PARAM: + LOG(DEBUG,"clock(%d) protocol_jt_parse_msg(JT_CMD_GET_PARAM).", util_clock()); + protocol_jt_parse_get_param(pdata,len); + break; + case JT_CMD_TERM_CTL: + LOG(DEBUG,"clock(%d) protocol_jt_parse_msg(JT_CMD_TERM_CTL).", util_clock()); + protocol_jt_parse_terminal_control(pdata,len); + break; + case JT_CMD_LOCATE_REQ: + LOG(DEBUG,"clock(%d) protocol_jt_parse_msg(JT_CMD_LOCATE_REQ).", util_clock()); + protocol_jt_parse_gps_req(pdata,len); + break; + case JT_CMD_CONFIRM_ALARM: + LOG(DEBUG,"clock(%d) protocol_jt_parse_msg(JT_CMD_CONFIRM_ALARM).", util_clock()); + protocol_jt_parse_general_msg(pdata,len); + break; + case JT_CMD_TEXT: + LOG(DEBUG,"clock(%d) protocol_jt_parse_msg(JT_CMD_TEXT).", util_clock()); + protocol_jt_parse_text(pdata,len); + break; + default: + LOG(DEBUG,"clock(%d) protocol_jt_parse_msg(%04x).", util_clock(),cmd); + log_service_print_hex((const char *)pdata,len); + protocol_jt_parse_general_msg(pdata,len); + break; + } +} + +static void protocol_jt_parse_text(U8* pdata, u16 len) +{ + U8* pOut = NULL; + u16 out_len = 0; + u8 idx = 0; + u16 msg_info; + u16 msg_len; + u8 msg_depart; + u8 msg_sec; + u8 data_start; + + msg_info = ((u16)pdata[3]<<8)+pdata[4]; + + // 保留(15 14) 分包(13) 加密(12 11 10) 长度(9-0) + msg_len = msg_info & 0x3FF; + msg_depart =(msg_info & JT_DATA_DEPART_FLAG)?1:0; + msg_sec = (msg_info & JT_DATA_SEC_FLAG) >> 10; + data_start = msg_depart ? 17: 13; + msg_sec = msg_sec; + + if(len != (data_start + msg_len + 2)) + { + LOG(INFO,"clock(%d) protocol_jt_parse_text assert(len(%d)).", util_clock(), len); + return; + } + + s_jt_msg_save.msg_id = ((u16)pdata[1]<<8)+pdata[2]; + s_jt_msg_save.server_serial = ((u16)pdata[11]<<8)+pdata[12]; + s_jt_msg_save.msg_result = 0; //成功 + + pOut = GM_MemoryAlloc(CMD_MAX_LEN + 1); + if (NULL == pOut) + { + LOG(WARN,"protocol_concox_parse_remote_msg assert(GM_MemoryAlloc(%d)) failed.", CMD_MAX_LEN + 1); + return; + } + + GM_memset(pOut, 0x00, CMD_MAX_LEN + 1); + + // flag(1) command(N) + idx = data_start + 1; + command_on_receive_data(COMMAND_GPRS, (char *)&pdata[idx], msg_len - 1, (char *)pOut,NULL); + out_len = GM_strlen((char *)pOut); + + if (out_len > 0) + { + gps_service_after_receive_remote_msg(pOut, out_len); + } + + //发送ack + gps_service_after_server_req(); + GM_MemoryFree(pOut); +} + +static void protocol_jt_parse_gps_req(U8* pdata, u16 len) +{ + u16 msg_info; + u16 msg_len; + u8 msg_depart; + u8 msg_sec; + u8 data_start; + + msg_info = ((u16)pdata[3]<<8)+pdata[4]; + + // 保留(15 14) 分包(13) 加密(12 11 10) 长度(9-0) + msg_len = msg_info & 0x3FF; + msg_depart =(msg_info & JT_DATA_DEPART_FLAG)?1:0; + msg_sec = (msg_info & JT_DATA_SEC_FLAG) >> 10; + data_start = msg_depart ? 17: 13; + msg_sec = msg_sec; + + if(len != (data_start + msg_len + 2)) + { + LOG(INFO,"clock(%d) protocol_jt_parse_gps_req assert(len(%d)).", util_clock(), len); + return; + } + + s_jt_msg_save.msg_id = ((u16)pdata[1]<<8)+pdata[2]; + s_jt_msg_save.server_serial = ((u16)pdata[11]<<8)+pdata[12]; + s_jt_msg_save.msg_result = 0; //成功 + + + //发送定位数据 + gps_service_after_server_locate_req(); +} + +static void protocol_jt_parse_general_msg(U8* pdata, u16 len) +{ + u16 msg_info; + u16 msg_len; + u8 msg_depart; + u8 msg_sec; + u8 data_start; + + msg_info = ((u16)pdata[3]<<8)+pdata[4]; + + // 保留(15 14) 分包(13) 加密(12 11 10) 长度(9-0) + msg_len = msg_info & 0x3FF; + msg_depart =(msg_info & JT_DATA_DEPART_FLAG)?1:0; + msg_sec = (msg_info & JT_DATA_SEC_FLAG) >> 10; + data_start = msg_depart ? 17: 13; + msg_sec = msg_sec; + + if(len != (data_start + msg_len + 2)) + { + LOG(INFO,"clock(%d) protocol_jt_parse_general_msg assert(len(%d)).", util_clock(), len); + return; + } + + s_jt_msg_save.msg_id = ((u16)pdata[1]<<8)+pdata[2]; + s_jt_msg_save.server_serial = ((u16)pdata[11]<<8)+pdata[12]; + s_jt_msg_save.msg_result = 0; //成功 + + //发送ack + gps_service_after_server_req(); +} + +static void protocol_jt_parse_terminal_control(U8* pdata, u16 len) +{ + u16 msg_info; + u16 msg_len; + u8 msg_depart; + u8 msg_sec; + u8 data_start; + GM_ERRCODE ret = GM_SUCCESS; + + msg_info = ((u16)pdata[3]<<8)+pdata[4]; + + // 保留(15 14) 分包(13) 加密(12 11 10) 长度(9-0) + msg_len = msg_info & 0x3FF; + msg_depart =(msg_info & JT_DATA_DEPART_FLAG)?1:0; + msg_sec = (msg_info & JT_DATA_SEC_FLAG) >> 10; + data_start = msg_depart ? 17: 13; + msg_sec = msg_sec; + + if(len != (data_start + msg_len + 2)) + { + LOG(INFO,"clock(%d) protocol_jt_parse_terminal_control assert(len(%d)).", util_clock(), len); + return; + } + + s_jt_msg_save.msg_id = ((u16)pdata[1]<<8)+pdata[2]; + s_jt_msg_save.server_serial = ((u16)pdata[11]<<8)+pdata[12]; + + switch(pdata[data_start]) + { + case 4: //终端复位 + ret = hard_ware_reboot(GM_REBOOT_CMD,1); + LOG(DEBUG,"clock(%d) protocol_jt_parse_terminal_control hard_ware_reboot.", util_clock()); + break; + case 0x64: //断油电 + ret = hard_ware_set_relay(true); + LOG(DEBUG,"clock(%d) protocol_jt_parse_terminal_control hard_ware_set_relay broke.", util_clock()); + break; + case 0x65: //通油电 + ret = hard_ware_set_relay(false); + LOG(DEBUG,"clock(%d) protocol_jt_parse_terminal_control hard_ware_set_relay good.", util_clock()); + break; + } + + if(GM_SUCCESS == ret) + { + s_jt_msg_save.msg_result = 0; //成功 + } + else + { + s_jt_msg_save.msg_result = 1; //失败 + } + + //发送ack + gps_service_after_server_req(); +} + +static void protocol_jt_parse_get_param(U8* pdata, u16 len) +{ + u16 msg_info; + u16 msg_len; + u8 msg_depart; + u8 msg_sec; + u8 data_start; + + msg_info = ((u16)pdata[3]<<8)+pdata[4]; + + // 保留(15 14) 分包(13) 加密(12 11 10) 长度(9-0) + msg_len = msg_info & 0x3FF; + msg_depart =(msg_info & JT_DATA_DEPART_FLAG)?1:0; + msg_sec = (msg_info & JT_DATA_SEC_FLAG) >> 10; + data_start = msg_depart ? 17: 13; + msg_sec = msg_sec; + + if(len != (data_start + msg_len + 2)) + { + LOG(INFO,"clock(%d) protocol_jt_parse_get_param assert(len(%d)).", util_clock(), len); + return; + } + + s_jt_msg_save.msg_id = ((u16)pdata[1]<<8)+pdata[2]; + s_jt_msg_save.server_serial = ((u16)pdata[11]<<8)+pdata[12]; + + gps_service_after_param_get(); +} + +static void protocol_jt_parse_set_param(U8* pdata, u16 len) +{ + u16 msg_info = 0; + u16 msg_len = 0; + u8 msg_depart = 0; + u8 msg_sec = 0; + + u8 data_start = 0; + u8 data_count = 0; + u8 para_idx = 0; + u32 para_id = 0; + u8 para_len = 0; + + u16 value_u16; + u8 value_u8; + + s_jt_msg_save.msg_id = ((u16)pdata[1]<<8)+pdata[2]; + s_jt_msg_save.server_serial = ((u16)pdata[11]<<8)+pdata[12]; + msg_info = ((u16)pdata[3]<<8)+pdata[4]; + + // 保留(15 14) 分包(13) 加密(12 11 10) 长度(9-0) + msg_len = msg_info & 0x3FF; + msg_depart =(msg_info & JT_DATA_DEPART_FLAG)?1:0; + msg_sec = (msg_info & JT_DATA_SEC_FLAG) >> 10; + data_start = msg_depart ? 17: 13; + msg_sec = msg_sec; + + if(len != (data_start + msg_len + 2)) + { + LOG(INFO,"clock(%d) protocol_jt_parse_set_param assert(len(%d)).", util_clock(), len); + return; + } + + //参数总数 + data_count = pdata[data_start++]; + while(para_idx < data_count) + { + ++para_idx; + //参数 ID(2) 参数长度(1) 参数值 + + para_id = ((u32)pdata[data_start]<<24)+((u32)pdata[data_start+1]<<16)+((u32)pdata[data_start+2]<<8)+((u32)pdata[data_start+3]); + para_len = pdata[data_start+4]; + data_start += 5; + + if(len < (data_start + para_len + 2)) + { + LOG(INFO,"clock(%d) protocol_jt_parse_set_param assert(len(%d)).", util_clock(), len); + return; + } + + switch(para_id) + { + case JT_PARAM_HEART_INTERVAL: + value_u16 = (u16)get_value_by_length(&pdata[data_start], para_len); + if(value_u16 >= GOOME_HEARTBEAT_MIN && value_u16 <= GOOME_HEARTBEAT_MAX) + { + config_service_set(CFG_HEART_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + } + else + { + LOG(INFO,"clock(%d) protocol_jt_parse_set_param assert(JT_PARAM_HEART_INTERVAL(%d)) failed.", util_clock(), value_u16); + } + break; + case JT_PARAM_APN: + config_service_set(CFG_APN_NAME, TYPE_STRING, &pdata[data_start], para_len); + break; + case JT_PARAM_APN_USR: + config_service_set(CFG_APN_USER, TYPE_STRING, &pdata[data_start], para_len); + break; + case JT_PARAM_APN_PWD: + config_service_set(CFG_APN_PWD, TYPE_STRING, &pdata[data_start], para_len); + break; + case JT_PARAM_IP: + config_service_get(CFG_SERVERLOCK, TYPE_BYTE, &value_u8, sizeof(value_u8)); + if(! value_u8) + { + config_service_change_ip(CFG_SERVERADDR, &pdata[data_start], para_len); + gps_service_change_config(); + } + case JT_PARAM_PORT: + value_u16 = (u16)get_value_by_length(&pdata[data_start], para_len); + config_service_change_port(CFG_SERVERADDR,value_u16); + gps_service_change_config(); + break; + case JT_PARAM_HEART_LOCATE_INTERVAL: + value_u16 = (u16)get_value_by_length(&pdata[data_start], para_len); + if(value_u16 >= GOOME_HEARTBEAT_MIN && value_u16 <= CONFIG_UPLOAD_TIME_MAX) + { + config_service_set(CFG_JT_HBINTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + } + else + { + LOG(INFO,"clock(%d) protocol_jt_parse_set_param assert(JT_PARAM_HEART_LOCATE_INTERVAL(%d)) failed.", util_clock(), value_u16); + } + break; + case JT_PARAM_TIME_INTERVAL: + value_u16 = (u16)get_value_by_length(&pdata[data_start], para_len); + if(value_u16 >= CONFIG_UPLOAD_TIME_MIN && value_u16 <= CONFIG_UPLOAD_TIME_MAX) + { + config_service_set(CFG_UPLOADTIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + } + else + { + LOG(INFO,"clock(%d) protocol_jt_parse_set_param assert(JT_PARAM_TIME_INTERVAL(%d)) failed.", util_clock(), value_u16); + } + break; + case JT_PARAM_TURN_ANGLE: + value_u16 = (u16)get_value_by_length(&pdata[data_start], para_len); + if(value_u16 < 180) + { + config_service_set(CFG_TURN_ANGLE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + } + else + { + LOG(INFO,"clock(%d) protocol_jt_parse_set_param assert(JT_PARAM_TURN_ANGLE(%d)) failed.", util_clock(), value_u16); + } + break; + case JT_PARAM_MAX_SPEED: + value_u8 = (u8)get_value_by_length(&pdata[data_start], para_len); + if(0 == value_u8) + { + //只修改开关,不修改速度值 + config_service_set(CFG_SPEED_ALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + } + else if(value_u8 >=5 && value_u8 <= 180) + { + config_service_set(CFG_SPEEDTHR, TYPE_BYTE, &value_u8, sizeof(value_u8)); + + //打开开关 + value_u8 = 1; + config_service_set(CFG_SPEED_ALARM_ENABLE, TYPE_BOOL, &value_u8, sizeof(value_u8)); + } + else + { + LOG(INFO,"clock(%d) protocol_jt_parse_set_param assert(JT_PARAM_MAX_SPEED(%d)) failed.", util_clock(), value_u8); + } + break; + case JT_PARAM_EXCEED_SPEED_TIME: + value_u8 = (u8)get_value_by_length(&pdata[data_start], para_len); + config_service_set(CFG_SPEED_CHECK_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + break; + case JT_PARAM_PROVINCE: + value_u16 = (u16)get_value_by_length(&pdata[data_start], para_len); + config_service_set(CFG_JT_PROVINCE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + break; + case JT_PARAM_CITY: + value_u16 = (u16)get_value_by_length(&pdata[data_start], para_len); + config_service_set(CFG_JT_CITY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + break; + case JT_PARAM_BRAND: + value_u8 = (para_len > 12) ? 12 : para_len; + config_service_set(CFG_JT_VEHICLE_NUMBER, TYPE_STRING, &pdata[data_start], value_u8); + break; + case JT_PARAM_BRAND_COLOR: + value_u16 = (u16)get_value_by_length(&pdata[data_start], para_len); + config_service_set(CFG_JT_VEHICLE_COLOR, TYPE_SHORT, &value_u16, sizeof(value_u16)); + break; + default: + break; + } + + data_start += para_len; + } + + if(data_count > 0) + { + config_service_save_to_local(); + + //发送ack + gps_service_after_server_req(); + + gps_service_change_config(); + } +} + +static void protocol_jt_parse_register_ack(U8* pdata, u16 len) +{ + u16 msg_info; + u16 msg_len; + u8 msg_depart; + u8 msg_sec; + u8 data_start; + u8 auth_code[100]; + u8 value_u8; + + msg_info = ((u16)pdata[3]<<8)+pdata[4]; + + // 保留(15 14) 分包(13) 加密(12 11 10) 长度(9-0) + msg_len = msg_info & 0x3FF; + msg_depart =(msg_info & JT_DATA_DEPART_FLAG)?1:0; + msg_sec = (msg_info & JT_DATA_SEC_FLAG) >> 10; + data_start = msg_depart ? 17: 13; + msg_sec = msg_sec; + + // {流水号2;结果1;鉴权码n;}checksum 1;flag 1; + if(len != (data_start + msg_len + 2)) + { + LOG(INFO,"clock(%d) protocol_jt_parse_register_ack assert(len(%d)).", util_clock(), len); + return; + } + + + //0 注册成功 3 终端 已注册 + if(pdata[data_start + 2] == 0 || pdata[data_start + 2] == 3) + { + LOG(INFO,"clock(%d) protocol_jt_parse_register_ack regist ok(%d).", util_clock(), pdata[data_start + 2]); + GM_memset(auth_code, 0x00, sizeof(auth_code)); + auth_code[0] = msg_len - 3; //为兼容,第一个字节是长度 + if(auth_code[0]) + { + GM_memcpy(&auth_code[1], &pdata[data_start + 3], auth_code[0]); + config_service_set(CFG_JT_AUTH_CODE, TYPE_STRING, &auth_code, auth_code[0] + 1); + } + + //记录已注册成功 + value_u8 = 1; + config_service_set(CFG_JT_ISREGISTERED, TYPE_BOOL, &value_u8, sizeof(value_u8)); + + config_service_save_to_local(); + + gps_service_after_register_response(); + } + else + { + LOG(INFO,"clock(%d) protocol_jt_parse_register_ack regist failed(%d).", util_clock(), pdata[data_start + 2]); + } +} + + +static void protocol_jt_parse_plat_ack(U8* pdata, u16 len) +{ + u16 msg_info; + u16 msg_len; + u8 msg_depart; + u8 msg_sec; + u8 data_start; + u16 msg_id; + + msg_info = ((u16)pdata[3]<<8)+pdata[4]; + + // 保留(15 14) 分包(13) 加密(12 11 10) 长度(9-0) + msg_len = msg_info & 0x3FF; + msg_depart =(msg_info & JT_DATA_DEPART_FLAG)?1:0; + msg_sec = (msg_info & JT_DATA_SEC_FLAG) >> 10; + data_start = msg_depart ? 17: 13; + msg_len = msg_len; + msg_sec = msg_sec; + + // 流水号 2 消息号2 结果1 checksum 1 flag 1 + if(len != (data_start + msg_len + 2)) + { + LOG(INFO,"clock(%d) protocol_jt_parse_plat_ack assert(len(%d)).", util_clock(), len); + return; + } + + msg_id = ((u16)pdata[data_start + 2]<<8)+pdata[data_start + 3]; + switch(msg_id) + { + case JT_CMD_AUTH: + // 0 成功,确认 ; 1失败; 2消息有误; 3不支持; 4报警; + if(pdata[data_start + 4] == 0) + { + LOG(INFO,"clock(%d) protocol_jt_parse_plat_ack auth ok(%d).", util_clock(), pdata[4]); + gps_service_after_login_response(); + } + else + { + u8 value_u8 = 0; + LOG(INFO,"clock(%d) protocol_jt_parse_plat_ack auth failed(%d).", util_clock(), pdata[4]); + config_service_set(CFG_JT_ISREGISTERED, TYPE_BOOL, &value_u8, sizeof(value_u8)); + // config_service_save_to_local(); // not so important to write to disk + } + break; + case JT_CMD_HEART_BEAT: + gps_service_after_receive_heartbeat(); + case JT_CMD_UNREGISTER: + break; + case JT_CMD_LOCATE: + gps_service_after_receive_heartbeat(); + break; + case JT_CMD_LOCATE_MULTI: + break; + } +} + + + +void protocol_jt_pack_remote_ack(u8 *pdata, u16 *idx, u16 len, u8 *pRet, u16 retlen) +{ + const char prefix_string[] = "返回:"; + u8 *send; + u16 send_len = 0; + u16 content_len = 0; + send = (u8 *) GM_MemoryAlloc(len); + if (send == NULL) + { + LOG(INFO,"clock(%d) protocol_jt_pack_remote_ack assert(GM_MemoryAlloc(%d)) failed.", util_clock(), len); + return; + } + + + protocol_jt_pack_head(send, &send_len, len, 1, 0); // 13bytes | 17bytes + content_len=retlen + GM_strlen(prefix_string); + content_len=GM_snprintf((char *)&send[send_len], content_len, "%s%s",prefix_string,pRet); + send_len += content_len; + if((send_len + 2) > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_remote_ack assert(len(%d)) failed content_len(%d) send_len(%d).", + util_clock(), len,content_len, send_len); + GM_MemoryFree(send); + return; + } + protocol_jt_pack_id_len(send, &send_len, JT_CMD_TEXT_RESULT, content_len, 0, false); // 2bytes + *idx = len; + protocol_jt_pack_escape(send, send_len, pdata, idx); + + GM_MemoryFree(send); + return; +} + +static void protocol_jt_pack_server_info(u8 *pdata, u16 *idx, u16 len, u16 *return_len) +{ + pdata[(*idx)++] = BHIGH_BYTE(s_jt_msg_save.server_serial); + pdata[(*idx)++] = BLOW_BYTE(s_jt_msg_save.server_serial); + pdata[(*idx)++] = BHIGH_BYTE(s_jt_msg_save.msg_id); + pdata[(*idx)++] = BLOW_BYTE(s_jt_msg_save.msg_id); + pdata[(*idx)++] = s_jt_msg_save.msg_result; + + *return_len = 5; +} + +void protocol_jt_pack_general_ack(u8 *pdata, u16 *idx, u16 len) +{ + u8 *send; + u16 send_len = 0; + u16 content_len = 0; + send = (u8 *) GM_MemoryAlloc(len); + if (send == NULL) + { + LOG(INFO,"clock(%d) protocol_jt_pack_general_ack assert(GM_MemoryAlloc(%d)) failed.", util_clock(), len); + return; + } + + protocol_jt_pack_head(send, &send_len, len, 1, 0); // 13bytes | 17bytes + protocol_jt_pack_server_info(send, &send_len, len, &content_len); //5 bytes + if((send_len + 2) > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_general_ack assert(len(%d)) failed.", util_clock(), len); + GM_MemoryFree(send); + return; + } + protocol_jt_pack_id_len(send, &send_len, JT_CMD_TERM_ACK, content_len, 0, false); // 2bytes + *idx = len; + protocol_jt_pack_escape(send, send_len, pdata, idx); + + GM_MemoryFree(send); + return; +} + +static void protocol_jt_pack_item_num(u8 *pdata, u16 *idx, u32 item, u32 value, u8 item_len) +{ + u16 value_u16; + u8 value_u8; + + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(item)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(item)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(item)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(item)); + pdata[(*idx)++] = item_len; + + if(item_len == 4) + { + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(value)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(value)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(value)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(value)); + } + else if (item_len == 2) + { + value_u16 = value; + pdata[(*idx)++] = BHIGH_BYTE(value_u16); + pdata[(*idx)++] = BLOW_BYTE(value_u16); + } + else // if (item_len == 1) + { + value_u8 = value; + pdata[(*idx)++] = value_u8; + } + + (*idx) += item_len; +} + + +static void protocol_jt_pack_item_string(u8 *pdata, u16 *idx, u32 item, u8 *pitem, u8 item_len) +{ + pdata[(*idx)++] = BHIGH_BYTE(WHIGH_WORD(item)); + pdata[(*idx)++] = BLOW_BYTE(WHIGH_WORD(item)); + pdata[(*idx)++] = BHIGH_BYTE(WLOW_WORD(item)); + pdata[(*idx)++] = BLOW_BYTE(WLOW_WORD(item)); + pdata[(*idx)++] = item_len; + + GM_memcpy(&pdata[(*idx)], pitem, item_len); + (*idx) += item_len; +} + +static void protocol_jt_pack_param_info(u8 *pdata, u16 *idx, u16 len, u16 *return_len) +{ + u16 orginal_idx = *idx; + u16 value_u16; + u8 value_u8; + u8 value_str[26]; + + pdata[(*idx)++] = BHIGH_BYTE(s_jt_msg_save.server_serial); + pdata[(*idx)++] = BLOW_BYTE(s_jt_msg_save.server_serial); + pdata[(*idx)++] = 40; // total 40 items + + config_service_get(CFG_HEART_INTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + protocol_jt_pack_item_num(pdata, idx, JT_PARAM_HEART_INTERVAL, value_u16, 4); + + protocol_jt_pack_item_num(pdata, idx, 0x0002, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0003, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0004, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0005, 0, 4); + + + protocol_jt_pack_item_num(pdata, idx, 0x0006, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0007, 0, 4); + + config_service_get(CFG_APN_NAME, TYPE_STRING, value_str, sizeof(value_str)); + protocol_jt_pack_item_string(pdata, idx, JT_PARAM_APN, value_str, GM_strlen((const char *)value_str)); + + protocol_jt_pack_item_string(pdata, idx, 0x0011, value_str, 0); + protocol_jt_pack_item_string(pdata, idx, 0x0012, value_str, 0); + + + protocol_jt_pack_item_string(pdata, idx, 0x0013, value_str, 0); + protocol_jt_pack_item_string(pdata, idx, 0x0014, value_str, 0); + protocol_jt_pack_item_string(pdata, idx, 0x0015, value_str, 0); + protocol_jt_pack_item_string(pdata, idx, 0x0016, value_str, 0); + protocol_jt_pack_item_string(pdata, idx, 0x0017, value_str, 0); + + + protocol_jt_pack_item_num(pdata, idx, 0x0018, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0019, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0020, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0021, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0022, 0, 4); + + config_service_get(CFG_JT_HBINTERVAL, TYPE_SHORT, &value_u16, sizeof(value_u16)); + protocol_jt_pack_item_num(pdata, idx, JT_PARAM_HEART_LOCATE_INTERVAL, value_u16, 4); + + protocol_jt_pack_item_num(pdata, idx, 0x0028, 0, 4); + + config_service_get(CFG_UPLOADTIME, TYPE_SHORT, &value_u16, sizeof(value_u16)); + protocol_jt_pack_item_num(pdata, idx, JT_PARAM_TIME_INTERVAL, value_u16, 4); + + config_service_get(CFG_TURN_ANGLE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + protocol_jt_pack_item_num(pdata, idx, JT_PARAM_TURN_ANGLE, value_u16, 4); + + config_service_get(CFG_SPEEDTHR, TYPE_BYTE, &value_u8, sizeof(value_u8)); + protocol_jt_pack_item_num(pdata, idx, JT_PARAM_MAX_SPEED, value_u8, 4); + + config_service_get(CFG_SPEED_CHECK_TIME, TYPE_BYTE, &value_u8, sizeof(value_u8)); + protocol_jt_pack_item_num(pdata, idx, JT_PARAM_EXCEED_SPEED_TIME, value_u16, 4); + + protocol_jt_pack_item_num(pdata, idx, 0x0057, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0058, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0059, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x005A, 0, 4); + + + protocol_jt_pack_item_num(pdata, idx, 0x0070, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0071, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0072, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0073, 0, 4); + protocol_jt_pack_item_num(pdata, idx, 0x0074, 0, 4); + + + protocol_jt_pack_item_num(pdata, idx, JT_PARAM_MILIAGE, 0, 4); + + config_service_get(CFG_JT_PROVINCE, TYPE_SHORT, &value_u16, sizeof(value_u16)); + protocol_jt_pack_item_num(pdata, idx, JT_PARAM_PROVINCE, value_u16, 4); + + config_service_get(CFG_JT_CITY, TYPE_SHORT, &value_u16, sizeof(value_u16)); + protocol_jt_pack_item_num(pdata, idx, JT_PARAM_CITY, value_u16, 4); + + config_service_get(CFG_JT_VEHICLE_NUMBER, TYPE_STRING, value_str, sizeof(value_str)); + protocol_jt_pack_item_string(pdata, idx, JT_PARAM_BRAND, value_str, GM_strlen((const char *)value_str)); + + config_service_get(CFG_JT_VEHICLE_COLOR, TYPE_BYTE, &value_u8, sizeof(value_u8)); + protocol_jt_pack_item_num(pdata, idx, JT_PARAM_BRAND_COLOR, value_u8, 4); + + *return_len = (*idx) - orginal_idx; +} + +void protocol_jt_pack_param_ack(u8 *pdata, u16 *idx, u16 len) +{ + u8 *send; + u16 send_len = 0; + u16 content_len = 0; + send = (u8 *) GM_MemoryAlloc(len); + if (send == NULL) + { + LOG(INFO,"clock(%d) protocol_jt_pack_general_ack assert(GM_MemoryAlloc(%d)) failed.", util_clock(), len); + return; + } + + + protocol_jt_pack_head(send, &send_len, len, 1, 0); // 13bytes | 17bytes + protocol_jt_pack_param_info(send, &send_len, len, &content_len); //5 bytes + if((send_len + 2) > len) + { + LOG(WARN,"clock(%d) protocol_jt_pack_general_ack assert(len(%d)) failed.", util_clock(), len); + GM_MemoryFree(send); + return; + } + protocol_jt_pack_id_len(send, &send_len, JT_CMD_GET_PARAM_ACK, content_len, 0, false); // 2bytes + *idx = len; + protocol_jt_pack_escape(send, send_len, pdata, idx); + + GM_MemoryFree(send); + return; +} + + diff --git a/src/relay.c b/src/relay.c new file mode 100644 index 0000000..392c25e --- /dev/null +++ b/src/relay.c @@ -0,0 +1,183 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: relay.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-01 + * Description: + * Others: + * Function List: + 1. 创建relay模块 + 2. 销毁relay模块 + 3. relay模块定时处理入口 + 4. 断油电 + 5. 恢复油电 + * History: + 1. Date: 2019-03-01 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include "relay.h" +#include "hard_ware.h" +#include "gps.h" +#include "system_state.h" +#include "utility.h" +#include "log_service.h" + +/** + * Function: 创建relay模块 + * Description:创建relay模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE relay_create(void) +{ + if (system_state_get_user_relay_state()) + { + return relay_on(false); + } + + //lz add for compiler error + return GM_SUCCESS; +} + +/** + * Function: 销毁relay模块 + * Description:销毁relay模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE relay_destroy(void) +{ + return GM_SUCCESS; +} + +/** + * Function: relay模块定时处理入口 + * Description:不满足断油电条件的,定时检查条件,条件满足时执行 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 1秒钟调用1次 + */ +GM_ERRCODE relay_timer_proc(void) +{ + bool user_relay_state = system_state_get_user_relay_state(); + bool device_relay_state = system_state_get_device_relay_state(); + if (user_relay_state != device_relay_state) + { + if (true == user_relay_state) + { + return relay_on(true); + } + else + { + return relay_off(); + } + } + else + { + return GM_SUCCESS; + } +} + +/** + * Function: 断油电 + * Description:接常闭继电器,打开继电器=断油电,不满足执行条件时会在条件满足时执行最后一条指令 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE relay_on (bool check_speed) +{ + GM_ERRCODE ret = GM_SUCCESS; + GPSData gps_data; + + system_state_set_user_relay_state(true); + + //如果当前是休眠状态,直接断油电 + //如果当前是静止状态, 直接断油电 + //如果当前系统刚刚启动(小于2秒),直接断油电 + if (GM_SYSTEM_STATE_SLEEP == system_state_get_work_state() + || VEHICLE_STATE_STATIC == system_state_get_vehicle_state() + || system_state_get_start_time() < 2) + { + ret = hard_ware_set_relay(true); + if (GM_SUCCESS == ret) + { + JsonObject* p_json_log = json_create(); + json_add_string(p_json_log,"event","relay on"); + json_add_string(p_json_log,"state","static"); + log_service_upload(INFO, p_json_log); + system_state_set_device_relay_state(true); + LOG(INFO,"Succeed to open relay."); + } + return ret; + } + //否则检查速度情况 + if (check_speed && !gps_get_last_data(&gps_data)) + { + return GM_WILL_DELAY_EXEC; + } + //如果是3D定位并且速度小于20,直接执行,否则会延迟执行 + if (!check_speed || (gps_is_fixed() && gps_data.speed < 20)) + { + ret = hard_ware_set_relay(true); + if (GM_SUCCESS == ret) + { + JsonObject* p_json_log = json_create(); + json_add_string(p_json_log,"event","relay on"); + json_add_string(p_json_log,"state","low speed"); + log_service_upload(INFO, p_json_log); + system_state_set_device_relay_state(true); + LOG(INFO,"Succeed to open relay."); + } + return ret; + } + else + { + return GM_WILL_DELAY_EXEC; + } +} + +/** + * Function: 恢复油电 + * Description:接常闭继电器,关闭继电器=恢复油电,不满足执行条件时会在条件满足时执行最后一条指令 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE relay_off (void) +{ + GM_ERRCODE ret = GM_SUCCESS; + + system_state_set_user_relay_state(false); + + //如果当前状态和用户希望的状态一致,直接返回成功 + if (false == system_state_get_device_relay_state()) + { + return GM_SUCCESS; + } + + ret = hard_ware_set_relay(false); + if (GM_SUCCESS == ret) + { + JsonObject* p_json_log = json_create(); + json_add_string(p_json_log,"event","relay off"); + log_service_upload(INFO, p_json_log); + system_state_set_device_relay_state(false); + } + return ret; +} + diff --git a/src/sample_json.c b/src/sample_json.c new file mode 100644 index 0000000..6b76561 --- /dev/null +++ b/src/sample_json.c @@ -0,0 +1,49 @@ +#include +#include "json.h" + +int test_create_json() +{ + /* + { + "semantic": + { + "slots": + { + "name":"张三" + } + }, + "rc":0, + "operation":"CALL", + "service":"telephone", + "text":"打电话给张三" + } + */ + + JsonObject* root = json_create(); + JsonObject* semantic = json_create(); + JsonObject* slots = json_create(); + + //root节点下添加semantic节点 + json_add_string(root, "semantic", semantic); + + //semantic节点下添加slots节点 + json_add_string(semantic, "slots", slots); + + //添加name节点 + json_add_string(slots, "name", ("张三")); + + //根节点下添加 + json_add_string(root, "rc", (0)); + json_add_string(root, "operation", ("CALL")); + json_add_string(root, "service", ("telephone")); + json_add_string(root, "text", ("打电话给张三")); + + printf("%s\n", cJSON_Print(root)); + + //释放内存 + json_destroy(root); + + return 0; +} + + diff --git a/src/sms.c b/src/sms.c new file mode 100644 index 0000000..207471e --- /dev/null +++ b/src/sms.c @@ -0,0 +1,153 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: sms.c + * Author: 王志华 + * Version: 1.0 + * Date: 2019-04-08 + * Description: + * Others: + * Function List: + 1. 创建sms模块 + 2. 销毁sms模块 + 3. sms模块定时处理入口 + * History: + 1. Date: 2019-04-08 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include +#include +#include +#include "sms.h" +#include "fifo.h" +#include "log_service.h" +#include "command.h" +#define GM_NUMBER_MAX_LEN 20 +#define GM_SMS_QUEUE_LEN 3 + + +typedef struct +{ + ENUM_SMSAL_DCS doc_type; + char number[GM_NUMBER_MAX_LEN]; + char content[CMD_MAX_LEN]; +}Message; + +typedef struct +{ + FifoType message_queue; + + //发送失败次数 + U8 send_error_times; +}SMS; + + +static SMS s_sms; + +static void send_sms_callback(void* p_msg); +static void send_sms_real(void); +static void on_recv_sms(void* p_msg); + +GM_ERRCODE sms_create(void) +{ + GM_RegisterCallBack(GM_CB_SMS_RECEIVE, (U32)on_recv_sms); + fifo_init(&s_sms.message_queue, GM_SMS_QUEUE_LEN * sizeof(Message)); + return GM_SUCCESS; +} + +GM_ERRCODE sms_destroy(void) +{ + GM_ERRCODE ret; + ret = fifo_delete(&s_sms.message_queue); + return ret; +} + +GM_ERRCODE sms_send(const char* p_data, u16 data_len, char* number, ENUM_SMSAL_DCS doc_type) +{ + GM_ERRCODE ret = GM_SUCCESS; + Message msg; + + data_len = (data_len > sizeof(msg.content) - 2) ? sizeof(msg.content) - 2 : data_len; + LOG(INFO,"Send SMS(%s),len:%d",number,data_len); + GM_memcpy(msg.content, p_data, data_len); + msg.content[data_len] = 0; + msg.content[data_len + 1] = 0; + msg.doc_type = doc_type; + GM_strncpy(msg.number, number, GM_strlen((char*)number)); + + ret = fifo_insert(&s_sms.message_queue, (U8*)&msg, sizeof(msg)); + + if (GM_SUCCESS != ret) + { + return ret; + } + else + { + send_sms_real(); + return GM_SUCCESS; + } +} + +static void send_sms_callback(void* p_msg) +{ + if(NULL == p_msg) + { + return; + } + + //发送成功 + if (*(U32*)p_msg) + { + s_sms.send_error_times = 0; + + //发送成功,从队列中移除 + LOG(INFO,"Succeed to send SMS."); + fifo_pop_len(&s_sms.message_queue, sizeof(Message)); + } + else + { + s_sms.send_error_times++; + if (s_sms.send_error_times >= 3) + { + //丢弃一条短信 + LOG(WARN,"Faild to send SMS.err=%d",*(U32*)p_msg); + fifo_pop_len(&s_sms.message_queue, sizeof(Message)); + s_sms.send_error_times = 0; + } + } + + //300毫秒后发送下一条短信 + GM_StartTimer(GM_TIMER_SMS_SEND, TIM_GEN_100MS*3, send_sms_real); +} + +static void send_sms_real(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + + Message msg; + + ret = fifo_peek(&s_sms.message_queue, (U8*)&msg, sizeof(msg)); + if (GM_SUCCESS != ret) + { + return; + } + GM_SendSMS(msg.number, msg.content, msg.doc_type, send_sms_callback); + LOG(INFO,"Send SMS:%s",msg.content); +} + +static void on_recv_sms(void* p_msg) +{ + char respons[CMD_MAX_LEN + 1] = {0}; + gm_sms_new_msg_struct* p_sms =(gm_sms_new_msg_struct*)p_msg; + command_on_receive_data(COMMAND_SMS,p_sms->content,p_sms->messageLen,respons,p_msg); + if(GM_strlen(respons)) + { + sms_send(respons, GM_strlen(respons),p_sms->asciiNum,GM_DEFAULT_DCS); + } +} + diff --git a/src/socket.c b/src/socket.c new file mode 100644 index 0000000..676ea21 --- /dev/null +++ b/src/socket.c @@ -0,0 +1,724 @@ +#include "gm_type.h" +#include "stdio.h" +#include "gm_stdlib.h" +#include "gm_gprs.h" +#include "socket.h" +#include "gm_memory.h" +#include "gm_timer.h" +#include "config_service.h" +#include "gps_service.h" +#include "log_service.h" +#include "agps_service.h" +#include "update_service.h" +#include "update_file.h" +#include "utility.h" +#include "gm_system.h" +#include "system_state.h" + +/*returned by apn register, used when creating socket. */ +static int s_account_id = -1; +static SocketType *s_all_sockets[MAX_SOCKET_SUPPORTED]; + +#define SOCKET_STATUS_STRING_MAX_LEN 32 +const char s_socket_status_string[SOCKET_STATUS_MAX][SOCKET_STATUS_STRING_MAX_LEN] = +{ + "SOCKET_STATUS_INIT", + "SOCKET_STATUS_GET_HOST", + "SOCKET_STATUS_CONNECTING", + "SOCKET_STATUS_LOGIN", + "SOCKET_STATUS_WORK", + "SOCKET_STATUS_DATA_FINISH", + "SOCKET_STATUS_ERROR" +}; + + +/* +这里将dns解析单独出来, 各模块只管去取ip地址 并设置 requested= true., +没取到就等着, +取到了就继续 +*/ +typedef struct +{ + bool requested; /* 是否触发了要请求host_name */ + u8 fail_count; /* fail count of current status */ + u32 send_time; /* record time of recent get host, connect, send msg etc*/ +}GetHostItem; + +GetHostItem s_get_host_list[SOCKET_INDEX_MAX]; + +typedef struct +{ + SocketType *socket; + u8 count; + CurrentGetHostByNameStatus status; +}CurrentGetHostByName; + +static CurrentGetHostByName current_get_host; +static GM_ERRCODE gm_socket_get_host_by_name(SocketType *socket, GetHostItem *item); +static CurrentGetHostByNameStatus gm_socket_current_get_host_status(void); + +/*由于gethostbyname同时只能有一个, 所以下面的函数让各service模块判断是否自已的域名解析操作*/ +static u8 gm_socket_same_as_current_get_host(SocketType *socket); + + +static void init_all_sockets(void); +static GM_ERRCODE add_to_all_sockets(SocketType *p); +static void current_get_host_start(SocketType *socket); +static void gm_socket_connect_failed(SocketType *socket); + + +static void init_all_sockets(void) +{ + int i; + for(i =0; i< MAX_SOCKET_SUPPORTED; ++i) + { + s_all_sockets[i] = NULL; + } + + for(i = 0; iaccess_id == p->access_id) + { + s_all_sockets[i] = p; + return GM_SUCCESS; + } + } + + //没加入的情况, 找一个空位加入 + for(i =0; i< MAX_SOCKET_SUPPORTED; ++i) + { + if(s_all_sockets[i] == NULL) + { + s_all_sockets[i] = p; + return GM_SUCCESS; + } + } + + return GM_MEM_NOT_ENOUGH; +} + + +SocketType * get_socket_by_id(int id) +{ + int i; + for(i =0; i< MAX_SOCKET_SUPPORTED; ++i) + { + if(s_all_sockets[i] && s_all_sockets[i]->id == id) + { + return s_all_sockets[i]; + } + } + return NULL; +} + +SocketType * get_socket_by_accessid(int access_id) +{ + int i; + for(i =0; i< MAX_SOCKET_SUPPORTED; ++i) + { + if(s_all_sockets[i] && s_all_sockets[i]->access_id == access_id) + { + return s_all_sockets[i]; + } + } + return NULL; +} + + +GM_ERRCODE gm_socket_global_init(void) +{ + init_all_sockets(); + current_get_host_init(); + return GM_SUCCESS; +} + + +/* init socket*/ +GM_ERRCODE gm_socket_init(SocketType *socket) +{ + socket->id=-1; + socket->status = SOCKET_STATUS_INIT; + socket->send_time = 0; + socket->status_fail_count = 0; + socket->excuted_get_host = 0; + socket->last_ack_seq = 0; + + fifo_init(&(socket->fifo), SIZE_OF_SOCK_FIFO); + add_to_all_sockets(socket); + return GM_SUCCESS; +} + + +GM_ERRCODE gm_socket_set_addr(SocketType *socket, u8 *addr, u8 addr_len, u16 port, StreamType type) +{ + if(addr_len >= sizeof(socket->addr)) + { + return GM_PARAM_ERROR; + } + GM_memcpy(socket->addr, addr , addr_len); + socket->addr[addr_len] = 0; + socket->port = port; + socket->type = type; + return GM_SUCCESS; +} + +void gm_socket_set_account_id(int account_id) +{ + s_account_id = account_id; +} + +GM_ERRCODE gm_socket_set_ip_port(SocketType *socket, u8 ip[4], u16 port, StreamType type) +{ + socket->ip[0] = ip[0]; + socket->ip[1] = ip[1]; + socket->ip[2] = ip[2]; + socket->ip[3] = ip[3]; + socket->port = port; + socket->type = type; + return GM_SUCCESS; +} + +void gm_socket_destroy(SocketType * socket) +{ + LOG(INFO,"clock(%d) gm_socket_destroy socket->access_id(%d) .", + util_clock(), socket->access_id); + switch(socket->access_id) + { + case SOCKET_INDEX_MAIN: + gps_service_destroy(); + break; + case SOCKET_INDEX_EPO: //SOCKET_INDEX_AGPS + agps_service_destroy(); + break; + case SOCKET_INDEX_LOG: + log_service_destroy(); + break; + case SOCKET_INDEX_UPDATE: + update_service_destroy(); + break; + case SOCKET_INDEX_UPDATE_FILE: + update_filemod_destroy(); + break; + case SOCKET_INDEX_CONFIG: + config_service_destroy(); + break; + default: + LOG(WARN,"clock(%d) gm_socket_destroy assert(socket->access_id(%d) unknown.", + util_clock(), socket->access_id); + break; + } +} + +void gm_socket_global_destroy(void) +{ + int i; + + for(i =0; i< MAX_SOCKET_SUPPORTED; ++i) + { + if(s_all_sockets[i] == NULL) + { + continue; + } + gm_socket_destroy(s_all_sockets[i]); + } +} + + +void current_get_host_init(void) +{ + current_get_host.socket = NULL; + current_get_host.count = 0; + current_get_host.status = CURRENT_GET_HOST_INIT; +} + +/* get host can only start one by one .*/ +static void current_get_host_start(SocketType *socket) +{ + current_get_host.socket = socket; + current_get_host.count = 0; + current_get_host.status = CURRENT_GET_HOST_CONTINUE; +} + + +void socket_get_host_by_name_callback(void *msg) +{ + if(current_get_host.socket == NULL) + { + LOG(ERROR,"clock(%d) socket_get_host_by_name_callback assert(current_get_host.socket != NULL) failed.", + util_clock()); + current_get_host.status = CURRENT_GET_HOST_INIT; + return; + } + + if(GM_SUCCESS != gm_is_valid_ip((const u8 *)msg)) + { + LOG(INFO,"clock(%d) socket_get_host_by_name_callback(%s) return error msg %s.", + util_clock(), current_get_host.socket->addr, (const char *)msg); + current_get_host.status = CURRENT_GET_HOST_FAILED; + return; + } + + system_state_set_ip_cache(current_get_host.socket->access_id, (const U8*)msg); + current_get_host.status = CURRENT_GET_HOST_SUCCESS; + + LOG(INFO,"clock(%d) socket_get_host_by_name_callback (%s)(%d.%d.%d.%d).", + util_clock(), current_get_host.socket->addr, ((const U8*)msg)[0], + ((const U8*)msg)[1], ((const U8*)msg)[2], ((const U8*)msg)[3]); +} + + + + + +static CurrentGetHostByNameStatus gm_socket_current_get_host_status() +{ + return current_get_host.status; +} + +u8 gm_socket_same_as_current_get_host(SocketType *socket) +{ + if(current_get_host.socket == socket) + { + return 1; + } + return 0; +} + +GM_ERRCODE gm_socket_get_host_by_name(SocketType *socket, GetHostItem *item) +{ + u8 result = 0; + + if(socket->addr[0] == 0) + { + LOG(INFO,"clock(%d) gm_socket_get_host_by_name socket(%d)->addr is empty.", util_clock(), socket->access_id ); + return GM_PARAM_ERROR; + } + + if(gm_socket_current_get_host_status() != CURRENT_GET_HOST_INIT) + { + //LOG(DEBUG,"gm_socket_get_host_by_name socket not init."); + return GM_NOT_INIT; + } + + item->send_time = util_clock(); + socket->excuted_get_host=1; + current_get_host_start(socket); + + GM_GetHostByName(socket->addr, s_account_id, &result); + LOG(INFO,"clock(%d) gm_socket_get_host_by_name socket->addr(%s) result(%d).", + util_clock(), socket->addr, result); + return GM_SUCCESS; +} + + +GM_ERRCODE gm_is_valid_ip(const u8*data) +{ + if ((data[0]==0) && (data[1]==0) + && (data[2]==0) && (data[3]==0)) + { + return GM_PARAM_ERROR; + } + + if ((data[0]==255) && (data[1]==255) + && (data[2]==255) && (data[3]==255)) + { + return GM_PARAM_ERROR; + } + + return GM_SUCCESS; +} + + + +void gm_socket_connect_ok(SocketType *socket) +{ + switch(socket->access_id) + { + case SOCKET_INDEX_MAIN: + gps_service_connection_ok(); + break; + case SOCKET_INDEX_EPO: //SOCKET_INDEX_AGPS + // udp not need callback + agps_service_connection_ok(); + break; + case SOCKET_INDEX_LOG: + log_service_connection_ok(); + break; + case SOCKET_INDEX_UPDATE: + update_service_connection_ok(); + break; + case SOCKET_INDEX_UPDATE_FILE: + update_filemod_connection_ok(); + break; + case SOCKET_INDEX_CONFIG: + config_service_connection_ok(); + break; + } +} + +void gm_socket_close_for_reconnect(SocketType *socket) +{ + switch(socket->access_id) + { + case SOCKET_INDEX_MAIN: + gps_service_close_for_reconnect(); + break; + case SOCKET_INDEX_EPO: //SOCKET_INDEX_AGPS + // udp not need callback + agps_service_close_for_reconnect(); + break; + case SOCKET_INDEX_LOG: + log_service_close_for_reconnect(); + break; + case SOCKET_INDEX_UPDATE: + update_service_finish(UPDATE_PING_TIME); + break; + case SOCKET_INDEX_UPDATE_FILE: + update_filemod_close_for_reconnect(); + break; + case SOCKET_INDEX_CONFIG: + config_service_close_for_reconnect(); + break; + } +} + + +static void gm_socket_connect_failed(SocketType *socket) +{ + /* different socket have different dealing + gps_service retry N times should reinit gprs + other services ignore failue */ + switch(socket->access_id) + { + case SOCKET_INDEX_MAIN: + gps_service_connection_failed(); + break; + case SOCKET_INDEX_EPO: //SOCKET_INDEX_AGPS + agps_service_connection_failed(); + break; + case SOCKET_INDEX_LOG: + log_service_connection_failed(); + break; + case SOCKET_INDEX_UPDATE: + update_service_connection_failed(); + break; + case SOCKET_INDEX_UPDATE_FILE: + update_filemod_connection_failed(); + break; + case SOCKET_INDEX_CONFIG: + config_service_connection_failed(); + break; + } +} + +GM_ERRCODE gm_socket_connect(SocketType *socket) +{ + char ip_addr[16]; + + if (socket->id >= 0) + { + return GM_SUCCESS; + } + + if(GM_SUCCESS != gm_is_valid_ip(socket->ip)) + { + LOG(INFO,"clock(%d) gm_socket_connect type(%d)(%d.%d.%d.%d:%d) ip not valid.", + util_clock(), socket->type, socket->ip[0], socket->ip[1], socket->ip[2], socket->ip[3], socket->port); + return GM_PARAM_ERROR; + } + + + socket->send_time = util_clock(); + socket->id = GM_SocketCreate(s_account_id, socket->type); + if (socket->id >= 0) + { + GM_snprintf(ip_addr, sizeof(ip_addr), "%d.%d.%d.%d", socket->ip[0], socket->ip[1], socket->ip[2], socket->ip[3]); + if (GM_SocketConnect(socket->id, ip_addr, socket->port, s_account_id, + socket->access_id, socket->type)) + { + if(socket->type == STREAM_TYPE_STREAM) + { + // wait call back + } + else if(socket->type == STREAM_TYPE_DGRAM) + { + LOG(INFO,"clock(%d) gm_socket_connect udp(%d.%d.%d.%d:%d) id(%d) access_id(%d) success.", + util_clock(), socket->ip[0], socket->ip[1], socket->ip[2], socket->ip[3], socket->port, socket->id, socket->access_id); + gm_socket_connect_ok(socket); + } + else + { + LOG(ERROR,"clock(%d) gm_socket_connect unknown type(%d)(%d.%d.%d.%d:%d).", + util_clock(), socket->type, socket->ip[0], socket->ip[1], socket->ip[2], socket->ip[3], socket->port); + return GM_UNKNOWN; + } + } + else + { + LOG(INFO,"clock(%d) gm_socket_connect type(%d)(%d.%d.%d.%d:%d) failed.", + util_clock(), socket->type, socket->ip[0], socket->ip[1], socket->ip[2], socket->ip[3], socket->port); + + gm_socket_connect_failed(socket); + return GM_UNKNOWN; + } + } + else + { + LOG(INFO,"clock(%d) gm_socket_connect type(%d)(%d.%d.%d.%d:%d) create failed.", + util_clock(), socket->type, socket->ip[0], socket->ip[1], socket->ip[2], socket->ip[3], socket->port); + return GM_UNKNOWN; + } + + return GM_SUCCESS; +} + + + +GM_ERRCODE gm_socket_send(SocketType *socket, u8 *data, u16 len) +{ + s32 ret; + + if(socket->status <= SOCKET_STATUS_CONNECTING || socket->status >= SOCKET_STATUS_DATA_FINISH) + { + LOG(ERROR,"clock(%d) gm_socket_send status(%d) error. type(%d)(%d.%d.%d.%d:%d) id(%d) len(%d).", + util_clock(), socket->status, socket->type, socket->ip[0], socket->ip[1], socket->ip[2], socket->ip[3], + socket->port,socket->id ,len); + return GM_ERROR_STATUS; + } + + if(len > MAX_SOCKET_SEND_MSG_LEN) + { + LOG(ERROR,"clock(%d) gm_socket_send type(%d)(%d.%d.%d.%d:%d) id(%d) len(%d) too long.", + util_clock(), socket->type, socket->ip[0], socket->ip[1], socket->ip[2], socket->ip[3], + socket->port,socket->id,len); + return GM_PARAM_ERROR; + } + if(len <= 0) + { + return GM_PARAM_ERROR; + } + + //发一部分的没有出现过,发送失败会返回负数 + gm_socket_get_ackseq(socket, &socket->last_ack_seq); + ret = GM_SocketSend(socket->id, (char *)data, len); + if (ret != len) + { + LOG(INFO,"clock(%d) gm_socket_send type(%d)(%d.%d.%d.%d:%d) id(%d) ret(%d)!=len(%d).", + util_clock(), socket->type, socket->ip[0], socket->ip[1], socket->ip[2], socket->ip[3], + socket->port,socket->id,ret,len); + + return GM_UNKNOWN; + } + + return GM_SUCCESS; + +} + + + +GM_ERRCODE gm_socket_recv(SocketType *socket) +{ + char *recv_buff = NULL; + int recvlen=0; + GM_ERRCODE ret; + + if(socket->status <= SOCKET_STATUS_CONNECTING || socket->status >= SOCKET_STATUS_DATA_FINISH) + { + LOG(ERROR,"clock(%d) gm_socket_recv status(%d) error. type(%d)(%d.%d.%d.%d:%d) id(%d).", + util_clock(), socket->status, socket->type, socket->ip[0], socket->ip[1], socket->ip[2], socket->ip[3], + socket->port,socket->id); + return GM_ERROR_STATUS; + } + + recv_buff = GM_MemoryAlloc(MAX_SOCKET_RECV_MSG_LEN); + if (NULL == recv_buff) + { + LOG(ERROR,"clock(%d) gm_socket_recv type(%d)(%d.%d.%d.%d:%d) id(%d) memory not enough.", + util_clock(), socket->type, socket->ip[0], socket->ip[1], socket->ip[2], socket->ip[3], + socket->port,socket->id); + return GM_MEM_NOT_ENOUGH; + } + + do + { + GM_memset(recv_buff, 0x00, MAX_SOCKET_RECV_MSG_LEN); + recvlen = GM_SocketRecv(socket->id, recv_buff, MAX_SOCKET_RECV_MSG_LEN); + if(recvlen > 0) + { + LOG(DEBUG,"clock(%d) gm_socket_recv type(%d)(%d.%d.%d.%d:%d) id(%d) recvlen(%d).", + util_clock(), socket->type, socket->ip[0], socket->ip[1], socket->ip[2], socket->ip[3], + socket->port,socket->id,recvlen); + } + + if (recvlen > 0) + { + gps_service_confirm_gps_cache(socket); + + ret = fifo_insert(&socket->fifo, (u8 *)recv_buff, recvlen); + if(ret != GM_SUCCESS) + { + LOG(ERROR,"clock(%d) fifo insert failed, return(%d)", util_clock(), ret ); + if(socket->access_id != SOCKET_INDEX_UPDATE) //update_service 会重发 + { + //socket need rebuild. + fifo_reset(&socket->fifo); + if(socket->access_id == SOCKET_INDEX_MAIN) + { + char reason[30]; + snprintf(reason,sizeof(reason),"fifo_insert return %d", ret); + reason[sizeof(reason) - 1] = 0; + system_state_set_gpss_reboot_reason(reason); + } + gm_socket_close_for_reconnect(socket); + GM_MemoryFree(recv_buff); + recv_buff = NULL; + return GM_MEM_NOT_ENOUGH; + } + } + } + }while(recvlen > 0); + + GM_MemoryFree(recv_buff); + recv_buff = NULL; + + if(recvlen != -2) //SOC_WOULDBLOCK + { + if(socket->access_id == SOCKET_INDEX_MAIN) + { + char reason[30]; + snprintf(reason,sizeof(reason),"socket recv %d", recvlen); + reason[sizeof(reason) - 1] = 0; + system_state_set_gpss_reboot_reason(reason); + } + gm_socket_close_for_reconnect(socket); + } + + return GM_SUCCESS; +} + + +const char * gm_socket_status_string(SocketStatus statu) +{ + return s_socket_status_string[statu]; +} + +GM_ERRCODE gm_socket_get_ackseq(SocketType *socket, u32 *ack_seq) +{ + u8 buff[20]; + + buff[0] = socket->id; + buff[4] = buff[3] = buff[2] = buff[1] = 0; + GM_GetTcpStatus(buff); + (*ack_seq) = MKDWORD(buff[4], buff[3], buff[2], buff[1]); + + return GM_SUCCESS; +} + + + +void gm_socket_get_host_by_name_trigger(SocketType *socket) +{ + if(socket->addr[0]) + { + s_get_host_list[socket->access_id].requested = true; + } +} + +/* + 循环处理所有的get_host_by_name请求 +*/ +void gm_socket_get_host_timer_proc(void) +{ + int i = 0; + SocketType * socket = NULL; + + for(i = 0; i < SOCKET_INDEX_MAX; ++i) + { + if(s_get_host_list[i].requested) + { + break; + } + } + + + if(i >= SOCKET_INDEX_MAX) + { + // no need get host + return; + } + + + socket = get_socket_by_accessid(i); + if(!socket) + { + s_get_host_list[i].requested = false; + LOG(ERROR,"clock(%d) gm_socket_get_host_timer_proc assert(socket_idx(%d)) failed.", util_clock(), i ); + return; + } + + if(current_get_host.socket) + { + u32 current_time = util_clock(); + bool same_as_current_get_host = false; + int current_idx = current_get_host.socket->access_id; + if(gm_socket_same_as_current_get_host(socket)) + { + same_as_current_get_host = true; + } + + //或者成功, 或者失败,或者超时 + if((gm_socket_current_get_host_status() == CURRENT_GET_HOST_SUCCESS) || + (gm_socket_current_get_host_status() == CURRENT_GET_HOST_FAILED)) + { + // 释放资源,后面去抢 + s_get_host_list[current_idx].requested = false; + s_get_host_list[current_idx].fail_count = 0; + s_get_host_list[current_idx].send_time = 0; + current_get_host_init(); + if(same_as_current_get_host) return; + } + else if((current_time - s_get_host_list[current_idx].send_time) > GET_HOST_TIME_OUT) + { + s_get_host_list[current_idx].fail_count ++; + current_get_host_init(); //clear ,后面 竞争 + + if(s_get_host_list[current_idx].fail_count >= MAX_GET_HOST_REPEAT) + { + s_get_host_list[current_idx].requested = false; + s_get_host_list[current_idx].fail_count = 0; + s_get_host_list[current_idx].send_time = 0; + if(same_as_current_get_host) return; + } + } + else + { + //正在执行, 未超时 + return; + } + } + + if(GM_SUCCESS == gm_socket_get_host_by_name(socket, &s_get_host_list[i])) + { + LOG(DEBUG,"clock(%d) gm_socket_get_host_timer_proc start dns(%s).", util_clock(), socket->addr ); + //do nothing. wait callback + } + // else do nothing . + + +} + diff --git a/src/system_state.c b/src/system_state.c new file mode 100644 index 0000000..201ccfb --- /dev/null +++ b/src/system_state.c @@ -0,0 +1,1276 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: system_state.c + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-12 + * Description: 全局系统状态管理 + * Others: + * Function List: + 1. + + * History: + 1. Date: 2019-03-12 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#pragma diag_suppress 870 + +#include +#include +#include +#include "system_state.h" +#include "utility.h" +#include "applied_math.h" +#include "config_service.h" +#include "log_service.h" +#include "gprs.h" +#include "gps_service.h" +#include "socket.h" + + +#define GPS_ON_TIME_SECONDS (5*SECONDS_PER_MIN) +#define SYSTEM_STATE_FILE L"Z:\\goome\\GmStatusFile\0" + +#define SYSTEM_STATE_MAGIC_NUMBER 0xFEFEFEFE + +//4字节对齐,crc会占用4个字节 +//8769D311FEFEFEFE3A000000FF00010001000000000000000000000000000100000000002A0000000000000000000000600000000000000065110301119863002A00000001000000 +typedef struct +{ + //16比特CRC(不包含前2个字段,从status_bits开始算起) + U16 crc; + + //特征值 + U32 magic; + + /********************************************************************** + bit0 ——启动类型:0-重启,1——上电 + bit1 ——上电后是否已上传过GPS定位 + bit2 ——是否已发送静止点 + bit3 ——修改IP后是否已上传GPS数据 + bit4 ——充电是否开启(软件控制) + bit5 ——ACC检测模式:0——震动检测; 1——ACC线检测 + bit6 ——设备relay端口状态: 0——低电平(恢复油电); 1——高电平(断油电) + bit7 ——用户设置relay端口状态:0——低电平(恢复油电); 1——高电平(断油电) + bit8 ——设防状态 + bit9 ——上电后是否已上传过LBS定位 + bit10——是否冷启动 + bit11——备用 + bit12——备用 + bit13——备用 + bit14——备用 + bit15——备用 + + bit16——断电报警, + bit17——电池低电报警 + bit18——电源电压过低报警 + bit19——震动报警 + bit20——超速报警 + bit21——伪基站报警 + bit22——电源电压过高报警 + bit23——碰撞报警 + bit24——急加速报警 + bit25——急减速报警 + bit26——翻车报警 + bit27——急转弯报警 + bit28——拆动报警 + bit29——车辆移动报警 + bit30——备用 + bit31——备用 + **********************************************************************/ + U32 status_bits; + + BootReason boot_reason; + + //系统状态(工作,休眠) + SystemWorkState work_state; + + //车辆状态(运动,静止) + VehicleState vehicle_state; + + //重启总次数 + U32 reboot_count; + + //上电重启次数 + U32 reboot_for_power_on_counts; + + //断网重启次数 + U16 reboot_for_net_counts; + + //不定位重启次数 + U16 reboot_for_gps_counts; + + //升级重启次数 + U16 reboot_for_upgrade_counts; + + //指令重启次数 + U16 reboot_for_command_counts; + + //意外重启 + U16 reboot_for_exception_counts; + + //修复重启 + U16 reboot_for_checkpara_counts; + + //其它重启 + U16 reboot_for_other_counts; + + //启用时间 + U32 start_time; + + //高电压报警次数 + U32 power_high_voltage_count; + + //电池低电压报警次数 + U32 battery_low_voltage_count; + + //外部电池电压等级 + U8 extern_battery_voltage_grade; + + //历程(单位:公里) + U32 mileage; + + //当前可执行文件的校验合 + U32 check_sum; + + GSensorType gsensor_type; + + u32 last_good_time; // 上次网络正常的时间 + u32 call_ok_count; //CURRENT_GPRS_INIT->CURRENT_GPRS_CALL_OK 次数 + + char gpss_reboot_reason[30]; /*recent gps_service disconnect reason*/ + + GPSData latest_gps; + + u8 ip_cache[SOCKET_INDEX_MAX][4]; +}SystemState,*PSystemState; + + + +static SystemState s_system_state; + +static void init_para(void); + +static GM_ERRCODE read_state_from_file(void); + +static GM_ERRCODE save_state_to_file(void); + +GM_ERRCODE system_state_create(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + init_para(); + ret = read_state_from_file(); + return ret; +} + +void system_state_set_last_gps(const GPSData *p_gps) +{ + GM_memcpy(&s_system_state.latest_gps, p_gps, sizeof(s_system_state.latest_gps)); + LOG(DEBUG,"clock(%d) system_state_set_last_gps %f,%f.", util_clock(), p_gps->lng,p_gps->lat); +} + +void system_state_get_last_gps(GPSData *p_gps) +{ + GM_memcpy(p_gps, &s_system_state.latest_gps, sizeof(s_system_state.latest_gps)); + LOG(DEBUG,"clock(%d) system_state_get_last_gps %f,%f.", util_clock(), p_gps->lng,p_gps->lat); +} + + + +static void init_para(void) +{ + char *addr = NULL; + s_system_state.magic = SYSTEM_STATE_MAGIC_NUMBER; + s_system_state.status_bits = 0; + s_system_state.boot_reason = GM_RREBOOT_UNKNOWN; + s_system_state.work_state = GM_SYSTEM_STATE_WORK; + s_system_state.vehicle_state = VEHICLE_STATE_RUN; + + s_system_state.reboot_count = 0; + s_system_state.reboot_for_power_on_counts = 0; + s_system_state.reboot_for_net_counts = 0; + s_system_state.reboot_for_gps_counts = 0; + s_system_state.reboot_for_upgrade_counts = 0; + s_system_state.reboot_for_command_counts = 0; + s_system_state.reboot_for_exception_counts = 0; + s_system_state.reboot_for_other_counts = 0; + s_system_state.reboot_for_checkpara_counts = 0; + s_system_state.start_time = 0; + s_system_state.power_high_voltage_count = 0; + s_system_state.battery_low_voltage_count = 0; + s_system_state.extern_battery_voltage_grade = 0; + s_system_state.mileage = 0; + s_system_state.gsensor_type = GSENSOR_TYPE_UNKNOWN; + s_system_state.last_good_time = 0; + s_system_state.call_ok_count = 0; + s_system_state.gpss_reboot_reason[0] = 0; + + GM_memset(&s_system_state.latest_gps, 0, sizeof(s_system_state.latest_gps)); + GM_memset(s_system_state.ip_cache, 0, sizeof(s_system_state.ip_cache)); + + + addr = config_service_get_pointer(CFG_SERVERADDR); + if (GM_strstr(addr, GOOME_GPSOO_DNS) > 0) + { + GM_ConvertIpAddr(CONFIG_GOOCAR_SERVER_IP,s_system_state.ip_cache[SOCKET_INDEX_MAIN]); + } + + if (GM_strstr(addr, GOOME_LITEDEV_DNS) > 0) + { + GM_ConvertIpAddr(CONFIG_LITE_SERVER_IP,s_system_state.ip_cache[SOCKET_INDEX_MAIN]); + } + + GM_ConvertIpAddr(CONFIG_AGPS_SERVER_IP,s_system_state.ip_cache[SOCKET_INDEX_AGPS]); + GM_ConvertIpAddr(CONFIG_LOG_SERVER_IP,s_system_state.ip_cache[SOCKET_INDEX_LOG]); + GM_ConvertIpAddr(GOOME_UPDATE_SERVER_IP,s_system_state.ip_cache[SOCKET_INDEX_UPDATE]); + GM_ConvertIpAddr(CONFIG_SERVER_IP,s_system_state.ip_cache[SOCKET_INDEX_CONFIG]); + +} + +GM_ERRCODE system_state_destroy(void) +{ + return GM_SUCCESS; +} + +GM_ERRCODE system_state_reset(void) +{ + init_para(); + LOG(INFO,"system_state_reset"); + return save_state_to_file(); +} + +GM_ERRCODE system_state_clear_reboot_count(void) +{ + s_system_state.reboot_count = 0; + s_system_state.reboot_for_power_on_counts = 0; + s_system_state.reboot_for_net_counts = 0; + s_system_state.reboot_for_gps_counts = 0; + s_system_state.reboot_for_upgrade_counts = 0; + s_system_state.reboot_for_command_counts = 0; + s_system_state.reboot_for_exception_counts = 0; + s_system_state.reboot_for_other_counts = 0; + s_system_state.reboot_for_checkpara_counts = 0; + LOG(INFO,"system_state_reset"); + return save_state_to_file(); +} + + + +GM_ERRCODE system_state_timer_proc(void) +{ + s_system_state.start_time++; + return GM_SUCCESS; +} + +U32 system_state_get_status_bits(void) +{ + return s_system_state.status_bits; +} + +U32 system_state_get_start_time() +{ + return s_system_state.start_time; +} + +BootReason system_state_get_boot_reason(bool add_counts) +{ + s_system_state.reboot_count++; + if(add_counts) + { + switch (s_system_state.boot_reason) + { + case GM_RREBOOT_UNKNOWN: + { + s_system_state.reboot_for_exception_counts++; + } + break; + + case GM_REBOOT_CMD: + { + s_system_state.reboot_for_command_counts++; + } + break; + + case GM_REBOOT_UPDATE: + { + s_system_state.reboot_for_upgrade_counts++; + } + break; + + case GM_REBOOT_POWER_ON: + { + s_system_state.reboot_for_power_on_counts++; + } + break; + + case GM_REBOOT_GPRS: + { + s_system_state.reboot_for_net_counts++; + } + break; + + case GM_REBOOT_GPS: + { + s_system_state.reboot_for_gps_counts++; + } + break; + + + case GM_REBOOT_CHECKPARA: + { + s_system_state.reboot_for_checkpara_counts++; + } + break; + + default: + { + s_system_state.reboot_for_other_counts++; + } + + break; + } + + LOG(INFO,"system_state_get_boot_reason"); + save_state_to_file(); + } + + return s_system_state.boot_reason; +} + +const char* system_state_get_boot_reason_str(BootReason reason) +{ + switch (reason) + { + case GM_RREBOOT_UNKNOWN: + return "意外重启"; + case GM_REBOOT_CMD: + return "指令重启"; + case GM_REBOOT_UPDATE: + return "升级重启"; + case GM_REBOOT_POWER_ON: + return "断电重启"; + case GM_REBOOT_GPRS: + return "断网重启"; + case GM_REBOOT_GPS: + return "不定位重启"; + case GM_REBOOT_CHECKPARA: + return "修复重启"; + default: + return "未知"; + } +} + + +GM_ERRCODE system_state_set_boot_reason(const BootReason boot_reason) +{ + if (GM_REBOOT_POWER_ON == boot_reason) + { + system_state_set_has_reported_gps_since_boot(false); + system_state_set_has_reported_lbs_since_boot(false); + system_state_set_has_reported_static_gps(false); + s_system_state.start_time = 0; + } + + s_system_state.boot_reason = boot_reason; + LOG(INFO,"system_state_set_boot_reason"); + return save_state_to_file(); +} + +U32 system_state_get_reboot_counts(const BootReason boot_reason) +{ + switch (boot_reason) + { + case GM_RREBOOT_UNKNOWN: + { + return s_system_state.reboot_for_exception_counts; + } + + case GM_REBOOT_CMD: + { + return s_system_state.reboot_for_command_counts; + } + + case GM_REBOOT_UPDATE: + { + return s_system_state.reboot_for_upgrade_counts; + } + + case GM_REBOOT_POWER_ON: + { + return s_system_state.reboot_for_power_on_counts; + } + + case GM_REBOOT_GPRS: + { + return s_system_state.reboot_for_net_counts; + } + + case GM_REBOOT_GPS: + { + return s_system_state.reboot_for_gps_counts; + } + + case GM_REBOOT_CHECKPARA: + { + return s_system_state.reboot_for_checkpara_counts; + } + + default: + { + return s_system_state.reboot_for_other_counts; + } + } +} + +SystemWorkState system_state_get_work_state(void) +{ + return s_system_state.work_state; +} + +GM_ERRCODE system_state_set_work_state(const SystemWorkState work_state) +{ + if(s_system_state.work_state != work_state) + { + s_system_state.work_state = work_state; + + //休眠或者唤醒,全部传感器报警状态清除,电压报警和其它状态不变 + s_system_state.status_bits &=0x0007ffff; + LOG(INFO,"system_state_set_work_state:%d",work_state); + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + return save_state_to_file(); + } + return GM_SUCCESS; +} + +GM_ERRCODE system_state_set_vehicle_state(const VehicleState vehicle_state) +{ + if(s_system_state.vehicle_state != vehicle_state) + { + LOG(INFO, "vehicle_state from %d to %d", s_system_state.vehicle_state,vehicle_state); + s_system_state.vehicle_state = vehicle_state; + + if (VEHICLE_STATE_STATIC == vehicle_state) + { + system_state_set_move_alarm(false); + } + else + { + return save_state_to_file(); + } + } + return GM_SUCCESS; +} + +VehicleState system_state_get_vehicle_state(void) +{ + return s_system_state.vehicle_state; +} + +static GM_ERRCODE read_state_from_file() +{ + U32 file_len = 0; + S32 file_handle = -1; + S32 ret = -1; + U16 crc = 0; + + + file_handle = GM_FS_Open(SYSTEM_STATE_FILE, GM_FS_READ_ONLY | GM_FS_ATTR_ARCHIVE | GM_FS_CREATE); + if (file_handle < 0) + { + LOG(ERROR,"Failed to open system state file[%d]", file_handle); + return GM_SYSTEM_ERROR; + } + + ret = GM_FS_Read(file_handle, (void *)&s_system_state, sizeof(s_system_state), &file_len); + if (ret < 0 || file_len != sizeof(s_system_state)) + { + LOG(ERROR,"Failed to read system state file[%d]", ret); + init_para(); + GM_FS_Close(file_handle); + return GM_SYSTEM_ERROR; + } + + GM_FS_Close(file_handle); + + if (s_system_state.magic != SYSTEM_STATE_MAGIC_NUMBER) + { + LOG(ERROR,"magic error:%x", s_system_state.magic); + init_para(); + return save_state_to_file(); + } + + crc = applied_math_calc_common_crc16((u8*)&s_system_state.status_bits, (sizeof(s_system_state) - 8)); + if (s_system_state.crc != crc) + { + LOG(ERROR,"crc error:%X,%X", s_system_state.crc,crc); + LOG_HEX((char*)&s_system_state, sizeof(s_system_state)); + init_para(); + return save_state_to_file(); + } + return GM_SUCCESS; +} + +static GM_ERRCODE save_state_to_file(void) +{ + U32 file_len = 0; + S32 file_handle = -1; + S32 ret = -1; + u32 old_last_good_time; + u32 old_call_ok_count; + + file_handle = GM_FS_Open(SYSTEM_STATE_FILE, GM_FS_READ_WRITE | GM_FS_ATTR_ARCHIVE | GM_FS_CREATE); + if (file_handle < 0) + { + LOG(ERROR,"Failed to open system state file[%d]", file_handle); + return GM_SYSTEM_ERROR; + } + + old_last_good_time = s_system_state.last_good_time; + old_call_ok_count = s_system_state.call_ok_count; + s_system_state.last_good_time = gprs_get_last_good_time(); + s_system_state.call_ok_count = gprs_get_call_ok_count(); + + s_system_state.crc = applied_math_calc_common_crc16((u8*)&s_system_state.status_bits, (sizeof(s_system_state) - 8)); + + ret = GM_FS_Write(file_handle, (void *)&s_system_state, sizeof(s_system_state), &file_len); + if (ret < 0 || file_len != sizeof(s_system_state)) + { + LOG(ERROR,"Failed to write system state file[%d]", ret); + GM_FS_Close(file_handle); + + s_system_state.last_good_time = old_last_good_time; + s_system_state.call_ok_count = old_call_ok_count; + return GM_SYSTEM_ERROR; + } + + GM_FS_Commit(file_handle); + GM_FS_Close(file_handle); + + s_system_state.last_good_time = old_last_good_time; + s_system_state.call_ok_count = old_call_ok_count; + return GM_SUCCESS; +} + +bool system_state_has_reported_gps_since_boot(void) +{ + return GET_BIT1(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_has_reported_gps_since_boot(bool state) +{ + if (state == system_state_has_reported_gps_since_boot()) + { + return GM_SUCCESS; + } + + if (state) + { + SET_BIT1(s_system_state.status_bits); + } + else + { + CLR_BIT1(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_has_reported_gps_since_boot"); + return save_state_to_file(); +} + +bool system_state_has_reported_static_gps(void) +{ + return GET_BIT2(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_has_reported_static_gps(bool state) +{ + if (state == system_state_has_reported_static_gps()) + { + return GM_SUCCESS; + } + + if (state) + { + SET_BIT2(s_system_state.status_bits); + } + else + { + CLR_BIT2(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_has_reported_static_gps"); + return save_state_to_file(); +} + +bool system_state_has_reported_gps_since_modify_ip(void) +{ + return GET_BIT3(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_reported_gps_since_modify_ip(bool state) +{ + if (state == system_state_has_reported_gps_since_modify_ip()) + { + return GM_SUCCESS; + } + + if (state) + { + SET_BIT3(s_system_state.status_bits); + } + else + { + CLR_BIT3(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_reported_gps_since_modify_ip"); + return save_state_to_file(); +} + + +bool system_state_get_has_started_charge(void) +{ + return GET_BIT4(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_has_started_charge(bool state) +{ + if (state == system_state_get_has_started_charge()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT4(s_system_state.status_bits); + } + else + { + CLR_BIT4(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_has_started_charge"); + //频繁变化,不保存到文件 + return GM_SUCCESS; +} + +bool system_state_get_acc_is_line_mode(void) +{ + return GET_BIT5(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_acc_is_line_mode(bool state) +{ + if (state == system_state_get_acc_is_line_mode()) + { + return GM_SUCCESS; + } + + if (state) + { + SET_BIT5(s_system_state.status_bits); + LOG(INFO,"ACC line is valid!"); + } + else + { + CLR_BIT5(s_system_state.status_bits); + LOG(INFO,"ACC line is invalid!"); + } + LOG(INFO,"system_state_set_acc_is_line_mode"); + return save_state_to_file(); +} + +bool system_state_get_device_relay_state(void) +{ + return GET_BIT6(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_device_relay_state(bool state) +{ + if (state == system_state_get_device_relay_state()) + { + return GM_SUCCESS; + } + + if (state) + { + SET_BIT6(s_system_state.status_bits); + } + else + { + CLR_BIT6(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_device_relay_state"); + return save_state_to_file(); +} + +bool system_state_get_user_relay_state(void) +{ + return GET_BIT7(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_user_relay_state(bool state) +{ + if (state == system_state_get_user_relay_state()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + if (state) + { + SET_BIT7(s_system_state.status_bits); + } + else + { + CLR_BIT7(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_user_relay_state"); + return save_state_to_file(); +} + +bool system_state_get_defence(void) +{ + return GET_BIT8(s_system_state.status_bits); +} +GM_ERRCODE system_state_set_defence(bool state) +{ + if (state == system_state_get_defence()) + { + return GM_SUCCESS; + } + + if (state) + { + SET_BIT8(s_system_state.status_bits); + } + else + { + CLR_BIT8(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_defence"); + return save_state_to_file(); +} + +bool system_state_has_reported_lbs_since_boot(void) +{ + return GET_BIT9(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_has_reported_lbs_since_boot(bool state) +{ + if (state == system_state_has_reported_lbs_since_boot()) + { + return GM_SUCCESS; + } + + if (state) + { + SET_BIT9(s_system_state.status_bits); + } + else + { + CLR_BIT9(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_has_reported_lbs_since_boot"); + return save_state_to_file(); +} + +bool system_state_is_cold_boot(void) +{ + return GET_BIT10(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_cold_boot(bool state) +{ + if (state == system_state_is_cold_boot()) + { + return GM_SUCCESS; + } + + if (state) + { + SET_BIT10(s_system_state.status_bits); + } + else + { + CLR_BIT10(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_cold_boot"); + return save_state_to_file(); +} + +U8 system_state_get_extern_battery_voltage_grade(void) +{ + return s_system_state.extern_battery_voltage_grade; +} + + +GM_ERRCODE system_state_set_extern_battery_voltage_grade(U8 voltage_grade) +{ + if (voltage_grade == s_system_state.extern_battery_voltage_grade) + { + return GM_SUCCESS; + } + else + { + s_system_state.extern_battery_voltage_grade = voltage_grade; + LOG(INFO,"system_state_set_extern_battery_voltage_grade"); + return save_state_to_file(); + } +} + +bool system_state_get_power_off_alarm(void) +{ + return GET_BIT16(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_power_off_alarm(bool state) +{ + if (state == system_state_get_power_off_alarm()) + { + return GM_SUCCESS; + } + + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT16(s_system_state.status_bits); + } + else + { + CLR_BIT16(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_power_off_alarm"); + return save_state_to_file(); +} + +bool system_state_get_battery_low_voltage_alarm(void) +{ + return GET_BIT17(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_battery_low_voltage_alarm(bool state) +{ + if (state == system_state_get_battery_low_voltage_alarm()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT17(s_system_state.status_bits); + s_system_state.battery_low_voltage_count++; + } + else + { + CLR_BIT17(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_battery_low_voltage_alarm"); + return save_state_to_file(); +} + +bool system_state_get_shake_alarm(void) +{ + return GET_BIT19(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_shake_alarm(bool state) +{ + if (state == system_state_get_shake_alarm()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT19(s_system_state.status_bits); + } + else + { + CLR_BIT19(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_shake_alarm"); + return save_state_to_file(); +} + +bool system_state_get_overspeed_alarm(void) +{ + return GET_BIT20(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_overspeed_alarm(bool state) +{ + if (state == system_state_get_overspeed_alarm()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT20(s_system_state.status_bits); + } + else + { + CLR_BIT20(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_overspeed_alarm"); + return save_state_to_file(); +} + +bool system_state_get_fakecell_alarm(void) +{ + return GET_BIT21(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_fakecell_alarm(bool state) +{ + if (state == system_state_get_fakecell_alarm()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT21(s_system_state.status_bits); + } + else + { + CLR_BIT21(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_fakecell_alarm"); + return save_state_to_file(); +} + +bool system_state_get_high_voltage_alarm(void) +{ + return GET_BIT22(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_high_voltage_alarm(bool state) +{ + if (state == system_state_get_high_voltage_alarm()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT22(s_system_state.status_bits); + } + else + { + CLR_BIT22(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_high_voltage_alarm"); + return save_state_to_file(); +} + + +bool system_state_get_collision_alarm(void) +{ + return GET_BIT23(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_collision_alarm(bool state) +{ + if (state == system_state_get_collision_alarm()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT23(s_system_state.status_bits); + } + else + { + CLR_BIT23(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_collision_alarm"); + return save_state_to_file(); +} + +bool system_state_get_speed_up_alarm(void) +{ + return GET_BIT24(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_speed_up_alarm(bool state) +{ + if (state == system_state_get_speed_up_alarm()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT24(s_system_state.status_bits); + } + else + { + CLR_BIT24(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_speed_up_alarm"); + return save_state_to_file(); +} + +bool system_state_get_speed_down_alarm(void) +{ + return GET_BIT25(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_speed_down_alarm(bool state) +{ + if (state == system_state_get_speed_down_alarm()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT25(s_system_state.status_bits); + } + else + { + CLR_BIT25(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_speed_down_alarm"); + return save_state_to_file(); +} + +bool system_state_get_turn_over_alarm(void) +{ + return GET_BIT26(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_turn_over_alarm(bool state) +{ + if (state == system_state_get_turn_over_alarm()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT26(s_system_state.status_bits); + } + else + { + CLR_BIT26(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_turn_over_alarm"); + return save_state_to_file(); +} + +bool system_state_get_sharp_turn_alarm(void) +{ + return GET_BIT27(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_sharp_turn_alarm(bool state) +{ + if (state == system_state_get_sharp_turn_alarm()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT27(s_system_state.status_bits); + } + else + { + CLR_BIT27(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_sharp_turn_alarm"); + return save_state_to_file(); +} + + +bool system_state_get_remove_alarm(void) +{ + return GET_BIT28(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_remove_alarm(bool state) +{ + if (state == system_state_get_remove_alarm()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT28(s_system_state.status_bits); + } + else + { + CLR_BIT28(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_remove_alarm"); + return save_state_to_file(); +} + + +bool system_state_get_move_alarm(void) +{ + return GET_BIT29(s_system_state.status_bits); +} + +GM_ERRCODE system_state_set_move_alarm(bool state) +{ + if (state == system_state_get_move_alarm()) + { + return GM_SUCCESS; + } + + //状态发生变化,触发一次心跳 + gps_service_heart_atonce(); + + if (state) + { + SET_BIT29(s_system_state.status_bits); + } + else + { + CLR_BIT29(s_system_state.status_bits); + } + LOG(INFO,"system_state_set_move_alarm"); + return save_state_to_file(); +} + +void system_state_set_mileage(U32 mileage) +{ + if (mileage == s_system_state.mileage) + { + return; + } + + s_system_state.mileage = mileage; + if (util_clock()%(10*SECONDS_PER_MIN) == 0) + { + save_state_to_file(); + } +} + +U32 system_state_get_mileage(void) +{ + return s_system_state.mileage; +} + +void system_state_set_bin_checksum(U32 check_sum) +{ + if (check_sum == s_system_state.check_sum) + { + return; + } + + else + { + s_system_state.check_sum = check_sum; + LOG(INFO,"system_state_set_bin_checksum"); + save_state_to_file(); + } +} + +U32 system_state_get_bin_checksum(void) +{ + return s_system_state.check_sum; +} + +void system_state_set_gsensor_type(GSensorType gsensor_type) +{ + if (gsensor_type == s_system_state.gsensor_type) + { + return; + } + + else + { + s_system_state.gsensor_type = gsensor_type; + LOG(INFO,"system_state_set_gsensor_type"); + save_state_to_file(); + } +} + +GSensorType system_state_get_gsensor_type(void) +{ + return s_system_state.gsensor_type; +} + +u32 system_state_get_last_good_time(void) +{ + return s_system_state.last_good_time; +} + +u32 system_state_get_call_ok_count(void) +{ + return s_system_state.call_ok_count; +} + +void system_state_set_gpss_reboot_reason(const char *reason) +{ + GM_snprintf(s_system_state.gpss_reboot_reason,sizeof(s_system_state.gpss_reboot_reason),"%s",reason); + s_system_state.gpss_reboot_reason[sizeof(s_system_state.gpss_reboot_reason) - 1] = 0; +} + +const char *system_state_get_gpss_reboot_reason(void) +{ + return s_system_state.gpss_reboot_reason; +} + +void system_state_set_ip_cache(U8 index,const U8* ip) +{ + GM_memcpy(s_system_state.ip_cache[index], ip, 4); + save_state_to_file(); +} + +void system_state_get_ip_cache(U8 index,U8* ip) +{ + GM_memcpy(ip, s_system_state.ip_cache[index], 4); +} + + diff --git a/src/uart.c b/src/uart.c new file mode 100644 index 0000000..2883cc2 --- /dev/null +++ b/src/uart.c @@ -0,0 +1,476 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: uart.c + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-06 + * Description: 串口配置管理、数据读写 + * Others: 接收到数据回调接收数据的模块,使用顺序:创建->注册回调函数->打开串口 + * Function List: + 1. 创建uart模块 + 2. 销毁uart模块 + 3. 定时处理入口 + 4. 注册回调函数 + 5. 打开串口 + 6. 关闭串口 + 7. 向串口写数据 + + * History: + 1. Date: 2019-03-06 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + + +#include +#include +#include +#include +#include +#include "uart.h" +#include "fifo.h" +#include "log_service.h" +#include "utility.h" +#include "nmea_protocol.h" +#include "gps.h" +#include "command.h" +#include "auto_test.h" +#include "bms.h" + +//每次串口接收数据内存大小 +#define GM_UART_RCV_BUFF_LEN 1024 + +//串口缓冲区内存大小 +#define GM_UART_RCV_FIFO_LEN 2048 + +typedef struct +{ + U32 baud_rate; + U16 no_data_to_reopen_time; + time_t last_rcv_time; + bool is_open; + char rcv_buff[GM_UART_RCV_BUFF_LEN]; + FifoType rcv_fifo; +}UARTPara; + +typedef struct +{ + bool inited; + UARTPara UARTParas[GM_UART_MAX]; +}UART,*PUART; + + +static UART g_uart; + +static void debug_port_on_receive(void* msg); + +static void gps_port_on_receive(void* msg); + +static void bms_port_on_receive(void* msg); + + + +/** + * Function: 创建uart模块 + * Description:创建uart模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: 使用前必须调用,否则调用其它接口返回失败错误码 + */ +GM_ERRCODE uart_create(void) +{ + U8 index = 0; + g_uart.inited = true; + + for (index = GM_UART_DEBUG; index < GM_UART_MAX; ++index) + { + g_uart.UARTParas[index].baud_rate = BAUD_RATE_HIGH; + g_uart.UARTParas[index].no_data_to_reopen_time = 0; + g_uart.UARTParas[index].last_rcv_time = 0; + g_uart.UARTParas[index].is_open = false; + fifo_init(&g_uart.UARTParas[index].rcv_fifo,GM_UART_RCV_FIFO_LEN); + } + + + GM_RegisterCallBack(GM_CB_UART1_RECEIVE, (U32)debug_port_on_receive); + GM_RegisterCallBack(GM_CB_UART2_RECEIVE, (U32)gps_port_on_receive); + GM_RegisterCallBack(GM_CB_UART3_RECEIVE, (U32)bms_port_on_receive); + + g_uart.inited = true; + + uart_open_port(GM_UART_DEBUG,BAUD_RATE_HIGH,0); + + return GM_SUCCESS; +} + +/** + * Function: 销毁uart模块 + * Description:销毁uart模块 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE uart_destroy(void) +{ + U8 index = 0; + + g_uart.inited = false; + + for (index = GM_UART_DEBUG; index < GM_UART_MAX; ++index) + { + g_uart.UARTParas[index].baud_rate = 115200; + g_uart.UARTParas[index].last_rcv_time = 0; + g_uart.UARTParas[index].is_open = false; + fifo_delete(&g_uart.UARTParas[index].rcv_fifo); + uart_close_port((UARTPort)index); + } + return GM_SUCCESS; +} + +/** + * Function: uart模块定时处理入口 + * Description:uart模块定时处理入口 + * Input: 无 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE uart_timer_proc(void) +{ + GM_ERRCODE ret = GM_SUCCESS; + U8 index = 0; + for (index = GM_UART_DEBUG; index < GM_UART_MAX; index++) + { + //检查GPS端口是否长时间收不到数据 + if (false == g_uart.UARTParas[index].is_open || 0 == g_uart.UARTParas[index].no_data_to_reopen_time) + { + //LOG(DEBUG,"port:%d,reopentime:%d",index,g_uart.UARTParas[index].no_data_to_reopen_time); + continue; + } + + //在规定的时间内未收到数据重新打开串口 + if(util_clock() - g_uart.UARTParas[index].last_rcv_time >= g_uart.UARTParas[index].no_data_to_reopen_time) + { + LOG(WARN,"Reopen UART:%d",index); + uart_close_port((UARTPort)index); + ret = uart_open_port((UARTPort)index, g_uart.UARTParas[index].baud_rate,g_uart.UARTParas[index].no_data_to_reopen_time); + if (GM_SUCCESS != ret) + { + LOG(ERROR,"Failed to open UART %d",index); + continue; + } + } + else + { + //LOG(DEBUG,"UART %d,receive time=%d",index,g_uart.UARTParas[index].last_rcv_time); + } + } + return GM_SUCCESS; +} + + +/** + * Function: 打开串口 + * Description:波特率只有特定的几个值(9600、115200等) + * Input: port:哪个串口;baud_rate:波特率 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE uart_open_port(const UARTPort port, const U32 baud_rate, const U16 no_data_to_reopen_time) +{ + S32 ret = 0; + if (false == g_uart.inited) + { + return GM_NOT_INIT; + } + + if (g_uart.UARTParas[port].is_open) + { + return GM_SUCCESS; + } + + g_uart.UARTParas[port].baud_rate = baud_rate; + ret = GM_UartOpen((Enum_SerialPort)port, baud_rate); + + if (1 == ret) + { + g_uart.UARTParas[port].baud_rate = baud_rate; + g_uart.UARTParas[port].no_data_to_reopen_time = no_data_to_reopen_time; + g_uart.UARTParas[port].last_rcv_time = util_clock(); + g_uart.UARTParas[port].is_open = true; + return GM_SUCCESS; + } + else + { + return GM_HARD_WARE_ERROR; + } +} + +/** + * Function: 关闭串口 + * Description:波特率只有特定的几个值(9600、115200等) + * Input: port:哪个串口 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE uart_close_port(const UARTPort port) +{ + if (false == g_uart.inited) + { + return GM_NOT_INIT; + } + + if(false == g_uart.UARTParas[port].is_open) + { + return GM_NOT_INIT; + } + + //关闭串口前要清理缓存 + GM_UartClrRxBuffer((Enum_SerialPort)port); + GM_UartClrTxBuffer((Enum_SerialPort)port); + + GM_UartClose((Enum_SerialPort)port); + + g_uart.UARTParas[port].last_rcv_time = 0; + g_uart.UARTParas[port].is_open = false; + + fifo_reset(&g_uart.UARTParas[port].rcv_fifo); + + if (GM_UART_DEBUG == port) + { + GM_GpioInit(GM_GPIO10, PINDIRECTION_OUT, PINLEVEL_LOW, PINPULLSEL_DISABLE); + GM_GpioInit(GM_GPIO11, PINDIRECTION_OUT, PINLEVEL_LOW, PINPULLSEL_DISABLE); + } + if (GM_UART_GPS == port) + { + GM_GpioInit(GM_GPIO12, PINDIRECTION_IN, PINLEVEL_LOW, PINPULLSEL_DISABLE); + GM_GpioInit(GM_GPIO17, PINDIRECTION_IN, PINLEVEL_LOW, PINPULLSEL_DISABLE); + } + return GM_SUCCESS; +} + + +/** + * Function: 向串口写数据 + * Description:同步操作 + * Input: port:哪个串口;p_data:数据指针;len——数据长度 + * Output: 无 + * Return: GM_SUCCESS——成功;其它错误码——失败 + * Others: + */ +GM_ERRCODE uart_write(const UARTPort port, const U8* p_data, const U16 len) +{ + s32 ret = -1; + if (false == g_uart.inited) + { + return GM_NOT_INIT; + } + + if (!g_uart.UARTParas[port].is_open) + { + GM_UartWrite((Enum_SerialPort)port, (U8*)"error len", GM_strlen("error len")); + return GM_NOT_INIT; + } + + if (len > 10*CMD_MAX_LEN) + { + return GM_PARAM_ERROR; + } + + ret = GM_UartWrite((Enum_SerialPort)port, (U8*)p_data, len); + if (ret <= 0) + { + uart_close_port(port); + uart_open_port(port, g_uart.UARTParas[port].baud_rate, g_uart.UARTParas[port].no_data_to_reopen_time); + return GM_HARD_WARE_ERROR; + } + else + { + return GM_SUCCESS; + } +} + +static void debug_port_on_receive(void* msg) +{ + S32 len = 0; + char cmd_rsp[CMD_MAX_LEN] = {0}; + + if (false == g_uart.UARTParas[GM_UART_DEBUG].is_open) + { + return; + } + + g_uart.UARTParas[GM_UART_DEBUG].last_rcv_time = util_clock(); + + do + { + GM_memset(g_uart.UARTParas[GM_UART_DEBUG].rcv_buff, 0, GM_UART_RCV_BUFF_LEN); + len = GM_UartRead((Enum_SerialPort)GM_UART_DEBUG, (U8*)g_uart.UARTParas[GM_UART_DEBUG].rcv_buff, GM_UART_RCV_BUFF_LEN); + if (len > 0) + { + command_on_receive_data(COMMAND_UART,g_uart.UARTParas[GM_UART_DEBUG].rcv_buff,len,cmd_rsp,NULL); + if (GM_SUCCESS != bms_msg_receive(g_uart.UARTParas[GM_UART_DEBUG].rcv_buff,len)) + { + //加结束符 + GM_snprintf(cmd_rsp + GM_strlen(cmd_rsp), (CMD_MAX_LEN - GM_strlen(cmd_rsp)), "\r\n"); + uart_write(GM_UART_DEBUG, (U8*)cmd_rsp, GM_strlen(cmd_rsp)); + } + } + else + { + break; + } + }while (len >= GM_UART_RCV_BUFF_LEN); + + return; +} + + +static void gps_port_on_receive(void* msg) +{ + U16 read_len = 0; + U16 sentence_len = 0; + GM_ERRCODE ret = GM_SUCCESS; + U16 head = 0; + + g_uart.UARTParas[GM_UART_GPS].last_rcv_time = util_clock(); + + do + { + read_len = 0; + GM_memset(g_uart.UARTParas[GM_UART_GPS].rcv_buff, 0, GM_UART_RCV_BUFF_LEN); + + read_len = GM_UartRead((Enum_SerialPort)GM_UART_GPS,(U8*)g_uart.UARTParas[GM_UART_GPS].rcv_buff,GM_UART_RCV_BUFF_LEN - 1); + if (read_len > 0 && read_len < GM_UART_RCV_BUFF_LEN) + { + //先插入到缓存中,因为可能不是一个完整的语句 + fifo_insert(&g_uart.UARTParas[GM_UART_GPS].rcv_fifo, (U8*)g_uart.UARTParas[GM_UART_GPS].rcv_buff, read_len); + //可能有多个语句 + do + { + //先看看前6个字节是什么?如果是TD_AGPS_SENTENCE_HEAD或者AT_APGS_SENTENCE_HEAD,则是二进制包 + GM_memset(g_uart.UARTParas[GM_UART_GPS].rcv_buff, 0, GM_UART_RCV_BUFF_LEN); + ret = fifo_peek(&g_uart.UARTParas[GM_UART_GPS].rcv_fifo, (U8*)g_uart.UARTParas[GM_UART_GPS].rcv_buff, 6); + + if (GM_SUCCESS != ret) + { + break; + } + else + { + U16 head_buff[3] = {0}; + GM_memcpy(head_buff, g_uart.UARTParas[GM_UART_GPS].rcv_buff, 6); + head = head_buff[0]; + if (head == TD_SENTENCE_HEAD) + { + //第0个U16是包头,第1个U16是命令字,第2个是长度,包头+校验 共8个字节 + sentence_len = head_buff[2] + 8; + GM_memset(g_uart.UARTParas[GM_UART_GPS].rcv_buff, 0, GM_UART_RCV_BUFF_LEN); + ret = fifo_peek(&g_uart.UARTParas[GM_UART_GPS].rcv_fifo, (U8*)g_uart.UARTParas[GM_UART_GPS].rcv_buff, sentence_len); + if (GM_SUCCESS != ret) + { + fifo_reset(&g_uart.UARTParas[GM_UART_GPS].rcv_fifo); + LOG(WARN, "Receive invalid data,reset fifo!,ret=%d", ret); + break; + } + else + { + fifo_pop_len(&g_uart.UARTParas[GM_UART_GPS].rcv_fifo, sentence_len); + LOG(DEBUG,"Receive TD BIN packet:"); + LOG_HEX(g_uart.UARTParas[GM_UART_GPS].rcv_buff,sentence_len); + } + } + else if (head == AT_SENTENCE_HEAD) + { + //第0个U16是起始字节,第1个U16是长度,第2个是ClassID和MessageID,,包头+校验(4个字节)共10个字节 + sentence_len = head_buff[1] + 10; + GM_memset(g_uart.UARTParas[GM_UART_GPS].rcv_buff, 0, GM_UART_RCV_BUFF_LEN); + ret = fifo_peek(&g_uart.UARTParas[GM_UART_GPS].rcv_fifo, (U8*)g_uart.UARTParas[GM_UART_GPS].rcv_buff, sentence_len); + if (GM_SUCCESS != ret) + { + fifo_reset(&g_uart.UARTParas[GM_UART_GPS].rcv_fifo); + LOG(WARN, "Receive invalid data,reset fifo!,ret=%d", ret); + break; + } + else + { + fifo_pop_len(&g_uart.UARTParas[GM_UART_GPS].rcv_fifo, sentence_len); + LOG(DEBUG,"Receive AT BIN packet:"); + LOG_HEX(g_uart.UARTParas[GM_UART_GPS].rcv_buff,sentence_len); + } + } + //不是二进制包,以'\n'为分隔取一行(一个语句) + else + { + sentence_len = GM_UART_RCV_BUFF_LEN; + GM_memset(g_uart.UARTParas[GM_UART_GPS].rcv_buff, 0, GM_UART_RCV_BUFF_LEN); + ret = fifo_peek_until(&g_uart.UARTParas[GM_UART_GPS].rcv_fifo, (U8*)g_uart.UARTParas[GM_UART_GPS].rcv_buff, &sentence_len, '\n'); + if (GM_SUCCESS != ret) + { + LOG(DEBUG,"Failed to peek_until data from FIFO."); + //fifo_reset(&g_uart.UARTParas[GM_UART_GPS].rcv_fifo); + LOG_HEX(g_uart.UARTParas[GM_UART_GPS].rcv_buff,sentence_len); + break; + } + else + { + LOG(DEBUG,g_uart.UARTParas[GM_UART_GPS].rcv_buff); + fifo_pop_len(&g_uart.UARTParas[GM_UART_GPS].rcv_fifo, sentence_len); + } + } + + gps_on_rcv_uart_data((char*)g_uart.UARTParas[GM_UART_GPS].rcv_buff, sentence_len); + } + }while (true); + } + else + { + break; + } + }while (read_len >= (GM_UART_RCV_BUFF_LEN - 1)); + return; +} + + + + +static void bms_port_on_receive(void* msg) +{ + S32 len = 0; + + if (false == g_uart.UARTParas[GM_UART_BMS].is_open) + { + return; + } + + g_uart.UARTParas[GM_UART_BMS].last_rcv_time = util_clock(); + + do + { + GM_memset(g_uart.UARTParas[GM_UART_BMS].rcv_buff, 0, GM_UART_RCV_BUFF_LEN); + len = GM_UartRead((Enum_SerialPort)GM_UART_BMS, (U8*)g_uart.UARTParas[GM_UART_BMS].rcv_buff, GM_UART_RCV_BUFF_LEN); + if (len > 0) + { + uart_write(GM_UART_DEBUG,"[RECV]:", sizeof("[RECV]:")-1); + bms_uart_receive_data(g_uart.UARTParas[GM_UART_BMS].rcv_buff,len,NULL,NULL); + } + else + { + break; + } + }while (len >= GM_UART_RCV_BUFF_LEN); + + return; +} + + + + diff --git a/src/update_file.c b/src/update_file.c new file mode 100644 index 0000000..99f75a2 --- /dev/null +++ b/src/update_file.c @@ -0,0 +1,1432 @@ +#include "update_file.h" +#include "update_service.h" +#include "config_service.h" +#include "log_service.h" +#include "gm_stdlib.h" +#include "gm_gprs.h" +#include "utility.h" +#include "gsm.h" +#include "gm_memory.h" +#include "gm_fs.h" +#include "hard_ware.h" +#include "gm_timer.h" +#include "system_state.h" + +static SocketType s_file_socket= {-1,"",SOCKET_STATUS_MAX,}; +static UpdateFileExtend s_file_extend; +static UpdateFileExtend s_file_extend_old; + +#define UPDATE_UPGRADE_STATE_FILE L"Z:\\goome\\GmUpState\0" + + +static GM_ERRCODE update_filemod_transfer_status(u8 new_status); +static void update_filemod_init_proc(void); +static void update_filemod_connecting_proc(void); +static void update_filemod_work_proc(void); + + +static void update_msg_parse_response(u8 *pdata, u16 len); +static void update_msg_parse_file_data(u8 *pdata, u16 len); +static void update_msg_parse_check_block_bits(u16 block); +static GM_ERRCODE update_msg_parse_one_block(u16 block, u8 *pdata, u16 data_len); + +static void update_msg_pack_result_report(u8 *pdata, u16 *idx, u16 len); + +static GM_ERRCODE update_filemod_file_open(void); +static GM_ERRCODE update_filemod_file_create(u32 fs_len, int *sys_error); +static GM_ERRCODE update_filemod_file_write(u32 fs_seek, u8* pdata, u32 len); +static GM_ERRCODE update_filemod_file_finish(void); + + +static bool is_update_file_extend_same(UpdateFileExtend *e1, UpdateFileExtend *e2); +static GM_ERRCODE update_filemod_state_file_load(void); +static GM_ERRCODE update_filemod_state_file_save(void); + + +static GM_ERRCODE update_filemod_transfer_status(u8 new_status) +{ + u8 old_status = (u8)s_file_socket.status; + GM_ERRCODE ret = GM_PARAM_ERROR; + switch(s_file_socket.status) + { + case SOCKET_STATUS_INIT: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_WORK: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_GET_HOST: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + break; + case SOCKET_STATUS_CONNECTING: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_CONNECTING: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_WORK: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_DATA_FINISH: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_ERROR: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + default: + break; + } + + + if(GM_SUCCESS == ret) + { + s_file_socket.status = new_status; + s_file_socket.status_fail_count = 0; + LOG(INFO,"clock(%d) update_filemod_transfer_status from %s to %s success", util_clock(), + gm_socket_status_string((SocketStatus)old_status), gm_socket_status_string((SocketStatus)new_status)); + } + else + { + LOG(INFO,"clock(%d) update_filemod_transfer_status from %s to %s failed", util_clock(), + gm_socket_status_string((SocketStatus)old_status), gm_socket_status_string((SocketStatus)new_status)); + } + + return ret; + +} + + +GM_ERRCODE update_filemod_create(void) +{ + u8 addr[2*GOOME_DNS_MAX_LENTH+1]; + u8 IP[4]; + u32 port = 0; + u8 idx = 0; + + s_file_socket.access_id = SOCKET_INDEX_UPDATE_FILE; + gm_socket_init(&s_file_socket); + + GM_memset(addr, 0x00, sizeof(addr)); + idx = GM_sscanf((const char *)config_service_get_pointer(CFG_UPDATEFILESERVER), "%[^:]:%d", addr, &port); + if (idx != 2) + { + LOG(WARN,"clock(%d) update_filemod_create assert(idx ==2) failed.", util_clock()); + return GM_PARAM_ERROR; + } + + if(GM_SUCCESS != GM_ConvertIpAddr(addr, IP)) + { + if(util_is_valid_dns(addr, GM_strlen((const char *)addr))) + { + gm_socket_set_addr(&s_file_socket, addr, GM_strlen((const char *)addr), port, config_service_update_socket_type()); + } + else + { + LOG(WARN,"clock(%d) update_filemod_create assert(dns(%s)) failed.", util_clock(), addr); + return GM_PARAM_ERROR; + } + } + else + { + gm_socket_set_ip_port(&s_file_socket, IP, port, config_service_update_socket_type()); + } + + LOG(WARN,"clock(%d) update_filemod_create access_id(%d) fifo(%p).", util_clock(), s_file_socket.access_id, &s_file_socket.fifo); + return GM_SUCCESS; +} + +GM_ERRCODE update_filemod_destroy(void) +{ + if(s_file_extend.use_new_socket) + { + if(s_file_socket.id >=0) + { + GM_SocketClose(s_file_socket.id); + s_file_socket.id=-1; + } + + //必须重新create + fifo_delete(&s_file_socket.fifo); + update_filemod_transfer_status(SOCKET_STATUS_ERROR); + } + + update_service_result_to_server(); + return GM_SUCCESS; +} + + +GM_ERRCODE update_filemod_timer_proc(void) +{ + if(!s_file_socket.fifo.base_addr) + { + return GM_SUCCESS; + } + + switch(s_file_socket.status) + { + case SOCKET_STATUS_INIT: + update_filemod_init_proc(); + break; + case SOCKET_STATUS_CONNECTING: + update_filemod_connecting_proc(); + break; + case SOCKET_STATUS_WORK: + update_filemod_work_proc(); + break; + // 没有 SOCKET_STATUS_ERROR 状态,因为进该状态就会调update_service_destroy + //case SOCKET_STATUS_ERROR: + //break; + default: + LOG(WARN,"clock(%d) update_filemod_timer_proc assert(s_file_socket.status(%d)) unknown.", util_clock(),s_file_socket.status); + return GM_ERROR_STATUS; + } + + return GM_SUCCESS; +} + + +static void update_filemod_init_proc(void) +{ + u8 IP[4]; + gm_socket_get_host_by_name_trigger(&s_file_socket); + system_state_get_ip_cache(SOCKET_INDEX_UPDATE_FILE, IP); + if(GM_SUCCESS == gm_is_valid_ip(IP)) + { + GM_memcpy( s_file_socket.ip , IP, sizeof(IP)); + update_filemod_transfer_status(SOCKET_STATUS_CONNECTING); + if(GM_SUCCESS == gm_socket_connect(&s_file_socket)) + { + } + // else do nothing . connecting_proc will deal. + } + else if((!s_file_socket.excuted_get_host) && (GM_SUCCESS == gm_is_valid_ip(s_file_socket.ip))) + { + update_filemod_transfer_status(SOCKET_STATUS_CONNECTING); + if(GM_SUCCESS == gm_socket_connect(&s_file_socket)) + { + } + // else do nothing . connecting_proc will deal. + } +} + +void update_filemod_connection_failed(void) +{ + if(s_file_socket.status_fail_count >= MAX_CONNECT_REPEAT) + { + // if excuted get_host transfer to error statu, else get_host. + if(s_file_socket.excuted_get_host || (s_file_socket.addr[0] == 0)) + { + s_file_extend.result = REPORT_RESULT_FAILED; + GM_strncpy((char *)s_file_extend.result_info, "connect to file server fail.", sizeof(s_file_extend.result_info)); + update_filemod_destroy(); + } + else + { + update_filemod_transfer_status(SOCKET_STATUS_INIT); + } + } + // else do nothing . wait connecting proc to deal. +} + +void update_filemod_connection_ok(void) +{ + update_filemod_transfer_status(SOCKET_STATUS_WORK); + + update_msg_start_data_block_request(&s_file_socket); +} + +void update_filemod_close_for_reconnect(void) +{ + update_filemod_destroy(); +} + + +static void update_filemod_connecting_proc(void) +{ + u32 current_time = util_clock(); + + if((current_time - s_file_socket.send_time) > CONNECT_TIME_OUT) + { + s_file_socket.status_fail_count ++; + update_filemod_connection_failed(); + + if(s_file_socket.status == SOCKET_STATUS_CONNECTING && + s_file_socket.status_fail_count < MAX_CONNECT_REPEAT) + { + if(GM_SUCCESS == gm_socket_connect(&s_file_socket)) + { + //do nothing. wait callback + } + } + + } +} + + +static void update_filemod_work_proc(void) +{ + u8 one_send = 1; + u32 current_time = util_clock(); + if((current_time - s_file_socket.send_time) > MESSAGE_TIME_OUT) + { + s_file_socket.status_fail_count ++; + one_send = (STREAM_TYPE_DGRAM == config_service_update_socket_type())? UPDATE_MAX_PACK_ONE_SEND: 1; + + if(s_file_socket.status_fail_count >= (MAX_MESSAGE_REPEAT * one_send)) + { + LOG(INFO,"clock(%d) update_filemod_work_proc failed:%d", util_clock(), s_file_socket.status_fail_count); + s_file_extend.result = REPORT_RESULT_FAILED; + GM_strncpy((char *)s_file_extend.result_info, "request blocks fail(filemod_work_proc).", sizeof(s_file_extend.result_info)); + update_filemod_destroy(); + } + else + { + update_msg_send_data_block_request(&s_file_socket); + } + } + + update_msg_receive(&s_file_socket); +} + + + + + + + + +void update_msg_pack_head(u8 *pdata, u16 *idx, u16 len) +{ + u8 imei[GM_IMEI_LEN + 1] = {0}; + GM_ERRCODE ret = GM_SUCCESS; + + if((*idx) + 13 > len) + { + LOG(WARN,"clock(%d) update_msg_pack_head assert(len(%d)) failed.", util_clock(), len); + return; + } + + pdata[(*idx)++] = PROTOCOL_HEADER_UPDATE; + pdata[(*idx)++] = PROTOCOL_HEADER_UPDATE; + (*idx) = (*idx) + 3; // id 1 , len 2 + + if(GM_SUCCESS != gsm_get_imei(imei)) + { + LOG(INFO,"clock(%d) update_msg_pack_head can not get imei, ret:%d.", util_clock(), ret); + } + + if (0 == GM_strlen((const char *)imei)) + { + GM_memset(imei, 0, sizeof(imei)); + } + + pdata[(*idx)++] = util_chr(imei[0]); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[1]), util_chr(imei[2])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[3]), util_chr(imei[4])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[5]), util_chr(imei[6])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[7]), util_chr(imei[8])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[9]), util_chr(imei[10])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[11]), util_chr(imei[12])); + pdata[(*idx)++] = MERGEBCD(util_chr(imei[13]), util_chr(imei[14])); + +} + + +void update_msg_pack_id_len(u8 *pdata, u8 id, u16 len) +{ + u16 idx = 0; + u8 checksum = 0; + u16 total = 0; + u16 len_send = 0; + + if(13 > len) + { + LOG(WARN,"clock(%d) update_msg_pack_id_len assert(len(%d)) failed.", util_clock(), len); + return; + } + + //len now is pointing checksum byte + total = 2 + len; + len_send = len - 5; + + pdata[2] = id; //id 1byte + pdata[3] = BHIGH_BYTE(len_send); //length 2bytes + pdata[4] = BLOW_BYTE(len_send); + + //from head to end_of_data + for(idx = 0; idx < len; ++ idx) + { + checksum ^= pdata[idx]; + } + + pdata[len] = checksum; // xor value. 1byte + + pdata[total - 1] = PROTOCOL_TAIL_UPDATE; //end +} + + + +void update_msg_pack_request(u8 *pdata, u16 *idx, u16 len) +{ + u16 copy_len = 0; + u16 copy_len_fix = 0; + u32 checksum = 0; + + if((*idx) + 51 + 2 > len) // aftter body(51 bytes), 1byte checksum, 1byte 0xD + { + LOG(WARN,"clock(%d) update_msg_pack_request assert(len(%d)) failed.", util_clock(), len); + return; + } + + + /*u8 custom_code[6]; //客户代码*/ + copy_len_fix = copy_len = 6; + GM_memset(pdata+(*idx),0, copy_len); + copy_len= (config_service_get_length(CFG_CUSTOM_CODE, TYPE_STRING) > copy_len)?copy_len: + config_service_get_length(CFG_CUSTOM_CODE, TYPE_STRING); + GM_memcpy(pdata+(*idx),config_service_get_pointer(CFG_CUSTOM_CODE),copy_len); + (*idx) += copy_len_fix; + + /*u8 terminal_type[5]; //终端型号ID*/ + copy_len_fix = copy_len = 5; + GM_memset(pdata+(*idx),0, copy_len); + copy_len= (config_service_get_length(CFG_TERM_MODEL, TYPE_STRING) > copy_len)?copy_len: + config_service_get_length(CFG_TERM_MODEL, TYPE_STRING); + GM_memcpy(pdata+(*idx),config_service_get_pointer(CFG_TERM_MODEL),copy_len); + (*idx) += copy_len_fix; + + + /*u8 termianl_version[20]; //终端当前版本号 */ + copy_len_fix = copy_len = 20; + GM_memset(pdata+(*idx),0, copy_len); + copy_len= (config_service_get_length(CFG_TERM_VERSION, TYPE_STRING) > copy_len)?copy_len: + config_service_get_length(CFG_TERM_VERSION, TYPE_STRING); + GM_memcpy(pdata+(*idx),config_service_get_pointer(CFG_TERM_VERSION),copy_len); + (*idx) += copy_len_fix; + + + /*u8 terminal_version_check[10]; //终端当前版本校验码 */ + copy_len_fix = copy_len = 10; + GM_memset(pdata+(*idx),0, copy_len); + checksum = update_filemod_get_checksum(UPDATE_TARGET_IMAGE); + LOG(INFO,"Bin file check sum:%4X",checksum); + util_long_to_asc(checksum, pdata+(*idx), 0); + (*idx) += copy_len_fix; + + + /*u8 terminal_boot_check[10]; //终端当前版本BOOT校验码 */ + copy_len_fix = copy_len = 10; + GM_memset(pdata+(*idx),0, copy_len); + copy_len= (config_service_get_length(CFG_TERM_BOOT_CHECK, TYPE_STRING) > copy_len)?copy_len: + config_service_get_length(CFG_TERM_BOOT_CHECK, TYPE_STRING); + GM_memcpy(pdata+(*idx),config_service_get_pointer(CFG_TERM_BOOT_CHECK),copy_len); + (*idx) += copy_len_fix; + +} + + +void update_msg_receive(SocketType *socket) +{ + u8 head[7]; + u32 len = sizeof(head); + u16 msg_len; + u8 *pdata; + static u32 packet_error_start = 0; + + /* + update协议 最短7 + 信息头(0x68 0x68) 2 协议号1 包长度2(下一字节至data_end) check2 0xD + */ + + if(GM_SUCCESS != fifo_peek(&socket->fifo, head, len)) + { + // no msg + return; + } + + msg_len = MKWORD(head[3], head[4]); + msg_len = msg_len + 7; + + if(msg_len > MAX_GPRS_MESSAGE_LEN) + { + LOG(WARN,"clock(%d) update_msg_receive assert(msg_len(%d)) failed.",util_clock(), msg_len); + //clear fifo and restart socket. + fifo_reset(&socket->fifo); + gm_socket_close_for_reconnect(socket); + return; + } + + pdata = GM_MemoryAlloc(msg_len); + if(pdata == NULL) + { + LOG(INFO,"clock(%d) update_msg_receive alloc buf failed. len:%d", util_clock(), msg_len); + + //clear fifo and restart socket. + fifo_reset(&socket->fifo); + gm_socket_close_for_reconnect(socket); + return; + } + + if(GM_SUCCESS != fifo_peek(&socket->fifo, pdata, msg_len)) + { + // GM_EMPTY_BUF + GM_MemoryFree(pdata); + + if(packet_error_start == 0) + { + LOG(DEBUG,"clock(%d) update_msg_receive get msg failed. len:%d", util_clock(), msg_len); + log_service_print_hex((const char*)head, sizeof(head)); + packet_error_start = util_clock(); + } + else + { + if((util_clock() - packet_error_start) > MAX_GPRS_PART_MESSAGE_TIMEOUT) + { + LOG(WARN,"clock(%d) update_msg_receive MAX_GPRS_PART_MESSAGE_TIMEOUT.",util_clock()); + //clear fifo and restart socket. + fifo_reset(&socket->fifo); + gm_socket_close_for_reconnect(socket); + packet_error_start = 0; + } + } + return; + } + fifo_pop_len(&socket->fifo, msg_len); + + LOG(DEBUG,"clock(%d) update_msg_receive msg len(%d)", util_clock(), msg_len); + + update_msg_parse(pdata, msg_len); + GM_MemoryFree(pdata); +} + + +static void update_msg_parse(u8 *pdata, u16 len) +{ + u8 checksum = 0; + u16 idx = 0; + + if(PROTOCOL_HEADER_UPDATE != pdata[0] || PROTOCOL_HEADER_UPDATE != pdata[1]) + { + LOG(WARN,"clock(%d) update_msg_parse assert(header(%02x %02x)) failed.", util_clock(), pdata[0],pdata[1]); + return; + } + if(PROTOCOL_TAIL_UPDATE != pdata[len-1] ) + { + LOG(WARN,"clock(%d) update_msg_parse assert(tail(%d)) failed.",util_clock(), pdata[len-1] ); + return; + } + + for(idx = 0; idx < (len-2); ++idx) + { + checksum ^= pdata[idx]; + } + + if(checksum != pdata[len-2]) + { + LOG(WARN,"clock(%d) update_msg_parse assert(xor(%d != %d)) failed.",util_clock(), checksum, pdata[len-2]); + return; + } + + //协议号 + switch(pdata[2]) + { + case PROTOCCOL_UPDATE_RESPONSE: + update_msg_parse_response(pdata,len); + break; + case PROTOCCOL_UPDATE_FILE_DATA: + update_msg_parse_file_data(pdata,len); + break; + default: + LOG(WARN,"clock(%d) update_msg_parse assert(msgid(%d)) failed.",util_clock(), pdata[2]); + break; + } + return; +} + + +static void update_msg_parse_response(u8 *pdata, u16 len) +{ + u8 req_result = 0; + u16 idx; + u8 addr[22]; //xxx.xxx.xxx.xxx:xxxxx + u32 ip; + u16 port; + + req_result = (ProtocolUpdateResultEnum)pdata[13]; + switch(req_result) + { + case UPDATE_NONE: + LOG(INFO,"clock(%d) update_msg_parse_response no need to update, try %dh later again.", util_clock(), UPDATE_PING_TIME/3600); + update_service_finish(UPDATE_PING_TIME); + break; + + case UPDATE_QUE: + LOG(DEBUG,"clock(%d) update_msg_parse_response queued to update, try %ds later again.", util_clock(), UPDATE_RETRY_TIME); + update_service_finish(UPDATE_RETRY_TIME); + break; + + case UPDATE_READY: + idx = 14; + port = MKWORD(pdata[idx+4] , pdata[idx+5]); + GM_snprintf((char *)addr, sizeof(addr),"%d.%d.%d.%d:%d\0",pdata[idx],pdata[idx+1],pdata[idx+2],pdata[idx+3],port); + ip =MKDWORD(pdata[idx],pdata[idx+1],pdata[idx+2],pdata[idx+3]); + idx += 6; + + //file information + s_file_extend.check_sum =MKDWORD(pdata[idx],pdata[idx+1],pdata[idx+2],pdata[idx+3]); + idx += 4; + s_file_extend.total_len =MKDWORD(pdata[idx],pdata[idx+1],pdata[idx+2],pdata[idx+3]); + idx += 4; + + LOG(INFO,"clock(%d) update_msg_parse_response file check_sum:0x%04X, len:%u.",util_clock(), s_file_extend.check_sum,s_file_extend.total_len); + GM_memcpy(s_file_extend.custom_code, &pdata[idx], 6); + s_file_extend.custom_code[6] = 0; + idx+=6; + + GM_memcpy(s_file_extend.model, &pdata[idx], 5); + s_file_extend.model[5] = 0; + idx += 5; + + GM_memcpy(s_file_extend.file_id, &pdata[idx], 8); + s_file_extend.file_id[8] = 0; + idx += 8; + + GM_memcpy(s_file_extend.task_id, &pdata[idx], 8); + s_file_extend.task_id[8] = 0; + idx += 8; + + if (GM_strcmp((const char *)s_file_extend.custom_code, (const char *)config_service_get_pointer(CFG_CUSTOM_CODE)) !=0) + { + LOG(INFO,"clock(%d) update_msg_parse_response compare custom_code(%s!=%s).", + util_clock(), s_file_extend.custom_code, config_service_get_pointer(CFG_CUSTOM_CODE)); + break; + } + + + if(ip !=0 || port != 0) + { + s_file_extend.use_new_socket = 1; + config_service_set(CFG_UPDATEFILESERVER, TYPE_STRING, addr, GM_strlen((const char *)addr)); + update_filemod_create(); + update_service_after_response(s_file_extend.use_new_socket , s_file_extend.total_len ); + } + else + { + s_file_extend.use_new_socket = 0; + update_service_after_response(s_file_extend.use_new_socket , s_file_extend.total_len); + } + + break; + } + return; +} + +static void update_msg_parse_file_data(u8 *pdata, u16 len) +{ + u16 current_idx = 0; //从s_file_extend.block_current计, 第 几个. [0-9] + u16 block_number; + u32 check_bit = 0x01; + GM_ERRCODE ret; + + block_number = MKWORD(pdata[13], pdata[14]); + if(block_number < s_file_extend.block_current) + { + // already dealed data + return; + } + current_idx = block_number - s_file_extend.block_current; + if(current_idx) check_bit = check_bit << current_idx; + if(check_bit & s_file_extend.block_status) + { + // already dealed data + return; + } + + /* + 2字节 1字节 2字节 8字节 N字节 1字节 1字节 + 包头 命令字 报文长度 终端ID 数据内容 校验 结束符 + 0x68 0x68 CMD LEN ID DATA CHK 0x0D + */ + ret = update_msg_parse_one_block(block_number, &pdata[15], len - 17); + LOG(INFO,"clock(%d) update_msg_parse_file_data update_msg_parse_one_block(%d/%d) ret(%d).", + util_clock(), block_number + 1,s_file_extend.total_blocks, ret); + + if(GM_SUCCESS == ret) + { + update_msg_parse_check_block_bits(block_number); + } + + return; +} + + + +static GM_ERRCODE update_msg_parse_one_block(u16 block, u8 *pdata, u16 data_len) +{ + int idx; + u32 fs_seek = 0; + + if(block == 0) + { + data_len = (data_len>UPD_RESERVER_LEN) ? (data_len-UPD_RESERVER_LEN) : data_len; + for (idx=0; idx len) + { + LOG(WARN,"clock(%d) update_msg_pack_file_request assert(len(%d)) failed.",util_clock(),len); + return; + } + + pdata[(*idx)++] = BHIGH_BYTE(s_file_extend.block_size); + pdata[(*idx)++] = BLOW_BYTE(s_file_extend.block_size); + + pdata[(*idx)++] = BHIGH_BYTE(current); + pdata[(*idx)++] = BLOW_BYTE(current); + GM_memcpy(&pdata[(*idx)], s_file_extend.file_id, 8); + (*idx) += 8; +} + +GM_ERRCODE update_msg_send_data_block_request(SocketType *socket) +{ + u8 buff[30]; + u16 len = sizeof(buff); + u16 idx = 0, idx_save = 0; //current place + u16 current_block = 0; //从0一直到 s_file_extend.total_blocks + u16 current_idx = 0; //从s_file_extend.block_current计, 第 几个. [0-9] + u32 check_bit = 0x01; + u8 one_send = 1; + + one_send = (STREAM_TYPE_DGRAM == config_service_update_socket_type())? UPDATE_MAX_PACK_ONE_SEND: 1; + update_msg_pack_head(buff, &idx, len); //13 bytes + idx_save = idx; // save idx + + for(current_block =s_file_extend.block_current,current_idx = 0; + current_block < s_file_extend.total_blocks && current_idx < one_send; + ++ current_block, ++ current_idx) + { + if(current_idx) check_bit =check_bit << current_idx; + if (s_file_extend.block_status & check_bit) + { + continue; + } + + idx = idx_save; // restore idx for each block + len = sizeof(buff); // restore len + + update_msg_pack_file_request(buff, &idx, len, current_block); //14 bytes + update_msg_pack_id_len(buff, PROTOCCOL_UPDATE_REQUEST_FILE, idx); + + len=idx+2; // 1byte checksum , 1byte 0xD + + LOG(DEBUG,"clock(%d) update_msg_send_data_block_request len(%d) current_block(%d).",util_clock(),len,current_block); + + if(GM_SUCCESS == gm_socket_send(socket, buff, len)) + { + socket->send_time = util_clock(); + } + else + { + s_file_extend.result = REPORT_RESULT_FAILED; + GM_strncpy((char *)s_file_extend.result_info, "request blocks fail(data_block_request).", sizeof(s_file_extend.result_info)); + update_filemod_destroy(); + return GM_SYSTEM_ERROR; + } + } + return GM_UNKNOWN; +} + + +void update_msg_start_data_block_request(SocketType *socket) +{ + GM_ERRCODE ret; + int sys_error; + bool bret = false; + + //init block status before sending messages. + s_file_extend.block_size = UPDATE_PAKET_MAX_LEN; + s_file_extend.block_status = 0; + s_file_extend.result = REPORT_RESULT_FAILED; + s_file_extend.result_info[0] = 0; + s_file_extend.block_current = 0; + + s_file_extend.total_blocks = s_file_extend.total_len / s_file_extend.block_size ; + if(s_file_extend.total_len % s_file_extend.block_size != 0) + { + s_file_extend.total_blocks += 1; + } + + LOG(DEBUG,"clock(%d) update_msg_start_data_block_request. use_new_socket(%d) check_sum(0x%04X) total_len(%d) " + "custom_code(%s) model(%s) file_id(%s) task_id(%s) total_blocks(%d) block_size(%d) block_current(%d) block_status(%d).", + util_clock(),s_file_extend.use_new_socket,s_file_extend.check_sum,s_file_extend.total_len,s_file_extend.custom_code,s_file_extend.model, + s_file_extend.file_id,s_file_extend.task_id,s_file_extend.total_blocks,s_file_extend.block_size, + s_file_extend.block_current,s_file_extend.block_status); + + + //从文件中读取上一次的s_file_extend, 与这次的比较, 如果相同, 就用上次的. 实现断点续传. + ret = update_filemod_state_file_load(); + if(GM_SUCCESS == ret) + { + bret = is_update_file_extend_same(&s_file_extend, &s_file_extend_old); + } + + if(UPD_RESERVER_LEN >= s_file_extend.total_len) + { + LOG(ERROR,"clock(%d) update_msg_start_data_block_request assert(total_len(%d)) failed.", util_clock(),s_file_extend.total_len); + return; + } + + if(!bret) + { + util_delete_file(UPDATE_UPGRADE_FILE); + + //create file for write. + ret = update_filemod_file_create(s_file_extend.total_len - UPD_RESERVER_LEN, &sys_error); + if(GM_SUCCESS != ret) + { + s_file_extend.result = REPORT_RESULT_FAILED; + GM_snprintf((char *)s_file_extend.result_info, sizeof(s_file_extend.result_info),"create file fail(!same).errcode=%d,%d", ret,sys_error); + update_filemod_destroy(); + return; + } + + s_file_extend.block_current = 0; + s_file_extend.block_status = 0; + LOG(DEBUG,"clock(%d) update_msg_start_data_block_request create new update file.", util_clock()); + + } + else + { + if(GM_SUCCESS != update_filemod_file_open()) + { + //打不开文件, 删除状态文件重新开始 + LOG(WARN,"clock(%d) update_msg_start_data_block_request open() failed, redo update.", util_clock()); + + util_delete_file(UPDATE_UPGRADE_STATE_FILE); + s_file_extend.block_current = 0; + s_file_extend.block_status = 0; + + util_delete_file(UPDATE_UPGRADE_FILE); + + //create file for write. + ret = update_filemod_file_create(s_file_extend.total_len - UPD_RESERVER_LEN, &sys_error); + if(GM_SUCCESS != ret) + { + s_file_extend.result = REPORT_RESULT_FAILED; + GM_snprintf((char *)s_file_extend.result_info, sizeof(s_file_extend.result_info),"create file fail(same).errcode=%d,%d", ret,sys_error); + update_filemod_destroy(); + return; + } + } + else + { + LOG(DEBUG,"clock(%d) update_msg_start_data_block_request use old update file start at(%d).", + util_clock(), s_file_extend.block_current); + } + } + + update_msg_send_data_block_request(socket); + return; +} + +static void update_msg_parse_check_block_bits(u16 block) +{ + u16 current_idx = 0; //从s_file_extend.block_current计, 第 几个. [0-9] + u32 check_bit = 0x01; + u8 one_send = 1; + + current_idx = block - s_file_extend.block_current; + if(current_idx) check_bit=check_bit << current_idx; + + s_file_extend.block_status = s_file_extend.block_status | check_bit; + one_send = (STREAM_TYPE_DGRAM == config_service_update_socket_type())? UPDATE_MAX_PACK_ONE_SEND: 1; + + for(current_idx = 0; current_idx < one_send; ++ current_idx) + { + check_bit = 0x01; + if(current_idx) check_bit=check_bit << current_idx; + if (!(s_file_extend.block_status & check_bit)) + { + return; + } + + // block_current==0, current_idx==0 means first block. + if((s_file_extend.block_current + current_idx + 1) >= s_file_extend.total_blocks) + { + // come to end block. + break; + } + } + + // here all bits is set, + s_file_extend.block_current += one_send; + if(s_file_extend.block_current >= s_file_extend.total_blocks) + { + s_file_extend.block_current = s_file_extend.total_blocks; + if(GM_SUCCESS != update_filemod_file_finish()) + { + s_file_extend.result = REPORT_RESULT_FINISH; + GM_strncpy((char *)s_file_extend.result_info, "check sum failed.",sizeof(s_file_extend.result_info)); + LOG(WARN,"clock(%d) update_msg_parse_check_block_bits assert(update_filemod_file_finish) failed.", util_clock()); + update_filemod_destroy(); + } + else + { + s_file_extend.result = REPORT_RESULT_UPDATED; + LOG(INFO,"clock(%d) update_msg_parse_check_block_bits update_filemod_file_finish success.", util_clock()); + update_filemod_destroy(); + } + + s_file_extend.block_status = 0; + } + else + { + s_file_extend.block_status = 0; + + LOG(INFO,"clock(%d) update_msg_parse_check_block_bits allok(%d) one_send(%d).", + util_clock(), s_file_extend.block_current, one_send); + + //写断点续传信息 + update_filemod_state_file_save(); + + //接着请求后续包 + update_service_after_blocks_finish(); + } +} + + + +static GM_ERRCODE update_filemod_file_finish(void) +{ + u32 check_sum=0; + + GM_FS_Close(s_file_extend.handle); + s_file_extend.handle = -1; + check_sum = update_filemod_get_checksum(UPDATE_UPGRADE_FILE); + + if(check_sum != s_file_extend.check_sum) + { + LOG(INFO,"clock(%d) check_sum(0x%04x) != (0x%04x).", util_clock(), check_sum,s_file_extend.check_sum); + return GM_UNKNOWN; + } + + s_file_extend.result = REPORT_RESULT_UPDATED; + + return GM_SUCCESS; +} + + + +static GM_ERRCODE update_filemod_file_write(u32 fs_seek, u8* pdata, u32 len) +{ + int fret; + u32 writen = 0; + + if(s_file_extend.handle < 0) + { + LOG(WARN,"clock(%d) update_filemod_file_write assert(handle(%d)) failed.", util_clock(), s_file_extend.handle); + return GM_SYSTEM_ERROR; + } + + fret = GM_FS_Seek(s_file_extend.handle, fs_seek, SEEK_SET); + if (fret < 0) + { + LOG(INFO,"clock(%d) update_filemod_file_write GM_FS_Seek failed, ret:%d.", util_clock(),fret); + GM_FS_Close(s_file_extend.handle); + s_file_extend.handle = -1; + return GM_SYSTEM_ERROR; + } + + fret = GM_FS_Write(s_file_extend.handle, (void *)pdata, len, &writen); + if (fret < 0 || writen != len) + { + LOG(INFO,"clock(%d) update_filemod_file_write GM_FS_Write failed. ret:%d, writen:%d.", util_clock(), fret, writen); + GM_FS_Close(s_file_extend.handle); + s_file_extend.handle = -1; + return GM_SYSTEM_ERROR; + } + LOG(DEBUG,"clock(%d) update_filemod_file_write seek(%d) len(%d).", util_clock(), fs_seek, len); + + return GM_SUCCESS; +} + +static GM_ERRCODE update_filemod_file_open(void) +{ + UINT file_size; + s_file_extend.handle = GM_FS_Open(UPDATE_UPGRADE_FILE, GM_FS_READ_WRITE | GM_FS_ATTR_ARCHIVE); + if (s_file_extend.handle >= 0) + { + GM_FS_GetFileSize(s_file_extend.handle, &file_size); + if(file_size != (s_file_extend.total_len - UPD_RESERVER_LEN)) + { + LOG(INFO,"clock(%d) update_filemod_file_open assert(filesize==%d) failed.", util_clock(),s_file_extend.total_len); + GM_FS_Close(s_file_extend.handle); + s_file_extend.handle = -1; + return GM_SYSTEM_ERROR; + } + return GM_SUCCESS; + } + + + return GM_NOT_INIT; +} + + +static GM_ERRCODE update_filemod_file_create(u32 fs_len, int *sys_error) +{ + int ret; + u8 byte[1024]; + u32 writen = 0; + u32 writen_total = 0; + u32 will_write = 0; + + *sys_error = 0; + if(s_file_extend.handle >= 0) + { + JsonObject* p_log_root = json_create(); + json_add_string(p_log_root, "event", "update_filemod_file_create need close"); + log_service_upload(INFO,p_log_root); + GM_FS_Close(s_file_extend.handle); + s_file_extend.handle = -1; + } + + s_file_extend.handle = GM_FS_Open(UPDATE_UPGRADE_FILE, GM_FS_READ_WRITE | GM_FS_ATTR_ARCHIVE | GM_FS_CREATE); + if (s_file_extend.handle < 0) + { + LOG(DEBUG,"clock(%d) update_filemod_file_create assert(GM_FS_Open) failed.", util_clock()); + *sys_error = s_file_extend.handle; + return GM_HARD_WARE_ERROR; + } + + GM_memset(byte, 0, sizeof(byte)); + + // 预先占用指定长度 + will_write = sizeof(byte); + while(writen_total != fs_len) + { + if((fs_len - writen_total) < will_write) + { + will_write = (fs_len - writen_total); + } + + ret = GM_FS_Write(s_file_extend.handle, (void *)byte, will_write, &writen); + if ((ret < 0) || (writen==0)) + { + LOG(DEBUG,"clock(%d) update_filemod_file_create assert(GM_FS_Write(ret:%d, writen:%d)) failed.", util_clock(), ret, writen); + GM_FS_Close(s_file_extend.handle); + s_file_extend.handle = -1; + *sys_error = s_file_extend.handle; + return GM_SYSTEM_ERROR; + } + writen_total += writen; + } + + return GM_SUCCESS; +} + + + +u32 update_filemod_get_checksum(const u16 *FileName) +{ + int fret = 0; + u32 retlen = 0; + u32 total_size = 0; + int handle = -1; + u8 buff[1024] = {0}; + u32 idx = 0; + u32 check_sum=0; + u32 read_total = 0; + + // 打开升级文件 + handle = GM_FS_Open(FileName, GM_FS_READ_WRITE | GM_FS_ATTR_ARCHIVE); + if (handle < 0) + { + LOG(DEBUG,"clock(%d) update_filemod_get_checksum assert(GM_FS_Open) failed. ret:%d", util_clock(), handle); + GM_FS_Close(handle); + return 0; + } + + // 获取文件长度 + GM_FS_GetFileSize(handle, &total_size); + + // 读取数据 + check_sum = 0x00; + while(read_total < total_size) + { + fret = GM_FS_Read(handle, (void *)&buff, sizeof(buff), &retlen); + if (fret != 0) + { + LOG(INFO,"clock(%d) update_filemod_get_checksum GM_FS_Read failed, ret:%d.", util_clock(), fret); + GM_FS_Close(handle); + return 0; + } + + read_total += retlen; + for (idx = 0; idx < retlen; idx++) + { + check_sum += buff[idx]; + } + } + + GM_FS_Close(handle); + + return check_sum; +} + + +static void update_msg_pack_result_report(u8 *pdata, u16 *idx, u16 len) +{ + if((*idx) + 12 + GM_strlen((const char *)s_file_extend.result_info) > len) + { + LOG(WARN,"clock(%d) update_msg_pack_file_request assert(len(%d)) failed.", util_clock(), len); + return; + } + + // task id + GM_memcpy(&pdata[(*idx)], s_file_extend.task_id, 8); + (*idx) += 8; + + // result + pdata[(*idx)++] = (u8)s_file_extend.result; + + //info len + pdata[(*idx)++] = GM_strlen((const char *)s_file_extend.result_info); + + // info + GM_memcpy(&pdata[(*idx)], s_file_extend.result_info, pdata[(*idx)-1]); + (*idx) += pdata[(*idx)-1]; +} + + + +GM_ERRCODE update_msg_send_result_to_server(SocketType *socket) +{ + GM_ERRCODE ret; + u8 buff[100]; + u16 len = sizeof(buff); + u16 idx = 0; //current place + + update_msg_pack_head(buff, &idx, len); //13 bytes + update_msg_pack_result_report(buff, &idx, len); //12+N bytes + update_msg_pack_id_len(buff, PROTOCCOL_UPDATE_REPORT, idx); + + len=idx+2; // 1byte checksum , 1byte 0xD + + LOG(DEBUG,"clock(%d) update_msg_send_result_to_server len(%d) result(%d).",util_clock(),len,s_file_extend.result); + + if(GM_SUCCESS == (ret = gm_socket_send(socket, buff, len))) + { + socket->send_time = util_clock(); + } + + //成功升级,重启 + if(REPORT_RESULT_UPDATED == s_file_extend.result) + { + //确保result发给了服务器 + hard_ware_reboot(GM_REBOOT_UPDATE, 5); + } + + if(REPORT_RESULT_FAILED != s_file_extend.result) + { + update_service_finish(UPDATE_PING_TIME); + } + else + { + static u32 s_fail_count = 0; + ++s_fail_count; + if(s_fail_count < 100) + { + //尽快重新update + update_service_finish(UPDATE_RETRY_TIME); + } + else + { + //失败太多次数了, 估计后面也是失败, 没必要增加服务器压力. + update_service_finish(UPDATE_PING_TIME); + } + } + + return ret; +} + + +UpdateFileExtend *get_file_extend(void) +{ + return &s_file_extend; +} + + +void init_file_extend(bool boot_init) +{ + if(!boot_init) + { + if(s_file_extend.handle >= 0) + { + GM_FS_Close(s_file_extend.handle); + } + } + GM_memset(&s_file_extend, 0, sizeof(s_file_extend)); + s_file_extend.handle = -1; +} + + +static bool is_update_file_extend_same(UpdateFileExtend *e1, UpdateFileExtend *e2) +{ + if(e1->block_size != e2->block_size) + { + return false; + } + + if(e1->total_blocks != e2->total_blocks) + { + return false; + } + + if(e1->check_sum != e2->check_sum) + { + return false; + } + + if(e1->total_len != e2->total_len) + { + return false; + } + + if(GM_strncmp((const char *)e1->custom_code,(const char *)e2->custom_code, sizeof(e1->custom_code))) + { + return false; + } + + if(GM_strncmp((const char *)e1->model,(const char *)e2->model, sizeof(e1->custom_code))) + { + return false; + } + + LOG(INFO,"clock(%d) is_update_file_extend_same same file start from:%d.", util_clock(), e2->block_current); + + //相同的情况下, 用旧的block_current + e1->block_current = e2->block_current; //当前包序号 + e1->block_status = e2->block_status; // 从低到高, 每一位代表从当前包开始,往后的回收情况,收到回包为1,未收到为0 + return true; +} + + + + +static GM_ERRCODE update_filemod_state_file_save(void) +{ + int handle; // file handle + int fret; + u32 writen = 0; + + int idx; + char *pbuf = (char *)&s_file_extend; + + // 由于要断点续传,所以收到的包要写到了文件系统中. + GM_FS_Commit(s_file_extend.handle); + + s_file_extend.state_sum = 0; + for (idx = 0; idx < (sizeof(s_file_extend)- sizeof(s_file_extend.state_sum)); idx++) + { + s_file_extend.state_sum += pbuf[idx]; + } + + handle = GM_FS_Open(UPDATE_UPGRADE_STATE_FILE, GM_FS_READ_WRITE | GM_FS_ATTR_ARCHIVE | GM_FS_CREATE); + if (handle < 0) + { + LOG(DEBUG,"clock(%d) update_filemod_state_file_save assert(GM_FS_Open) failed.", util_clock()); + return GM_HARD_WARE_ERROR; + } + + + fret = GM_FS_Write(handle, &s_file_extend, sizeof(s_file_extend), &writen); + if (fret < 0 || (writen != sizeof(s_file_extend))) + { + LOG(INFO,"clock(%d) update_filemod_state_file_save GM_FS_Write failed. ret:%d, writen:%d.", util_clock(), fret, writen); + GM_FS_Close(handle); + return GM_SYSTEM_ERROR; + } + LOG(INFO,"clock(%d) update_filemod_state_file_save.", util_clock()); + + GM_FS_Close(handle); + return GM_SUCCESS; +} + + +static GM_ERRCODE update_filemod_state_file_load(void) +{ + int handle; // file handle + int fret; + u32 readed = 0; + int idx; + char *pbuf; + u32 sum = 0; + + handle = GM_FS_Open(UPDATE_UPGRADE_STATE_FILE, GM_FS_READ_WRITE | GM_FS_ATTR_ARCHIVE); + if (handle < 0) + { + return GM_NOT_INIT; + } + + + fret = GM_FS_Read(handle, &s_file_extend_old, sizeof(s_file_extend_old), &readed); + if (fret < 0 || (readed != sizeof(s_file_extend_old))) + { + LOG(INFO,"clock(%d) update_filemod_state_file_load GM_FS_Read failed. ret:%d, writen:%d.", util_clock(), fret, readed); + GM_FS_Close(handle); + return GM_SYSTEM_ERROR; + } + + GM_FS_Close(handle); + + pbuf = (char *)&s_file_extend_old; + for (idx = 0; idx < (sizeof(s_file_extend_old)- sizeof(s_file_extend_old.state_sum)); idx++) + { + sum += pbuf[idx]; + } + + if(sum == s_file_extend_old.state_sum) + { + LOG(DEBUG,"clock(%d) update_filemod_state_file_load use_new_socket(%d) check_sum(%d) total_len(%d) " + "custom_code(%s) model(%s) file_id(%s) task_id(%s) total_blocks(%d) block_size(%d) block_current(%d) block_status(%d).", + util_clock(),s_file_extend_old.use_new_socket,s_file_extend_old.check_sum,s_file_extend_old.total_len,s_file_extend_old.custom_code,s_file_extend_old.model, + s_file_extend_old.file_id,s_file_extend_old.task_id,s_file_extend_old.total_blocks,s_file_extend_old.block_size, + s_file_extend_old.block_current,s_file_extend_old.block_status); + return GM_SUCCESS; + } + else + { + LOG(INFO,"clock(%d) update_filemod_state_file_load assert(sum) failed.", util_clock()); + return GM_NOT_INIT; + } +} + + diff --git a/src/update_service.c b/src/update_service.c new file mode 100644 index 0000000..13a4639 --- /dev/null +++ b/src/update_service.c @@ -0,0 +1,579 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: update_service.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-02-28 + * Description: 模块升级服务 + * Others: + * Function List: + 1. 创建 + 2. 销毁 + 3. + * History: + 1. Date: 2019-02-28 + Author: 王志华 + Modification: 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include "update_service.h" +#include "update_file.h" +#include "config_service.h" +#include "log_service.h" +#include "gm_stdlib.h" +#include "gm_gprs.h" +#include "utility.h" +#include "gm_fs.h" +#include "system_state.h" + +static SocketType s_update_socket= {-1,"",SOCKET_STATUS_MAX,}; + +typedef struct +{ + u8 getting_data; //是否正在请求数据文件 + u32 last_ok_time; //上一次执行升级检测的时间 + u32 wait; //执行升级检测的间隔 +}SocketTypeUpdateExtend; + +static SocketTypeUpdateExtend s_update_socket_extend; + +static GM_ERRCODE update_service_transfer_status(u8 new_status); +static void update_service_init_proc(void); +static void update_service_connecting_proc(void); +static void update_service_work_proc(void); +static void update_service_close(void); + + +static GM_ERRCODE update_msg_send_request(void); +static void update_service_data_finish_proc(void); + + + +static GM_ERRCODE update_service_transfer_status(u8 new_status) +{ + u8 old_status = (u8)s_update_socket.status; + GM_ERRCODE ret = GM_PARAM_ERROR; + switch(s_update_socket.status) + { + case SOCKET_STATUS_INIT: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_GET_HOST: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + break; + case SOCKET_STATUS_CONNECTING: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_CONNECTING: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_WORK: + switch(new_status) + { + case SOCKET_STATUS_INIT: + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_DATA_FINISH: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + case SOCKET_STATUS_ERROR: + switch(new_status) + { + case SOCKET_STATUS_INIT: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_GET_HOST: + ret = GM_SUCCESS; + break; + case SOCKET_STATUS_CONNECTING: + break; + case SOCKET_STATUS_WORK: + break; + case SOCKET_STATUS_DATA_FINISH: + break; + case SOCKET_STATUS_ERROR: + ret = GM_SUCCESS; + break; + default: + break; + } + break; + default: + break; + } + + + if(GM_SUCCESS == ret) + { + s_update_socket.status = new_status; + s_update_socket.status_fail_count = 0; + LOG(INFO,"clock(%d) update_service_transfer_status from %s to %s success", util_clock(), + gm_socket_status_string((SocketStatus)old_status), gm_socket_status_string((SocketStatus)new_status)); + } + else + { + LOG(INFO,"clock(%d) update_service_transfer_status from %s to %s failed", util_clock(), + gm_socket_status_string((SocketStatus)old_status), gm_socket_status_string((SocketStatus)new_status)); + } + + return ret; + +} + + +GM_ERRCODE update_service_create(bool first_create) +{ + u8 addr[2*GOOME_DNS_MAX_LENTH+1]; + u8 IP[4]; + u32 port = 0; + u8 idx = 0; + + if(!first_create) + { + if(s_update_socket.fifo.base_addr) + { + return GM_SUCCESS; + } + } + + s_update_socket.access_id = SOCKET_INDEX_UPDATE; + gm_socket_init(&s_update_socket); + + GM_memset(addr, 0x00, sizeof(addr)); + idx = GM_sscanf((const char *)config_service_get_pointer(CFG_UPDATESERVERADDR), "%[^:]:%d", addr, &port); + if (idx != 2) + { + LOG(WARN,"clock(%d) update_service_create assert(idx ==2) failed.", util_clock()); + return GM_PARAM_ERROR; + } + + if(GM_SUCCESS != GM_ConvertIpAddr(addr, IP)) + { + if(util_is_valid_dns(addr, GM_strlen((const char *)addr))) + { + gm_socket_set_addr(&s_update_socket, addr, GM_strlen((const char *)addr), port, config_service_update_socket_type()); + } + else + { + LOG(WARN,"clock(%d) update_service_create assert(dns(%s)) failed.", util_clock(), addr); + return GM_PARAM_ERROR; + } + } + else + { + gm_socket_set_ip_port(&s_update_socket, IP, port, config_service_update_socket_type()); + } + + s_update_socket_extend.getting_data = 0; + s_update_socket_extend.last_ok_time = 0; + s_update_socket_extend.wait = UPDATE_PING_TIME; + + LOG(INFO,"clock(%d) update_service_create access_id(%d) fifo(%p).", util_clock(), s_update_socket.access_id, &s_update_socket.fifo); + + init_file_extend(true); + return GM_SUCCESS; +} + +GM_ERRCODE update_service_destroy(void) +{ + if(SOCKET_STATUS_ERROR == s_update_socket.status) + { + return GM_SUCCESS; + } + + update_service_close(); + + //update socket only reconnect, not recreated. + //fifo_delete(&s_update_socket.fifo); + + update_service_transfer_status(SOCKET_STATUS_ERROR); + + return GM_SUCCESS; +} + +SocketStatus update_service_get_status(void) +{ + return (SocketStatus)(s_update_socket.status); +} + +bool update_service_is_waiting_reboot(void) +{ + if(update_service_get_status() != SOCKET_STATUS_DATA_FINISH) + { + return false; + } + + if(get_file_extend()->result == REPORT_RESULT_UPDATED) + { + return true; + } + + return false; +} + +GM_ERRCODE update_service_timer_proc(void) +{ + if(!s_update_socket.fifo.base_addr) + { + return GM_SUCCESS; + } + + switch(s_update_socket.status) + { + case SOCKET_STATUS_INIT: + update_service_init_proc(); + break; + case SOCKET_STATUS_CONNECTING: + update_service_connecting_proc(); + break; + case SOCKET_STATUS_WORK: + update_service_work_proc(); + break; + case SOCKET_STATUS_DATA_FINISH: + update_service_data_finish_proc(); + break; + case SOCKET_STATUS_ERROR: + update_service_data_finish_proc(); + break; + default: + LOG(WARN,"clock(%d) update_service_timer_proc assert(s_update_socket.status(%d)) unknown.", util_clock(),s_update_socket.status); + return GM_ERROR_STATUS; + } + + return GM_SUCCESS; +} + + +static void update_service_init_proc(void) +{ + u8 IP[4]; + gm_socket_get_host_by_name_trigger(&s_update_socket); + system_state_get_ip_cache(SOCKET_INDEX_UPDATE, IP); + if(GM_SUCCESS == gm_is_valid_ip(IP)) + { + GM_memcpy( s_update_socket.ip , IP, sizeof(IP)); + update_service_transfer_status(SOCKET_STATUS_CONNECTING); + if(GM_SUCCESS == gm_socket_connect(&s_update_socket)) + { + } + // else do nothing . connecting_proc will deal. + } + else if((!s_update_socket.excuted_get_host) && (GM_SUCCESS == gm_is_valid_ip(s_update_socket.ip))) + { + update_service_transfer_status(SOCKET_STATUS_CONNECTING); + if(GM_SUCCESS == gm_socket_connect(&s_update_socket)) + { + } + // else do nothing . connecting_proc will deal. + } +} + +void update_service_connection_failed(void) +{ + update_service_close(); + + if(s_update_socket.status_fail_count >= MAX_CONNECT_REPEAT) + { + // if excuted get_host transfer to error statu, else get_host. + if(s_update_socket.excuted_get_host || (s_update_socket.addr[0] == 0)) + { + update_service_finish(UPDATE_PING_TIME); + } + else + { + update_service_transfer_status(SOCKET_STATUS_INIT); + } + } + // else do nothing . wait connecting proc to deal. +} + +void update_service_connection_ok(void) +{ + update_service_transfer_status(SOCKET_STATUS_WORK); + + update_msg_send_request(); +} + +void update_service_finish(u32 wait) +{ + update_service_close(); + + s_update_socket_extend.last_ok_time=util_clock(); + s_update_socket_extend.wait=wait; + + update_service_transfer_status(SOCKET_STATUS_DATA_FINISH); +} + + +static void update_service_close(void) +{ + if(s_update_socket.id >=0) + { + GM_SocketClose(s_update_socket.id); + s_update_socket.id=-1; + } +} + + +static void update_service_connecting_proc(void) +{ + u32 current_time = util_clock(); + + if((current_time - s_update_socket.send_time) > CONNECT_TIME_OUT) + { + s_update_socket.status_fail_count ++; + update_service_connection_failed(); + + if(s_update_socket.status == SOCKET_STATUS_CONNECTING && + s_update_socket.status_fail_count < MAX_CONNECT_REPEAT) + { + if(GM_SUCCESS == gm_socket_connect(&s_update_socket)) + { + //do nothing. wait callback + } + } + + } +} + + +static void update_service_work_proc(void) +{ + u32 current_time = util_clock(); + u8 one_send = 1; + + one_send = (STREAM_TYPE_DGRAM == config_service_update_socket_type())? UPDATE_MAX_PACK_ONE_SEND: 1; + if(! s_update_socket_extend.getting_data ) + { + //发送请求阶段 + if((current_time - s_update_socket.send_time) > MESSAGE_TIME_OUT) + { + s_update_socket.status_fail_count ++; + if(s_update_socket.status_fail_count >= MAX_MESSAGE_REPEAT) + { + LOG(INFO,"clock(%d) update_service_work_proc failed:%d", util_clock(), s_update_socket.status_fail_count); + update_service_finish(UPDATE_RETRY_TIME); + } + else + { + update_msg_send_request(); + } + } + } + else + { + //请求数据阶段 + if(! (get_file_extend()->use_new_socket)) + { + if((current_time - s_update_socket.send_time) > MESSAGE_TIME_OUT) + { + s_update_socket.status_fail_count ++; + if(s_update_socket.status_fail_count >= (MAX_MESSAGE_REPEAT * one_send)) + { + LOG(INFO,"clock(%d) update_filemod_work_proc failed:%d", util_clock(), s_update_socket.status_fail_count); + get_file_extend()->result = REPORT_RESULT_FAILED; + GM_strncpy((char *)get_file_extend()->result_info, "request blocks fail(work_proc).", sizeof(get_file_extend()->result_info)); + update_service_result_to_server(); + } + else + { + update_msg_send_data_block_request(&s_update_socket); + } + } + + } + else + { + update_filemod_timer_proc(); + } + } + + update_msg_receive(&s_update_socket); +} + + + +static void update_service_data_finish_proc(void) +{ + u32 current_time = util_clock(); + + if((current_time - s_update_socket_extend.last_ok_time) > s_update_socket_extend.wait) + { + LOG(DEBUG,"clock(%d) update_service_data_finish_proc cur(%d) - lastok(%d) > wait(%d).", + util_clock(), current_time, s_update_socket_extend.last_ok_time,s_update_socket_extend.wait); + init_file_extend(false); + s_update_socket_extend.getting_data = 0; + s_update_socket_extend.last_ok_time = 0; + s_update_socket_extend.wait = UPDATE_PING_TIME; + update_service_transfer_status(SOCKET_STATUS_INIT); + } +} + + + + +static GM_ERRCODE update_msg_send_request(void) +{ + u8 buff[100]; + u16 len = sizeof(buff); + u16 idx = 0; //current place + + update_msg_pack_head(buff, &idx, len); //13 bytes + update_msg_pack_request(buff, &idx, len); //53 bytes + update_msg_pack_id_len(buff, PROTOCCOL_UPDATE_REQUEST, idx); + + len=idx+2; // 1byte checksum , 1byte 0xD + + + if(GM_SUCCESS == gm_socket_send(&s_update_socket, buff, len)) + { + s_update_socket.send_time = util_clock(); + LOG(DEBUG,"clock(%d) update_msg_send_request msglen:%d success", util_clock(), len); + return GM_SUCCESS; + } + else + { + LOG(DEBUG,"clock(%d) update_msg_send_request msglen:%d failed.", util_clock(), len); + update_service_finish(UPDATE_PING_TIME); + } + return GM_ERROR_STATUS; +} + + + + +void update_service_after_response(bool newsocket, u32 total_len) +{ + if (total_len <= UPDATAE_FILE_MAX_SIZE) + { + //准备获取文件 + s_update_socket_extend.getting_data = 1; + + if(!get_file_extend()->use_new_socket) + { + update_msg_start_data_block_request(&s_update_socket); + } + //else update_filemod_timer_proc() will send request + } + else + { + LOG(INFO,"clock(%d) update_service_after_response assert(file_total_len(%d)) failed.", util_clock(), total_len); + update_service_finish(UPDATE_PING_TIME); + } +} + + +void update_service_result_to_server(void) +{ + if(get_file_extend()->result == REPORT_RESULT_UPDATED) + { + util_delete_file(UPDATE_MINOR_IMAGE); + GM_FS_Rename(UPDATE_TARGET_IMAGE, UPDATE_MINOR_IMAGE); + GM_FS_Rename(UPDATE_UPGRADE_FILE, UPDATE_TARGET_IMAGE); + } + + update_msg_send_result_to_server(&s_update_socket); +} + +void update_service_after_blocks_finish(void) +{ + s_update_socket.status_fail_count = 0; + update_msg_send_data_block_request(&s_update_socket); +} + + diff --git a/src/utility.c b/src/utility.c new file mode 100644 index 0000000..2e57cff --- /dev/null +++ b/src/utility.c @@ -0,0 +1,987 @@ + +#include +#include +#include +#include +#include "utility.h" +#include "config_service.h" +#include "log_service.h" + + +typedef struct +{ + U32 clock; +}Util; + +Util g_util; + + +GM_ERRCODE util_create(void) +{ + g_util.clock = 0; + return GM_SUCCESS; +} + + +GM_ERRCODE util_destroy(void) +{ + g_util.clock = 0; + return GM_SUCCESS; +} + +GM_ERRCODE util_timer_proc(void) +{ + g_util.clock++; + return GM_SUCCESS; +} + + +u8 util_chr(u8 x) +{ + u8 bRet = 0; + + if ((x>='0') && (x<='9')) + { + bRet = x - '0'; + } + else if ((x>='A') && (x<='F')) + { + bRet = x - 'A' + 0x0a; + } + else if ((x>='a') && (x<='f')) + { + bRet = x - 'a' + 0x0a; + } + else + { + bRet = 0; + } + + return bRet; +} + + +u8 util_asc(u8 x, u8 unrecognize_char) +{ + u8 bret; + + + if (x <= 9) + { + bret = x + '0'; + } + else if (x <= 0x0f) + { + bret = x - 0x0a + 'A'; + } + else + { + bret = unrecognize_char; + } + + return bret; +} + + +u16 util_remove_char(u8 *pdata, u16 len,char c) +{ + u16 idxr = 0; + u16 idxw = 0; + + for (idxr=0; idxr= 'a') && (c <= 'z')) + { + c = c - 'a' + 'A'; + } + return c; +} + +char util_to_lower(char c) +{ + if ((c >= 'a') && (c <= 'z')) + { + c = c - 'A' + 'a'; + } + return c; +} + + +void util_string_upper(u8 *pdata, u16 len) +{ + u16 idx; + + for (idx=0; idx < len; idx++) + { + if ((pdata[idx] >= 'a') && (pdata[idx] <= 'z')) + { + pdata[idx] = pdata[idx] - 'a' + 'A'; + } + } +} + + + +void util_string_lower(u8 *pdata, u16 len) +{ + u16 idx; + + for (idx=0; idx < len; idx++) + { + if ((pdata[idx] >= 'A') && (pdata[idx] <= 'Z')) + { + pdata[idx] = pdata[idx] - 'A' + 'a'; + } + } +} + + + +u8 util_is_valid_dns(const u8 *pdns, u16 len) +{ + u16 idx; + u8 have_point = 0; + + if (len == 0) + { + return 0; + } + + for (idx=0; idx0x7F)) + { + return 0; + } + + if (IS_DNS_CHAR(pdns[idx]) == 0) + { + return 0; + } + + if(pdns[idx]=='.') + { + have_point = 1; + } + } + + if(have_point) + { + return 1; + } + else + { + return 0; + } +} + + + +u8 util_is_valid_ip(const u8 *ip, u16 len) +{ + if (len != 4) + { + return 0; + } + + if(ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0) + { + return 0; + } + + if(ip[0] == 255 && ip[1] == 255 && ip[2] == 255 && ip[3] == 255) + { + return 0; + } + + return 1; +} + + + + +/* + 根据zone获取当前时间, pdata是bcd(基于2000)格式, time是ST_Time格式 + pdata与time 可以是NULL, 表示不输出对应格式的时间 +*/ +GM_ERRCODE util_get_current_local_time(u8* pdata, ST_Time* time, u8 zone) +{ + struct tm tm_t; + time_t t; + ST_Time mtk_t; + u32 adj_sec = (zone & 0x7F) * 3600; + + //app内部使用zone==0 的时间, 涉及具体通信时,才转成对应的时区的时间 + t = util_get_utc_time(); + if(t == (time_t)-1) + { + return GM_SYSTEM_ERROR; + } + + if (zone & 0x80) + { + t -= adj_sec; + } + else + { + t += adj_sec; + } + + tm_t = *util_localtime(&t); + + if(!time) + { + time = &mtk_t; + } + + util_tm_to_mtktime(&tm_t, time); + + if(pdata) + { + pdata[0] = HEX2BCD(time->year - BASE_YEAR_2000); + pdata[1] = HEX2BCD(time->month); + pdata[2] = HEX2BCD(time->day); + pdata[3] = HEX2BCD(time->hour); + pdata[4] = HEX2BCD(time->minute); + pdata[5] = HEX2BCD(time->second); + } + + return GM_SUCCESS; +} + + +void util_utc_sec_to_bcdtime_base2000(time_t sec_time, u8 *bcd, u8 zone) +{ + struct tm tm_t; + ST_Time mtk_t, *time = 0; + u32 adj_sec = (zone & 0x7F) * 3600; + + //app内部使用zone==0 的时间, 涉及具体通信时,才转成对应的时区的时间 + if(sec_time == (time_t)-1) + { + return; + } + + if (zone & 0x80) + { + sec_time -= adj_sec; + } + else + { + sec_time += adj_sec; + } + + tm_t = *util_localtime(&sec_time); + time = &mtk_t; + + util_tm_to_mtktime(&tm_t, time); + + bcd[0] = HEX2BCD(time->year - BASE_YEAR_2000); + bcd[1] = HEX2BCD(time->month); + bcd[2] = HEX2BCD(time->day); + bcd[3] = HEX2BCD(time->hour); + bcd[4] = HEX2BCD(time->minute); + bcd[5] = HEX2BCD(time->second); + + return; +} + + +/** +* Function: 判断是否是闰年 +* Description: +* Input: year:年 +* Output: +* Return: true——是闰年;false——不是闰年 +* Others: +*/ +bool util_is_leap_year(U16 year) +{ + if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) + { + return true; + } + else + { + return false; + } +} + + +static const int days[4][13] = +{ + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}, + {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, + {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}, +}; + +#define WRAP(a,b,m) ((a) = ((a) < 0 ) ? ((b)--, (a) + (m)) : (a)) + +struct tm util_gmtime(time_t t) +{ + S32 v_tm_sec = 0; + S32 v_tm_min = 0; + S32 v_tm_hour = 0; + S32 v_tm_mon = 0; + S32 v_tm_wday = 0; + S32 v_tm_tday = 0; + bool leap = false; + S32 m = 0; + + struct tm result; + + v_tm_sec = ( t % 60); + t /= 60; + v_tm_min = ( t % 60); + t /= 60; + v_tm_hour = ( t % 24); + t /= 24; + v_tm_tday = t; + + //WRAP (v_tm_sec, v_tm_min, 60); + //WRAP (v_tm_min, v_tm_hour, 60); + //WRAP (v_tm_hour, v_tm_tday, 24); + + if ((v_tm_wday = (v_tm_tday + 4) % 7) < 0) + { + v_tm_wday += 7; + } + + //计算第多少天(从0开始) + m = v_tm_tday; + result.tm_year = 70; + leap = util_is_leap_year (result.tm_year + 1900); + while (m >= days[leap + 2][12]) + { + m -= days[leap + 2][12]; + result.tm_year++; + leap = util_is_leap_year (result.tm_year + 1900); + } + + v_tm_mon = 0; + while (m >= days[leap][v_tm_mon]) + { + m -= days[leap][v_tm_mon]; + v_tm_mon++; + } + + result.tm_mday = (int) m + 1; + result.tm_yday = days[leap + 2][v_tm_mon] + m; + result.tm_sec = v_tm_sec; + result.tm_min = v_tm_min; + result.tm_hour = v_tm_hour; + result.tm_mon = v_tm_mon; + result.tm_wday = v_tm_wday; + + return result; +} + + + +enum TIME_DEF +{ + TIME_DEF_SEC = 1, + TIME_DEF_MIN = TIME_DEF_SEC * 60, + TIME_DEF_HOUR = TIME_DEF_MIN * 60, + TIME_DEF_DAY = TIME_DEF_HOUR * 24, + TIME_DEF_YEAR = TIME_DEF_DAY * 365, +}; + +time_t time_difference = 0; // 8 * TIME_DEF_HOUR; +static time_t util_mon_yday[2][12] = +{ + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }, + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }, +}; + + +long long util_get_day(int year) { + int util_is_leap_year_year_num; + u32 tol_day; + year = year - 1; + util_is_leap_year_year_num = year / 4 - year / 100 + year / 400; + tol_day = year * 365 + util_is_leap_year_year_num; + return tol_day; +} + +time_t util_items_mktime(int year, int mon, int day, int hour, int min, int sec) { + u32 ret = 0; + u32 tol_day = 0; + year += 1900; + tol_day = util_get_day(year) - util_get_day(1970); + tol_day += util_mon_yday[util_is_leap_year(year)][mon]; + tol_day += day - 1; + + ret = 0; + ret += tol_day * TIME_DEF_DAY; + ret += hour * TIME_DEF_HOUR; + ret += min * TIME_DEF_MIN; + ret += sec * TIME_DEF_SEC; + + return ret - time_difference; +} + +time_t util_mktime(struct tm* mk) { + if (!mk) { + return (time_t)-1; + } + if (!(mk->tm_sec >= 0 && mk->tm_sec <= 59)) { + return (time_t)-1; + } + if (!(mk->tm_min >= 0 && mk->tm_min <= 59)) { + return (time_t)-1; + } + if (!(mk->tm_hour >= 0 && mk->tm_hour <= 23)) { + return (time_t)-1; + } + if (!(mk->tm_mday >= 1 && mk->tm_hour <= 31)) { + return (time_t)-1; + } + if (!(mk->tm_mon >= 0 && mk->tm_mon <= 11)) { + return (time_t)-1; + } + if (!(mk->tm_year >= 70)) { + return (time_t)-1; + } + + return util_items_mktime(mk->tm_year, mk->tm_mon, mk->tm_mday, mk->tm_hour, mk->tm_min, mk->tm_sec); +} + + + +struct tm * util_localtime(const time_t *srctime) +{ + static struct tm tm_time; + long int n32_Pass4year,n32_hpery; + + // 每个月的天数 非闰年 + const static char Days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + // 一年的小时数 + const static int ONE_YEAR_HOURS = 8760; // 365 * 24 (非闰年) + + //计算时差8*60*60 固定北京时间 + time_t time = *srctime; + tm_time.tm_isdst=0; + + //取秒时间 + tm_time.tm_sec=(int)(time % 60); + time /= 60; + + //取分钟时间 + tm_time.tm_min=(int)(time % 60); + time /= 60; + + //计算星期 + tm_time.tm_wday=(time/24+4)%7; + + //取过去多少个四年,每四年有 1461*24 小时 + n32_Pass4year=((unsigned int)time / (1461L * 24L)); + + //计算年份 + tm_time.tm_year=(n32_Pass4year << 2)+70; + + //四年中剩下的小时数 + time %= 1461L * 24L; + + //计算在这一年的天数 + tm_time.tm_yday=(time/24)%365; + + //校正闰年影响的年份,计算一年中剩下的小时数 + for (;;) + { + //一年的小时数 + n32_hpery = ONE_YEAR_HOURS; + + //判断闰年 + if ((tm_time.tm_year & 3) == 0) + { + //是闰年,一年则多24小时,即一天 + n32_hpery += 24; + } + + if (time < n32_hpery) + { + break; + } + + tm_time.tm_year++; + time -= n32_hpery; + } + + //小时数 + tm_time.tm_hour=(int)(time % 24); + + //一年中剩下的天数 + time /= 24; + + //假定为闰年 + time++; + + //校正润年的误差,计算月份,日期 + if ((tm_time.tm_year & 3) == 0) + { + if (time > 60) + { + time--; + } + else + { + if (time == 60) + { + tm_time.tm_mon = 1; + tm_time.tm_mday = 29; + return &tm_time; + } + } + } + + //计算月日 + for (tm_time.tm_mon = 0;Days[tm_time.tm_mon] < time;tm_time.tm_mon++) + { + time -= Days[tm_time.tm_mon]; + } + + tm_time.tm_mday = (int)(time); + return &tm_time; +} + + +void util_mtktime_to_gpstime(const ST_Time st_time,const U8 leap_sencond, double* p_tow, U16* p_wn) +{ + U8 days_per_month_table[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + U16 index = 0; + // 天内时间 + double tod = 0; + + U16 days = 0; + + // 天内时间 + tod = st_time.hour * 3600 + st_time.minute * 60 + st_time.second; + + // 参考时间: 1980.1.6 + days = st_time.day; + // 年->天 + for (index = 1980; index < st_time.year; index++) + { + if (util_is_leap_year(index)) + { + days += 366; + } + else + { + days += 365; + } + } + + days -= 6; + + // 月->天 + if (util_is_leap_year(st_time.year)) + { + days_per_month_table[1] = 29; + } + for (index = 1; index < st_time.month - 1; index++) + { + days += days_per_month_table[index - 1]; + } + + // 周数 + *p_wn = (days / 7); + // 周内时间,闰秒修正 + *p_tow = (days % 7) * 86400 + tod + leap_sencond; +} + +void util_mtktime_to_tm(const ST_Time *mtk_t, struct tm *tm_t) +{ + tm_t->tm_sec = mtk_t->second; + tm_t->tm_min = mtk_t->minute; + tm_t->tm_hour = mtk_t->hour; + tm_t->tm_mday = mtk_t->day; + tm_t->tm_mon = mtk_t->month - 1; + tm_t->tm_year = mtk_t->year -1900; + tm_t->tm_wday = mtk_t->dayindex; + tm_t->tm_isdst = 0; +} + +void util_tm_to_mtktime(const struct tm *tm_t, ST_Time *mtk_t) +{ + mtk_t->second = tm_t->tm_sec ; + mtk_t->minute = tm_t->tm_min ; + mtk_t->hour = tm_t->tm_hour ; + mtk_t->day = tm_t->tm_mday; + mtk_t->month= tm_t->tm_mon + 1; + mtk_t->year = tm_t->tm_year + 1900; + mtk_t->dayindex = tm_t->tm_wday; +} + + +time_t util_get_utc_time(void) +{ + ST_Time utc_time_mtk; + struct tm utc_time_tm; + time_t ret; + GM_GetLocalTime(&utc_time_mtk,0); + + utc_time_tm.tm_sec = utc_time_mtk.second; + utc_time_tm.tm_min = utc_time_mtk.minute; + utc_time_tm.tm_hour = utc_time_mtk.hour; + utc_time_tm.tm_mday = utc_time_mtk.day; + utc_time_tm.tm_mon = utc_time_mtk.month - 1; + utc_time_tm.tm_year = utc_time_mtk.year - 1900; + utc_time_tm.tm_wday = utc_time_mtk.dayindex; + utc_time_tm.tm_isdst = 0; + ret = util_mktime(&utc_time_tm); + return ret; +} + + +u32 util_clock(void) +{ + return g_util.clock; +} + + +/************************************************************************ + Function : + Description : + + Unicode符号范围 UTF-8编码方式 + 十六进制 二进制 + 0000 0000-0000 007F | 0xxxxxxx + 0000 0080-0000 07FF | 110xxxxx 10xxxxxx + 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx + 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + + Parameter : + Return : + Author: + Date: +************************************************************************/ +u16 util_utf8_msg_len(const u8 *msg) +{ + u16 len = 0; + + if (msg == NULL) + { + return 0; + } + + if (((*msg) & 0x80) == 0) + { + len = 1; //0xxx,xxxx Normal ASCII code + } + else if ((((*msg)&0xe0) == 0xc0) + && (((*(msg+1))&0xc0) == 0x80)) + { + if (((*msg)&0xfe ) == 0xc0) // 1100,000x is illegal data + { + len = 0; + } + else + { + len = 2; // 110x,xxxx 10xx,xxxx + } + } + else if ((((*msg)&0xf0) == 0xe0) + && (((*(msg+1))&0xc0) == 0x80) + && (((*(msg+2))&0xc0) == 0x80)) + { + //1110,0000 100x,xxxx is illegal data + if ((*msg ==0xe0) && (((*(msg+1))&0xe0)==0x80)) + { + len = 0; + } + else + { + len = 3; // 1110,xxxx 10xx,xxxx 10xx,xxxx + } + } + else + { + len = 0; + } + + return len; +} + + +u16 util_utf8_to_unicode(const u8 *msg, u16 msg_len, u16 *ucs2_msg, u16 max_len) +{ + u16 byte_len=0; + u16 total_len=0; + u8 utf8_len = 0; + + if (msg_len == 0) + { + return 0; + } + + + for(; (*msg != 0x00) && (total_len <= max_len - 1) && (utf8_len < msg_len); ) + { + byte_len = util_utf8_msg_len(msg); + + if (byte_len == 1) + { + (*ucs2_msg) = *(msg); + ucs2_msg++; + msg++; + utf8_len++; + total_len += 1; + } + else if (byte_len == 2) + { + *ucs2_msg = ((((*msg) >> 2) & (u8)0x07 ) & 0x00ff) << 8; + *ucs2_msg |= (((*msg) << 6) | ((*(msg+1)) & (u8)0x3f)) & 0x00ff; + ucs2_msg++; + msg += 2; + utf8_len += 2; + total_len += 1; + } + else if (byte_len == 3) + { + *ucs2_msg = ((((*msg) << 4 ) | (((*(msg+1)) >> 2) & 0x0f)) & 0x00ff) << 8; + *ucs2_msg |= (((*(msg+1)) << 6) | ((*(msg+2)) & (u8)0x3f)) & 0x00ff; + ucs2_msg++; + msg += 3; + utf8_len += 3; + total_len += 1; + } + else + { + msg++; + utf8_len++; + } + } + + return total_len; +} + + +u16 util_ucs2_u16_to_u8(const u16 *input, u16 len, u8 *output) +{ + u16 i=0,j=0; + + for (i=0; i>jval); + + if ((r==0)&&(k==0)&&(with_zero==0)) /* withZero=1 返回8字节,withZero=0可变的字节 */ + { + + } + else + { + *(buffer+k)=util_asc(r, '0'); + k++; + } + + flag >>= 4; + value &= flag; + jval -= 4; + } + + if (k == 0) + { + *buffer = '0'; + k = 1; + } + + return k; +} + + +s32 util_delete_file(const u16 *file) +{ + s32 ret=0; + s32 handle; + + + // 检查文件是否存在 + handle = GM_FS_CheckFile(file); + if (handle >= 0) + { + // 文件存在删掉,重新创建 + ret = GM_FS_Delete(file); + } + + return ret; +} + + +/************************************************************************ + Function : + Description : + + Parameter : + Return : + Author: + Date: Seo-26-2016 +************************************************************************/ +u16 util_ucs2_to_ascii(const u8 *w_in, u8 *a_out, u16 len) +{ + u16 i = 0; + + while (w_in[i * 2] != '\0' || w_in[i * 2 + 1] != '\0') + { + a_out[i] = w_in[i * 2]; + i += 1; + if (i*2 >= len) + { + break; + } + } + a_out[i] = '\0'; + + return i; +} + +float util_mile_to_km(const float miles) +{ + return 1.852 * miles; +} + +bool util_isdigit(const char c) +{ + if (c >= '0' && c <= '9') + { + return true; + } + else + { + return false; + } +} + +bool util_isprint(const char c) +{ + if (c >= 0x20 && c <= 0x7E) + { + return true; + } + else + { + return false; + } +} + + +U32 util_strtoul(const char* cp,char** endp) +{ + unsigned long result = 0; + while (util_isdigit(*cp)) + { + result = result * 10 + (*cp - '0'); + cp++; + } + if (endp) + { + *endp = (char*)cp; + } + return result; +} + +S32 util_strtol(const char* cp,char** endp) +{ + if(*cp == '-') + { + return (S32)(util_strtoul(cp+1,endp)) * (-1); + } + return util_strtoul(cp,endp); +} + +GM_CHANGE_ENUM util_check_state_change(bool current_state, PStateRecord p_record, U16 true_hold_time_threshold, U16 false_hold_time_threshold) +{ + GM_CHANGE_ENUM ret = GM_NO_CHANGE; + + if (current_state) + { + p_record->true_state_hold_seconds++; + p_record->false_state_hold_seconds = 0; + } + else + { + p_record->false_state_hold_seconds++; + p_record->true_state_hold_seconds = 0; + } + + //与历史状态不同 + if (current_state ^ p_record->state ) + { + if ((p_record->true_state_hold_seconds >= true_hold_time_threshold) && current_state) + { + ret = GM_CHANGE_TRUE; + p_record->state = current_state; + } + else if((p_record->false_state_hold_seconds >= false_hold_time_threshold) && !current_state) + { + ret = GM_CHANGE_FALSE; + p_record->state = current_state; + } + else + { + ret = GM_NO_CHANGE; + } + } + else + { + ret = GM_NO_CHANGE; + } + + return ret; +} + + + + + diff --git a/src/watch_dog.c b/src/watch_dog.c new file mode 100644 index 0000000..2e24b4f --- /dev/null +++ b/src/watch_dog.c @@ -0,0 +1,103 @@ +/** + * Copyright @ Goome Technologies Co., Ltd. 2009-2019. All rights reserved. + * File name: watch_dog.h + * Author: 王志华 + * Version: 1.0 + * Date: 2019-03-06 + * Description: 实现软件看门狗功能 + * Others: + * Function List: + 1. 创建 + 2. 销毁 + 3. 定时处理入口 + 4. 开启/关闭软件看门狗 + * History: + 1. Date: 2019-03-06 + Author: 王志华 + Modification 创建初始版本 + 2. Date: + Author: + Modification: + + */ + +#include "watch_dog.h" +#include "gm_wdt.h" +#include "gm_memory.h" +#include "hard_ware.h" + +//第1个软件看门狗清零时间(10秒) +#define GM_FIRST_SW_WDT_CLEAR_TIME 10 + +//第2个软件看门狗重启时间(1800秒=30分钟) +#define GM_SECCOND_SW_WDT_RESTART_TIME 1800 + +//第2个软件看门狗清零时间(300秒=5分钟) +#define GM_SECCOND_SW_WDT_CLEAR_TIME 300 + +typedef struct +{ + bool software_watchdog_enable; + bool last_gpio_pin_level; +}WatchDog, *PWatchDog; + +static WatchDog s_watch_dog; + +GM_ERRCODE watch_dog_create(void) +{ + //第1个软件看门狗,内部固定30秒重启 + GM_SoftwareWdtCounterEnable(true); + + //第2软件看门狗,自定义重启时长 + //使用两个软件看门狗是为了确保可靠性 + GM_SetSwLogicCounterEnable(true); + GM_SetSwLogicCounterMax(GM_SECCOND_SW_WDT_RESTART_TIME); + + s_watch_dog.software_watchdog_enable = true; + s_watch_dog.last_gpio_pin_level = false; + + return GM_SUCCESS; +} + +GM_ERRCODE watch_dog_destroy(void) +{ + GM_SoftwareWdtCounterEnable(false); + GM_SetSwLogicCounterEnable(false); + + return GM_SUCCESS; +} + +GM_ERRCODE watch_dog_timer_proc(void) +{ + + //处理硬件看门狗 + s_watch_dog.last_gpio_pin_level = !(s_watch_dog.last_gpio_pin_level); + hard_ware_set_watchdog(s_watch_dog.last_gpio_pin_level); + + //处理软件看门狗 + if (s_watch_dog.software_watchdog_enable) + { + if (GM_GetSoftwareWdtCounter() >= GM_FIRST_SW_WDT_CLEAR_TIME) + { + GM_SetSoftwareWdtCounter(0); + } + + if (GM_GetSwLogicCounter() >= GM_SECCOND_SW_WDT_CLEAR_TIME) + { + GM_SetSwLogicCounter(0); + } + } + + return GM_SUCCESS; +} + +GM_ERRCODE watch_dog_enable(bool enable) +{ + s_watch_dog.software_watchdog_enable = enable; + + GM_SoftwareWdtCounterEnable(enable); + GM_SetSwLogicCounterEnable(enable); + + return GM_SUCCESS; +} +