Compare commits
72 Commits
PCB_Rev_1.
...
170c66ff49
Author | SHA1 | Date | |
---|---|---|---|
170c66ff49 | |||
2ad835966c | |||
a20a351002 | |||
c9fba23e70 | |||
9301607468 | |||
fc592c4342 | |||
ab2ab0e0c1 | |||
5ee0a23a6d | |||
cf76ea7cc7 | |||
7a2e95c126 | |||
1cf0560957 | |||
b66d175948 | |||
0967b6aa65 | |||
498d813624 | |||
268c204957 | |||
65d51f13aa | |||
f727bb3247 | |||
cd1379f90c | |||
0363b1eebc | |||
e6f1283aae | |||
a92b1edfd9 | |||
4cce7c1c86 | |||
0a1625e9b8 | |||
c24829ed70 | |||
a102405596 | |||
1b7157dbdc | |||
cad34d6b84 | |||
701bf9f457 | |||
0a895a00b9 | |||
22a62e3d1e | |||
f48b5a09ed | |||
7f6c486eab | |||
3e77f89538 | |||
f33076a0a3 | |||
7e58db489d | |||
eb771d07d3 | |||
e2059cb587 | |||
6702154ef5 | |||
a899cf4dcf | |||
ea230bcee7 | |||
c059d7d085 | |||
b8c79955a8 | |||
44240aa7bf | |||
6bc523b2a8 | |||
97cdd7fad1 | |||
ec62eeee1e | |||
7b166caf84 | |||
62a7cd1b9c | |||
7e047c0c09 | |||
8c2d553dfb | |||
ca9409e328 | |||
5a6dc524ad | |||
41b27c02dd | |||
e344977b8f | |||
aeab80d5a8 | |||
4507c80eba | |||
427e5e5d16 | |||
3a0e1a931d | |||
a960e67c7d | |||
9e1a4d821f | |||
4d0a9918ce | |||
53928a93b0 | |||
6b89ed9a8c | |||
ae29e23812 | |||
8884e995ca | |||
8eb52e286f | |||
98145b424d | |||
43ab7c6934 | |||
99dc58f3c9 | |||
3ee276c189 | |||
0b95cff140 | |||
641412ecc8 |
BIN
Documentation/Datasheets/E220-900T22D_UserManual_EN_v1.0.pdf
Normal file
BIN
Documentation/Pinout_UART_LoRa.png
Normal file
After Width: | Height: | Size: 53 KiB |
@@ -1 +0,0 @@
|
|||||||
E:\Dark Emergency Timer\Hardware\DE-Timer\_autosave-DE-Timer.kicad_sch
|
|
BIN
Hardware/BOM DE-Timer HW Rev.1.0.xlsx
Normal file
@@ -33,9 +33,9 @@
|
|||||||
"other_text_thickness": 0.15,
|
"other_text_thickness": 0.15,
|
||||||
"other_text_upright": false,
|
"other_text_upright": false,
|
||||||
"pads": {
|
"pads": {
|
||||||
"drill": 0.762,
|
"drill": 3.0,
|
||||||
"height": 1.524,
|
"height": 4.0,
|
||||||
"width": 1.524
|
"width": 4.0
|
||||||
},
|
},
|
||||||
"silk_line_width": 0.15,
|
"silk_line_width": 0.15,
|
||||||
"silk_text_italic": false,
|
"silk_text_italic": false,
|
||||||
@@ -384,7 +384,7 @@
|
|||||||
"idf": "",
|
"idf": "",
|
||||||
"netlist": "",
|
"netlist": "",
|
||||||
"specctra_dsn": "",
|
"specctra_dsn": "",
|
||||||
"step": "",
|
"step": "DE-Timer.step",
|
||||||
"vrml": ""
|
"vrml": ""
|
||||||
},
|
},
|
||||||
"page_layout_descr_file": ""
|
"page_layout_descr_file": ""
|
||||||
|
@@ -1601,6 +1601,13 @@
|
|||||||
(effects (font (size 1.27 1.27)) (justify right) hide)
|
(effects (font (size 1.27 1.27)) (justify right) hide)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
(global_label "LoRa_M0" (shape input) (at 262.89 76.2 270) (fields_autoplaced)
|
||||||
|
(effects (font (size 1.27 1.27)) (justify right))
|
||||||
|
(uuid 72e274cf-d09b-40a2-b1e3-3b71338c2588)
|
||||||
|
(property "Intersheet References" "${INTERSHEET_REFS}" (id 0) (at 262.9694 86.8379 90)
|
||||||
|
(effects (font (size 1.27 1.27)) (justify right) hide)
|
||||||
|
)
|
||||||
|
)
|
||||||
(global_label "BTN_FAC_2" (shape input) (at 199.39 121.92 0) (fields_autoplaced)
|
(global_label "BTN_FAC_2" (shape input) (at 199.39 121.92 0) (fields_autoplaced)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
(uuid 7a25f527-6714-4bf4-8e93-5473e8c7ec97)
|
(uuid 7a25f527-6714-4bf4-8e93-5473e8c7ec97)
|
||||||
@@ -1727,6 +1734,13 @@
|
|||||||
(effects (font (size 1.27 1.27)) (justify right) hide)
|
(effects (font (size 1.27 1.27)) (justify right) hide)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
(global_label "LoRa_M1" (shape input) (at 256.54 76.2 270) (fields_autoplaced)
|
||||||
|
(effects (font (size 1.27 1.27)) (justify right))
|
||||||
|
(uuid eeff06ce-5dd6-48ad-98cf-4489d7624b9c)
|
||||||
|
(property "Intersheet References" "${INTERSHEET_REFS}" (id 0) (at 256.6194 86.8379 90)
|
||||||
|
(effects (font (size 1.27 1.27)) (justify right) hide)
|
||||||
|
)
|
||||||
|
)
|
||||||
(global_label "LoRa_M1" (shape output) (at 234.95 125.73 180) (fields_autoplaced)
|
(global_label "LoRa_M1" (shape output) (at 234.95 125.73 180) (fields_autoplaced)
|
||||||
(effects (font (size 1.27 1.27)) (justify right))
|
(effects (font (size 1.27 1.27)) (justify right))
|
||||||
(uuid f177e463-2a20-4337-808d-73eaa4f12d69)
|
(uuid f177e463-2a20-4337-808d-73eaa4f12d69)
|
||||||
@@ -1897,7 +1911,7 @@
|
|||||||
(property "Reference" "R6" (id 0) (at 212.598 44.5516 0)
|
(property "Reference" "R6" (id 0) (at 212.598 44.5516 0)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
)
|
)
|
||||||
(property "Value" "R" (id 1) (at 212.598 46.863 0)
|
(property "Value" "4k7" (id 1) (at 212.598 46.863 0)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
)
|
)
|
||||||
(property "Footprint" "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder" (id 2) (at 209.042 45.72 90)
|
(property "Footprint" "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder" (id 2) (at 209.042 45.72 90)
|
||||||
@@ -1916,7 +1930,7 @@
|
|||||||
(property "Reference" "R7" (id 0) (at 217.678 44.5516 0)
|
(property "Reference" "R7" (id 0) (at 217.678 44.5516 0)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
)
|
)
|
||||||
(property "Value" "R" (id 1) (at 217.678 46.863 0)
|
(property "Value" "4k7" (id 1) (at 217.678 46.863 0)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
)
|
)
|
||||||
(property "Footprint" "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder" (id 2) (at 214.122 45.72 90)
|
(property "Footprint" "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder" (id 2) (at 214.122 45.72 90)
|
||||||
@@ -2302,7 +2316,7 @@
|
|||||||
(uuid 00000000-0000-0000-0000-0000608139a0)
|
(uuid 00000000-0000-0000-0000-0000608139a0)
|
||||||
(property "Reference" "U6" (id 0) (at 100.33 78.9432 0))
|
(property "Reference" "U6" (id 0) (at 100.33 78.9432 0))
|
||||||
(property "Value" "OKI-78SR-5_1.5-W36-C" (id 1) (at 100.33 81.2546 0))
|
(property "Value" "OKI-78SR-5_1.5-W36-C" (id 1) (at 100.33 81.2546 0))
|
||||||
(property "Footprint" "Converter_DCDC:Converter_DCDC_muRata_OKI-78SR_Vertical" (id 2) (at 101.6 91.44 0)
|
(property "Footprint" "Converter_DCDC:Converter_DCDC_RECOM_R-78E-0.5_THT" (id 2) (at 101.6 91.44 0)
|
||||||
(effects (font (size 1.27 1.27) italic) (justify left) hide)
|
(effects (font (size 1.27 1.27) italic) (justify left) hide)
|
||||||
)
|
)
|
||||||
(property "Datasheet" "https://power.murata.com/data/power/oki-78sr.pdf" (id 3) (at 100.33 85.09 0)
|
(property "Datasheet" "https://power.murata.com/data/power/oki-78sr.pdf" (id 3) (at 100.33 85.09 0)
|
||||||
@@ -2396,6 +2410,25 @@
|
|||||||
(pin "9" (uuid 8020776e-90b2-4b88-a91b-d42c0c930bde))
|
(pin "9" (uuid 8020776e-90b2-4b88-a91b-d42c0c930bde))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(symbol (lib_id "Device:R") (at 256.54 72.39 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes)
|
||||||
|
(uuid 2bcb8eff-5353-49d7-940f-1af0870f1ac9)
|
||||||
|
(property "Reference" "R10" (id 0) (at 258.318 71.2216 0)
|
||||||
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
|
)
|
||||||
|
(property "Value" "4k7" (id 1) (at 258.318 73.533 0)
|
||||||
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
|
)
|
||||||
|
(property "Footprint" "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder" (id 2) (at 254.762 72.39 90)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(property "Datasheet" "~" (id 3) (at 256.54 72.39 0)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(pin "1" (uuid 6115d08d-ef27-4828-8c89-a6e903cffdaa))
|
||||||
|
(pin "2" (uuid e577afa2-1c52-4e68-895a-b4c7f4efbfd1))
|
||||||
|
)
|
||||||
|
|
||||||
(symbol (lib_id "power:GND") (at 160.02 83.82 0) (unit 1)
|
(symbol (lib_id "power:GND") (at 160.02 83.82 0) (unit 1)
|
||||||
(in_bom yes) (on_board yes)
|
(in_bom yes) (on_board yes)
|
||||||
(uuid 3608f094-4a83-4b12-a751-ce01f8af8f37)
|
(uuid 3608f094-4a83-4b12-a751-ce01f8af8f37)
|
||||||
@@ -2433,7 +2466,7 @@
|
|||||||
(symbol (lib_id "power:+3.3V") (at 243.84 68.58 0) (unit 1)
|
(symbol (lib_id "power:+3.3V") (at 243.84 68.58 0) (unit 1)
|
||||||
(in_bom yes) (on_board yes)
|
(in_bom yes) (on_board yes)
|
||||||
(uuid 40a343f4-2d59-4a27-ab4f-ae28f587fed5)
|
(uuid 40a343f4-2d59-4a27-ab4f-ae28f587fed5)
|
||||||
(property "Reference" "#PWR?" (id 0) (at 243.84 72.39 0)
|
(property "Reference" "#PWR02" (id 0) (at 243.84 72.39 0)
|
||||||
(effects (font (size 1.27 1.27)) hide)
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
)
|
)
|
||||||
(property "Value" "+3.3V" (id 1) (at 244.221 64.1858 0))
|
(property "Value" "+3.3V" (id 1) (at 244.221 64.1858 0))
|
||||||
@@ -2465,10 +2498,10 @@
|
|||||||
(symbol (lib_id "Device:R") (at 250.19 72.39 0) (unit 1)
|
(symbol (lib_id "Device:R") (at 250.19 72.39 0) (unit 1)
|
||||||
(in_bom yes) (on_board yes)
|
(in_bom yes) (on_board yes)
|
||||||
(uuid 43fa7042-3495-4cdb-99c3-d2fae29fcc2e)
|
(uuid 43fa7042-3495-4cdb-99c3-d2fae29fcc2e)
|
||||||
(property "Reference" "R?" (id 0) (at 251.968 71.2216 0)
|
(property "Reference" "R9" (id 0) (at 251.968 71.2216 0)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
)
|
)
|
||||||
(property "Value" "R" (id 1) (at 251.968 73.533 0)
|
(property "Value" "4k7" (id 1) (at 251.968 73.533 0)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
)
|
)
|
||||||
(property "Footprint" "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder" (id 2) (at 248.412 72.39 90)
|
(property "Footprint" "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder" (id 2) (at 248.412 72.39 90)
|
||||||
@@ -2566,7 +2599,7 @@
|
|||||||
(symbol (lib_id "power:+3.3V") (at 250.19 68.58 0) (unit 1)
|
(symbol (lib_id "power:+3.3V") (at 250.19 68.58 0) (unit 1)
|
||||||
(in_bom yes) (on_board yes)
|
(in_bom yes) (on_board yes)
|
||||||
(uuid 6c9e14ce-f378-409f-83b0-3017c42aa43a)
|
(uuid 6c9e14ce-f378-409f-83b0-3017c42aa43a)
|
||||||
(property "Reference" "#PWR?" (id 0) (at 250.19 72.39 0)
|
(property "Reference" "#PWR03" (id 0) (at 250.19 72.39 0)
|
||||||
(effects (font (size 1.27 1.27)) hide)
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
)
|
)
|
||||||
(property "Value" "+3.3V" (id 1) (at 250.571 64.1858 0))
|
(property "Value" "+3.3V" (id 1) (at 250.571 64.1858 0))
|
||||||
@@ -2633,7 +2666,7 @@
|
|||||||
(property "Reference" "C2" (id 0) (at 142.621 76.3016 0)
|
(property "Reference" "C2" (id 0) (at 142.621 76.3016 0)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
)
|
)
|
||||||
(property "Value" "C" (id 1) (at 142.621 78.613 0)
|
(property "Value" "100n" (id 1) (at 142.621 78.613 0)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
)
|
)
|
||||||
(property "Footprint" "Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder" (id 2) (at 140.6652 81.28 0)
|
(property "Footprint" "Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder" (id 2) (at 140.6652 81.28 0)
|
||||||
@@ -2739,7 +2772,7 @@
|
|||||||
(symbol (lib_id "power:+3.3V") (at 237.49 68.58 0) (unit 1)
|
(symbol (lib_id "power:+3.3V") (at 237.49 68.58 0) (unit 1)
|
||||||
(in_bom yes) (on_board yes)
|
(in_bom yes) (on_board yes)
|
||||||
(uuid 9db85383-a03f-4209-a928-87be53d1e345)
|
(uuid 9db85383-a03f-4209-a928-87be53d1e345)
|
||||||
(property "Reference" "#PWR?" (id 0) (at 237.49 72.39 0)
|
(property "Reference" "#PWR01" (id 0) (at 237.49 72.39 0)
|
||||||
(effects (font (size 1.27 1.27)) hide)
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
)
|
)
|
||||||
(property "Value" "+3.3V" (id 1) (at 237.871 64.1858 0))
|
(property "Value" "+3.3V" (id 1) (at 237.871 64.1858 0))
|
||||||
@@ -2780,10 +2813,10 @@
|
|||||||
(symbol (lib_id "Device:R") (at 243.84 72.39 0) (unit 1)
|
(symbol (lib_id "Device:R") (at 243.84 72.39 0) (unit 1)
|
||||||
(in_bom yes) (on_board yes)
|
(in_bom yes) (on_board yes)
|
||||||
(uuid af841cc7-411b-4fa7-bf12-b2b6bf90990e)
|
(uuid af841cc7-411b-4fa7-bf12-b2b6bf90990e)
|
||||||
(property "Reference" "R?" (id 0) (at 245.618 71.2216 0)
|
(property "Reference" "R8" (id 0) (at 245.618 71.2216 0)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
)
|
)
|
||||||
(property "Value" "R" (id 1) (at 245.618 73.533 0)
|
(property "Value" "4k7" (id 1) (at 245.618 73.533 0)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
)
|
)
|
||||||
(property "Footprint" "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder" (id 2) (at 242.062 72.39 90)
|
(property "Footprint" "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder" (id 2) (at 242.062 72.39 90)
|
||||||
@@ -2796,6 +2829,22 @@
|
|||||||
(pin "2" (uuid b71998a2-dc31-488e-96c8-f96d58289595))
|
(pin "2" (uuid b71998a2-dc31-488e-96c8-f96d58289595))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(symbol (lib_id "power:+3.3V") (at 262.89 68.58 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes)
|
||||||
|
(uuid b2a70cb2-3ea0-4d7a-83e9-2996d0cf206b)
|
||||||
|
(property "Reference" "#PWR0131" (id 0) (at 262.89 72.39 0)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(property "Value" "+3.3V" (id 1) (at 263.271 64.1858 0))
|
||||||
|
(property "Footprint" "" (id 2) (at 262.89 68.58 0)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(property "Datasheet" "" (id 3) (at 262.89 68.58 0)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(pin "1" (uuid a565fbe1-90b3-4bf4-85a9-0bf50a5110f2))
|
||||||
|
)
|
||||||
|
|
||||||
(symbol (lib_id "power:GND") (at 139.7 81.28 0) (unit 1)
|
(symbol (lib_id "power:GND") (at 139.7 81.28 0) (unit 1)
|
||||||
(in_bom yes) (on_board yes)
|
(in_bom yes) (on_board yes)
|
||||||
(uuid bb27d01d-6f95-44db-9098-a0b85d39315e)
|
(uuid bb27d01d-6f95-44db-9098-a0b85d39315e)
|
||||||
@@ -2918,6 +2967,41 @@
|
|||||||
(pin "1" (uuid 1d18dbe4-48e7-470b-b33a-c9b54fb84aeb))
|
(pin "1" (uuid 1d18dbe4-48e7-470b-b33a-c9b54fb84aeb))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(symbol (lib_id "power:+3.3V") (at 256.54 68.58 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes)
|
||||||
|
(uuid f19e33ae-597f-4b9a-8f2d-c4d9c6bead68)
|
||||||
|
(property "Reference" "#PWR0130" (id 0) (at 256.54 72.39 0)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(property "Value" "+3.3V" (id 1) (at 256.921 64.1858 0))
|
||||||
|
(property "Footprint" "" (id 2) (at 256.54 68.58 0)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(property "Datasheet" "" (id 3) (at 256.54 68.58 0)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(pin "1" (uuid f4708d09-7ba1-402c-9e48-47aea89c0016))
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol (lib_id "Device:R") (at 262.89 72.39 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes)
|
||||||
|
(uuid f4ba32ab-ab3d-4753-a0b7-a2a898ba4b27)
|
||||||
|
(property "Reference" "R11" (id 0) (at 264.668 71.2216 0)
|
||||||
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
|
)
|
||||||
|
(property "Value" "4k7" (id 1) (at 264.668 73.533 0)
|
||||||
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
|
)
|
||||||
|
(property "Footprint" "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder" (id 2) (at 261.112 72.39 90)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(property "Datasheet" "~" (id 3) (at 262.89 72.39 0)
|
||||||
|
(effects (font (size 1.27 1.27)) hide)
|
||||||
|
)
|
||||||
|
(pin "1" (uuid 4b77d0a4-5200-4718-ad55-d12fcc0160fd))
|
||||||
|
(pin "2" (uuid 970b75d2-be6a-4922-bf76-1e9d7e25dec5))
|
||||||
|
)
|
||||||
|
|
||||||
(symbol (lib_id "Connector_Generic:Conn_01x04") (at 116.84 147.32 0) (unit 1)
|
(symbol (lib_id "Connector_Generic:Conn_01x04") (at 116.84 147.32 0) (unit 1)
|
||||||
(in_bom yes) (on_board yes)
|
(in_bom yes) (on_board yes)
|
||||||
(uuid f7c59d3b-150e-4fe4-9d7a-d8150b555fa0)
|
(uuid f7c59d3b-150e-4fe4-9d7a-d8150b555fa0)
|
||||||
@@ -2942,10 +3026,10 @@
|
|||||||
(symbol (lib_id "Device:R") (at 237.49 72.39 0) (unit 1)
|
(symbol (lib_id "Device:R") (at 237.49 72.39 0) (unit 1)
|
||||||
(in_bom yes) (on_board yes)
|
(in_bom yes) (on_board yes)
|
||||||
(uuid fe50da4c-5b14-4959-9cb1-4b2b431f31fd)
|
(uuid fe50da4c-5b14-4959-9cb1-4b2b431f31fd)
|
||||||
(property "Reference" "R?" (id 0) (at 239.268 71.2216 0)
|
(property "Reference" "R5" (id 0) (at 239.268 71.2216 0)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
)
|
)
|
||||||
(property "Value" "R" (id 1) (at 239.268 73.533 0)
|
(property "Value" "4k7" (id 1) (at 239.268 73.533 0)
|
||||||
(effects (font (size 1.27 1.27)) (justify left))
|
(effects (font (size 1.27 1.27)) (justify left))
|
||||||
)
|
)
|
||||||
(property "Footprint" "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder" (id 2) (at 235.712 72.39 90)
|
(property "Footprint" "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder" (id 2) (at 235.712 72.39 90)
|
||||||
@@ -2963,6 +3047,15 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
(symbol_instances
|
(symbol_instances
|
||||||
|
(path "/9db85383-a03f-4209-a928-87be53d1e345"
|
||||||
|
(reference "#PWR01") (unit 1) (value "+3.3V") (footprint "")
|
||||||
|
)
|
||||||
|
(path "/40a343f4-2d59-4a27-ab4f-ae28f587fed5"
|
||||||
|
(reference "#PWR02") (unit 1) (value "+3.3V") (footprint "")
|
||||||
|
)
|
||||||
|
(path "/6c9e14ce-f378-409f-83b0-3017c42aa43a"
|
||||||
|
(reference "#PWR03") (unit 1) (value "+3.3V") (footprint "")
|
||||||
|
)
|
||||||
(path "/e450da72-98c3-4b02-bd53-9f12a50ec903"
|
(path "/e450da72-98c3-4b02-bd53-9f12a50ec903"
|
||||||
(reference "#PWR0101") (unit 1) (value "GND") (footprint "")
|
(reference "#PWR0101") (unit 1) (value "GND") (footprint "")
|
||||||
)
|
)
|
||||||
@@ -3050,6 +3143,12 @@
|
|||||||
(path "/88bd6a1b-baf5-4675-82b2-2c94b1d8679e"
|
(path "/88bd6a1b-baf5-4675-82b2-2c94b1d8679e"
|
||||||
(reference "#PWR0129") (unit 1) (value "GND") (footprint "")
|
(reference "#PWR0129") (unit 1) (value "GND") (footprint "")
|
||||||
)
|
)
|
||||||
|
(path "/f19e33ae-597f-4b9a-8f2d-c4d9c6bead68"
|
||||||
|
(reference "#PWR0130") (unit 1) (value "+3.3V") (footprint "")
|
||||||
|
)
|
||||||
|
(path "/b2a70cb2-3ea0-4d7a-83e9-2996d0cf206b"
|
||||||
|
(reference "#PWR0131") (unit 1) (value "+3.3V") (footprint "")
|
||||||
|
)
|
||||||
(path "/00000000-0000-0000-0000-0000606a3dab"
|
(path "/00000000-0000-0000-0000-0000606a3dab"
|
||||||
(reference "#PWR0137") (unit 1) (value "+3.3V") (footprint "")
|
(reference "#PWR0137") (unit 1) (value "+3.3V") (footprint "")
|
||||||
)
|
)
|
||||||
@@ -3068,20 +3167,11 @@
|
|||||||
(path "/00000000-0000-0000-0000-0000608d2410"
|
(path "/00000000-0000-0000-0000-0000608d2410"
|
||||||
(reference "#PWR0151") (unit 1) (value "GND") (footprint "")
|
(reference "#PWR0151") (unit 1) (value "GND") (footprint "")
|
||||||
)
|
)
|
||||||
(path "/40a343f4-2d59-4a27-ab4f-ae28f587fed5"
|
|
||||||
(reference "#PWR?") (unit 1) (value "+3.3V") (footprint "")
|
|
||||||
)
|
|
||||||
(path "/6c9e14ce-f378-409f-83b0-3017c42aa43a"
|
|
||||||
(reference "#PWR?") (unit 1) (value "+3.3V") (footprint "")
|
|
||||||
)
|
|
||||||
(path "/9db85383-a03f-4209-a928-87be53d1e345"
|
|
||||||
(reference "#PWR?") (unit 1) (value "+3.3V") (footprint "")
|
|
||||||
)
|
|
||||||
(path "/00000000-0000-0000-0000-00006065cd79"
|
(path "/00000000-0000-0000-0000-00006065cd79"
|
||||||
(reference "C1") (unit 1) (value "NP") (footprint "Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder")
|
(reference "C1") (unit 1) (value "NP") (footprint "Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder")
|
||||||
)
|
)
|
||||||
(path "/79810dae-0a78-4064-835f-fd152b22a1ed"
|
(path "/79810dae-0a78-4064-835f-fd152b22a1ed"
|
||||||
(reference "C2") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder")
|
(reference "C2") (unit 1) (value "100n") (footprint "Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder")
|
||||||
)
|
)
|
||||||
(path "/00000000-0000-0000-0000-00006065ba95"
|
(path "/00000000-0000-0000-0000-00006065ba95"
|
||||||
(reference "C3") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder")
|
(reference "C3") (unit 1) (value "C") (footprint "Capacitor_SMD:C_0805_2012Metric_Pad1.18x1.45mm_HandSolder")
|
||||||
@@ -3134,20 +3224,26 @@
|
|||||||
(path "/644e1842-7b7f-4923-bdec-dc0f5dc47467"
|
(path "/644e1842-7b7f-4923-bdec-dc0f5dc47467"
|
||||||
(reference "R4") (unit 1) (value "0") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
(reference "R4") (unit 1) (value "0") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
||||||
)
|
)
|
||||||
|
(path "/fe50da4c-5b14-4959-9cb1-4b2b431f31fd"
|
||||||
|
(reference "R5") (unit 1) (value "4k7") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
||||||
|
)
|
||||||
(path "/00000000-0000-0000-0000-000060644009"
|
(path "/00000000-0000-0000-0000-000060644009"
|
||||||
(reference "R6") (unit 1) (value "R") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
(reference "R6") (unit 1) (value "4k7") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
||||||
)
|
)
|
||||||
(path "/00000000-0000-0000-0000-000060644d37"
|
(path "/00000000-0000-0000-0000-000060644d37"
|
||||||
(reference "R7") (unit 1) (value "R") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
(reference "R7") (unit 1) (value "4k7") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
||||||
)
|
|
||||||
(path "/43fa7042-3495-4cdb-99c3-d2fae29fcc2e"
|
|
||||||
(reference "R?") (unit 1) (value "R") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
|
||||||
)
|
)
|
||||||
(path "/af841cc7-411b-4fa7-bf12-b2b6bf90990e"
|
(path "/af841cc7-411b-4fa7-bf12-b2b6bf90990e"
|
||||||
(reference "R?") (unit 1) (value "R") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
(reference "R8") (unit 1) (value "4k7") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
||||||
)
|
)
|
||||||
(path "/fe50da4c-5b14-4959-9cb1-4b2b431f31fd"
|
(path "/43fa7042-3495-4cdb-99c3-d2fae29fcc2e"
|
||||||
(reference "R?") (unit 1) (value "R") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
(reference "R9") (unit 1) (value "4k7") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
||||||
|
)
|
||||||
|
(path "/2bcb8eff-5353-49d7-940f-1af0870f1ac9"
|
||||||
|
(reference "R10") (unit 1) (value "4k7") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
||||||
|
)
|
||||||
|
(path "/f4ba32ab-ab3d-4753-a0b7-a2a898ba4b27"
|
||||||
|
(reference "R11") (unit 1) (value "4k7") (footprint "Resistor_SMD:R_0805_2012Metric_Pad1.20x1.40mm_HandSolder")
|
||||||
)
|
)
|
||||||
(path "/0dfd3030-be04-4d31-ab7a-5e9d80308efc"
|
(path "/0dfd3030-be04-4d31-ab7a-5e9d80308efc"
|
||||||
(reference "U1") (unit 1) (value "WeMos_D1_mini") (footprint "Module:WEMOS_D1_mini_light")
|
(reference "U1") (unit 1) (value "WeMos_D1_mini") (footprint "Module:WEMOS_D1_mini_light")
|
||||||
@@ -3165,7 +3261,7 @@
|
|||||||
(reference "U5") (unit 1) (value "PCF8574") (footprint "Package_SO:SOIC-16W_7.5x10.3mm_P1.27mm")
|
(reference "U5") (unit 1) (value "PCF8574") (footprint "Package_SO:SOIC-16W_7.5x10.3mm_P1.27mm")
|
||||||
)
|
)
|
||||||
(path "/00000000-0000-0000-0000-0000608139a0"
|
(path "/00000000-0000-0000-0000-0000608139a0"
|
||||||
(reference "U6") (unit 1) (value "OKI-78SR-5_1.5-W36-C") (footprint "Converter_DCDC:Converter_DCDC_muRata_OKI-78SR_Vertical")
|
(reference "U6") (unit 1) (value "OKI-78SR-5_1.5-W36-C") (footprint "Converter_DCDC:Converter_DCDC_RECOM_R-78E-0.5_THT")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
3
Software/.gitignore
vendored
@@ -4,4 +4,5 @@ data/
|
|||||||
.vscode/c_cpp_properties.json
|
.vscode/c_cpp_properties.json
|
||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
.vscode/ipch
|
.vscode/ipch
|
||||||
wifi_credentials.ini
|
wifi_credentials.ini
|
||||||
|
__pycache__
|
145
Software/codegen/dtcs.py
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
import os
|
||||||
|
import time
|
||||||
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import filechecksum as fcs
|
||||||
|
|
||||||
|
def build_dtcs():
|
||||||
|
# Pfad zur Eingabedatei und Ausgabedatei
|
||||||
|
input_file = "src/dtc_defs.txt"
|
||||||
|
output_file = "include/dtc_defs.h"
|
||||||
|
json_output_file = "data_src/static/dtc_table.json"
|
||||||
|
|
||||||
|
# Überprüfen, ob das Verzeichnis existiert, andernfalls erstellen
|
||||||
|
json_output_dir = os.path.dirname(json_output_file)
|
||||||
|
if not os.path.exists(json_output_dir):
|
||||||
|
os.makedirs(json_output_dir)
|
||||||
|
|
||||||
|
# Mehrdimensionales Array zum Speichern der Zeilen aus der Eingabedatei
|
||||||
|
dtc_lines = []
|
||||||
|
|
||||||
|
# Lesen und analysieren der Eingabedatei
|
||||||
|
with open(input_file, "r", encoding="utf-8") as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith("#"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
parts = line.split(";")
|
||||||
|
if len(parts) == 5:
|
||||||
|
num, dtc_name, dtc_severity, title, description = [part.strip() for part in parts]
|
||||||
|
dtc_lines.append([int(num), dtc_name, dtc_severity, title, description])
|
||||||
|
|
||||||
|
# Überprüfen auf Duplikate in den DTC-Nummern und DTC-Namen
|
||||||
|
num_set = set()
|
||||||
|
dtc_name_set = set()
|
||||||
|
duplicates = []
|
||||||
|
|
||||||
|
for line in dtc_lines:
|
||||||
|
num, dtc_name, _, _, _ = line
|
||||||
|
if num in num_set:
|
||||||
|
duplicates.append(f"DTC-Nummer {num} ist ein Duplikat.")
|
||||||
|
else:
|
||||||
|
num_set.add(num)
|
||||||
|
|
||||||
|
if dtc_name in dtc_name_set:
|
||||||
|
duplicates.append(f"DTC-Name '{dtc_name}' ist ein Duplikat.")
|
||||||
|
else:
|
||||||
|
dtc_name_set.add(dtc_name)
|
||||||
|
|
||||||
|
if duplicates:
|
||||||
|
for duplicate in duplicates:
|
||||||
|
print(f"Fehler: {duplicate}")
|
||||||
|
raise ValueError("Duplicate DTC Data detected")
|
||||||
|
|
||||||
|
# Suchen nach DTC_NO_DTC und DTC_LAST_DTC
|
||||||
|
dtc_no_dtc_added = False
|
||||||
|
dtc_last_dtc_line = None
|
||||||
|
|
||||||
|
for line in dtc_lines:
|
||||||
|
_, dtc_name, _, _, _ = line
|
||||||
|
if dtc_name == "DTC_NO_DTC":
|
||||||
|
dtc_no_dtc_added = True
|
||||||
|
elif dtc_name == "DTC_LAST_DTC":
|
||||||
|
dtc_last_dtc_line = line
|
||||||
|
|
||||||
|
# Einen DTC für DTC_NO_DTC hinzufügen (wenn nicht vorhanden)
|
||||||
|
if not dtc_no_dtc_added:
|
||||||
|
dtc_lines.insert(0, [0, "DTC_NO_DTC", "DTC_NONE", "No Error", "No Error"])
|
||||||
|
|
||||||
|
# Falls DTC_LAST_DTC existiert, lösche es
|
||||||
|
if dtc_last_dtc_line:
|
||||||
|
dtc_lines.remove(dtc_last_dtc_line)
|
||||||
|
|
||||||
|
# Einen DTC für DTC_LAST_DTC hinzufügen (mit der höchsten Nummer)
|
||||||
|
if dtc_lines:
|
||||||
|
highest_num = max([line[0] for line in dtc_lines])
|
||||||
|
else:
|
||||||
|
highest_num = 0
|
||||||
|
|
||||||
|
dtc_lines.append([highest_num + 1, "DTC_LAST_DTC", "DTC_NONE", "Last Error", "Last Error"])
|
||||||
|
|
||||||
|
# Sortieren der Zeilen nach der Nummer aufsteigend
|
||||||
|
dtc_lines.sort(key=lambda x: x[0])
|
||||||
|
|
||||||
|
checksum = fcs.calculate_checksum(dtc_lines)
|
||||||
|
timestamp = int(time.time())
|
||||||
|
|
||||||
|
if fcs.read_and_compare_checksum(output_file, checksum):
|
||||||
|
print("Keine Änderungen im DTC-Headerfile erforderlich.")
|
||||||
|
else:
|
||||||
|
# DTC_NAME_CONSTANT-Makros initialisieren
|
||||||
|
dtc_macros = []
|
||||||
|
dtc_structs = []
|
||||||
|
|
||||||
|
# Verarbeiten der sortierten Zeilen
|
||||||
|
for i, line in enumerate(dtc_lines):
|
||||||
|
num, dtc_name, dtc_severity, title, description = line
|
||||||
|
dtc_macros.append(f"#define {dtc_name:<30} {num}")
|
||||||
|
comma = "," if i < len(dtc_lines) - 1 else " "
|
||||||
|
dtc_structs.append(f" {{ {dtc_name:<30}, {dtc_severity:<12} }}{comma} // {description}")
|
||||||
|
|
||||||
|
env = Environment(loader=FileSystemLoader('codegen/templates', encoding='utf-8'))
|
||||||
|
# Lade das Jinja2-Template aus der Datei
|
||||||
|
template = env.get_template('dtc_defs.h.j2')
|
||||||
|
|
||||||
|
# Erstelle ein Context-Dictionary mit den erforderlichen Daten
|
||||||
|
context = {
|
||||||
|
'timestamp_unix': timestamp,
|
||||||
|
'timestamp' : time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp)),
|
||||||
|
'date' : time.strftime('%d.%m.%Y', time.localtime(timestamp)),
|
||||||
|
'dtc_macros': dtc_macros, # Übergebe die dtc_macros-Liste direkt
|
||||||
|
'dtc_structs': dtc_structs, # Übergebe die dtc_structs-Liste direkt
|
||||||
|
'checksum' : checksum
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rendere das Template mit den Werten und erhalte den Header-Text
|
||||||
|
header_text = template.render(context)
|
||||||
|
|
||||||
|
# Schreibe den generierten Header-Text in die Header-Datei
|
||||||
|
with open(output_file, "w", encoding='utf-8') as f:
|
||||||
|
f.write(header_text)
|
||||||
|
|
||||||
|
print(f"Header-Datei wurde erstellt: {output_file}")
|
||||||
|
|
||||||
|
if fcs.read_and_compare_json_checksum(json_output_file, checksum):
|
||||||
|
print("Keine Änderungen im DTC-JSON-file erforderlich.")
|
||||||
|
else:
|
||||||
|
dtc_info = {
|
||||||
|
"codegenerator_checksum": checksum,
|
||||||
|
'timestamp' : time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp)),
|
||||||
|
"dtc_table_data": []
|
||||||
|
}
|
||||||
|
|
||||||
|
# Verarbeiten der sortierten Zeilen
|
||||||
|
for i, line in enumerate(dtc_lines):
|
||||||
|
num, dtc_name, dtc_severity, title, description = line
|
||||||
|
dtc_info["dtc_table_data"].append({"num": num, "title": title, "description": description})
|
||||||
|
|
||||||
|
# JSON-Datei mit UTF-8-Zeichencodierung erstellen
|
||||||
|
with open(json_output_file, 'w', encoding='utf-8') as json_f:
|
||||||
|
json.dump(dtc_info, json_f, ensure_ascii=False, indent=4, separators=(',', ': '))
|
||||||
|
|
||||||
|
print(f"JSON-Datei wurde erstellt: {json_output_file}")
|
45
Software/codegen/filechecksum.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Funktion zum Berechnen der SHA-256-Checksumme
|
||||||
|
def calculate_checksum(data):
|
||||||
|
sha256 = hashlib.sha256()
|
||||||
|
sha256.update(str(data).encode('utf-8'))
|
||||||
|
return sha256.hexdigest()
|
||||||
|
|
||||||
|
# Funktion zum Lesen und Vergleichen der Checksumme in einer Datei
|
||||||
|
def read_and_compare_checksum(file_path, expected_checksum):
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r') as file:
|
||||||
|
content = file.read()
|
||||||
|
# Suche nach der Zeile mit der Checksumme
|
||||||
|
checksum_line_start = content.find("// CODEGENERATOR_CHECKSUM:")
|
||||||
|
if checksum_line_start != -1:
|
||||||
|
# Extrahiere die Checksumme aus der Zeile
|
||||||
|
existing_checksum = content[checksum_line_start + len("// CODEGENERATOR_CHECKSUM:"):].strip()
|
||||||
|
# Vergleiche die Checksummen
|
||||||
|
if existing_checksum == expected_checksum:
|
||||||
|
return True
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass # Datei existiert nicht, was nicht schlimm ist
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def read_and_compare_json_checksum(json_file_path, expected_checksum):
|
||||||
|
try:
|
||||||
|
with open(json_file_path, 'r') as json_file:
|
||||||
|
# Lade das JSON aus der Datei
|
||||||
|
data = json.load(json_file)
|
||||||
|
|
||||||
|
# Überprüfe, ob "codegenerator_checksum" im JSON vorhanden ist
|
||||||
|
if "codegenerator_checksum" in data:
|
||||||
|
existing_checksum = data["codegenerator_checksum"]
|
||||||
|
|
||||||
|
# Vergleiche die Checksummen
|
||||||
|
if existing_checksum == expected_checksum:
|
||||||
|
return True
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass # Datei existiert nicht, was nicht schlimm ist
|
||||||
|
|
||||||
|
return False
|
181
Software/codegen/prepare_littlefs.py
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
# SCRIPT TO GZIP CRITICAL FILES FOR ACCELERATED WEBSERVING
|
||||||
|
# see also https://community.platformio.org/t/question-esp32-compress-files-in-data-to-gzip-before-upload-possible-to-spiffs/6274/10
|
||||||
|
|
||||||
|
|
||||||
|
import glob
|
||||||
|
import shutil
|
||||||
|
import gzip
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import platform
|
||||||
|
Import("env")
|
||||||
|
Import("projenv")
|
||||||
|
|
||||||
|
# Überprüfe die Betriebssystemplattform
|
||||||
|
if platform.system() == "Windows":
|
||||||
|
# Setze die Pfade zu den Tools für Windows
|
||||||
|
html_minifier_path = os.path.join(os.getenv("APPDATA"), "npm", "html-minifier.cmd")
|
||||||
|
uglifyjs_path = os.path.join(os.getenv("APPDATA"), "npm", "uglifyjs.cmd")
|
||||||
|
terser_path = os.path.join(os.getenv("APPDATA"), "npm", "terser.cmd")
|
||||||
|
cssnano_path = os.path.join(os.getenv("APPDATA"), "npm", "cssnano.cmd")
|
||||||
|
elif platform.system() == "Linux":
|
||||||
|
# Setze die Namen der Tools für Linux
|
||||||
|
html_minifier_path = "html-minifier"
|
||||||
|
uglifyjs_path = "uglifyjs"
|
||||||
|
terser_path = "terser"
|
||||||
|
cssnano_path = "cssnano"
|
||||||
|
else:
|
||||||
|
# Hier könntest du weitere Bedingungen für andere Betriebssysteme hinzufügen
|
||||||
|
raise Exception("Unterstütztes Betriebssystem nicht erkannt")
|
||||||
|
|
||||||
|
|
||||||
|
def minify_html(input_path, output_path):
|
||||||
|
subprocess.run([html_minifier_path, '--collapse-whitespace', '--remove-comments', input_path, '-o', output_path])
|
||||||
|
|
||||||
|
def minify_js(input_path, output_path):
|
||||||
|
subprocess.run([terser_path, input_path, '-o', output_path, '-c', '-m'])
|
||||||
|
|
||||||
|
def minify_css(input_path, output_path):
|
||||||
|
subprocess.run([cssnano_path, '--no-discardUnused', input_path, output_path])
|
||||||
|
|
||||||
|
def process_file(src_path, dest_path):
|
||||||
|
_, file_extension = os.path.splitext(src_path)
|
||||||
|
|
||||||
|
# Extrahiere den Ordnerpfad im Zielverzeichnis
|
||||||
|
dest_dir = os.path.dirname(dest_path)
|
||||||
|
|
||||||
|
# Erstelle den Ordner und alle dazugehörigen Unterordner, falls sie nicht existieren
|
||||||
|
os.makedirs(dest_dir, exist_ok=True)
|
||||||
|
|
||||||
|
if file_extension.lower() == '.js':
|
||||||
|
minify_js(src_path, dest_path)
|
||||||
|
elif file_extension.lower() == '.css':
|
||||||
|
minify_css(src_path, dest_path)
|
||||||
|
elif file_extension.lower() in ['.html', '.htm']:
|
||||||
|
minify_html(src_path, dest_path)
|
||||||
|
else:
|
||||||
|
# Kopiere nicht bearbeitbare Dateien direkt in den Zielordner
|
||||||
|
shutil.copy2(src_path, dest_path)
|
||||||
|
|
||||||
|
def strip_files(src_dir, dest_dir):
|
||||||
|
# Erstelle den Zielordner und alle dazugehörigen Unterordner, falls sie nicht existieren
|
||||||
|
os.makedirs(dest_dir, exist_ok=True)
|
||||||
|
|
||||||
|
# Durchlaufe alle Dateien und Unterverzeichnisse im Quellordner
|
||||||
|
for root, _, files in os.walk(src_dir):
|
||||||
|
for filename in files:
|
||||||
|
src_path = os.path.join(root, filename)
|
||||||
|
dest_path = os.path.relpath(src_path, src_dir)
|
||||||
|
dest_path = os.path.join(dest_dir, dest_path)
|
||||||
|
|
||||||
|
# Verarbeite nur Dateien (keine Unterverzeichnisse)
|
||||||
|
process_file(src_path, dest_path)
|
||||||
|
|
||||||
|
|
||||||
|
def gzip_file(src_path, dst_path):
|
||||||
|
|
||||||
|
with open(src_path, 'rb') as src, gzip.open(dst_path, 'wb') as dst:
|
||||||
|
for chunk in iter(lambda: src.read(4096), b""):
|
||||||
|
dst.write(chunk)
|
||||||
|
|
||||||
|
|
||||||
|
def getListOfFiles(dirName):
|
||||||
|
# create a list of file and sub directories
|
||||||
|
# names in the given directory
|
||||||
|
listOfFile = os.listdir(dirName)
|
||||||
|
allFiles = list()
|
||||||
|
# Iterate over all the entries
|
||||||
|
for entry in listOfFile:
|
||||||
|
# Create full path
|
||||||
|
fullPath = os.path.join(dirName, entry)
|
||||||
|
# If entry is a directory then get the list of files in this directory
|
||||||
|
if os.path.isdir(fullPath):
|
||||||
|
allFiles = allFiles + getListOfFiles(fullPath)
|
||||||
|
else:
|
||||||
|
allFiles.append(fullPath)
|
||||||
|
|
||||||
|
return allFiles
|
||||||
|
|
||||||
|
def remove_prefix(text, prefix):
|
||||||
|
if text.startswith(prefix):
|
||||||
|
return text[len(prefix):]
|
||||||
|
return text # or whatever
|
||||||
|
|
||||||
|
# Compress files from 'data_src/' to 'data/'
|
||||||
|
|
||||||
|
|
||||||
|
def gzip_webfiles(source, target, env):
|
||||||
|
# Filetypes to compress
|
||||||
|
filetypes_to_gzip = ['.css', '.png', '.js', '.ico', '.woff2', '.json']
|
||||||
|
print('\nGZIP: Starting gzip-Process for LittleFS-Image...\n')
|
||||||
|
data_src_dir_path = os.path.join(env.get('PROJECT_DIR'), 'data_src')
|
||||||
|
data_temp_dir_path = os.path.join(env.get('PROJECT_DIR'), 'data_stripped')
|
||||||
|
strip_files(data_src_dir_path, data_temp_dir_path)
|
||||||
|
data_dir_path = env.get('PROJECT_DATA_DIR')
|
||||||
|
# check if data and datasrc exist. If the first exists and not the second, it renames it
|
||||||
|
if(os.path.exists(data_dir_path) and not os.path.exists(data_temp_dir_path)):
|
||||||
|
print('GZIP: Directory "'+data_dir_path +
|
||||||
|
'" exists, "'+data_temp_dir_path+'" is not found.')
|
||||||
|
print('GZIP: Renaming "' + data_dir_path +
|
||||||
|
'" to "' + data_temp_dir_path + '"')
|
||||||
|
os.rename(data_dir_path, data_temp_dir_path)
|
||||||
|
# Delete the 'data' directory
|
||||||
|
if(os.path.exists(data_dir_path)):
|
||||||
|
print('GZIP: Deleting the "data" directory ' + data_dir_path)
|
||||||
|
shutil.rmtree(data_dir_path)
|
||||||
|
# Recreate empty 'data' directory
|
||||||
|
print('GZIP: Re-creating an empty data directory ' + data_dir_path)
|
||||||
|
os.mkdir(data_dir_path)
|
||||||
|
# Determine the files to compress
|
||||||
|
|
||||||
|
files_to_copy = []
|
||||||
|
files_to_gzip = []
|
||||||
|
|
||||||
|
all_data_src = getListOfFiles(data_temp_dir_path)
|
||||||
|
for file in all_data_src:
|
||||||
|
file_name, file_extension = os.path.splitext(file)
|
||||||
|
print(file_name + " has filetype " + file_extension)
|
||||||
|
if file_extension in filetypes_to_gzip:
|
||||||
|
files_to_gzip.append(file)
|
||||||
|
else:
|
||||||
|
filename_subdir = remove_prefix(file, data_temp_dir_path)
|
||||||
|
files_to_copy.append(filename_subdir)
|
||||||
|
|
||||||
|
for file in files_to_copy:
|
||||||
|
print('GZIP: Copying file from: ' + data_temp_dir_path + file + ' to: ' + data_dir_path + file)
|
||||||
|
os.makedirs(os.path.dirname(data_dir_path + file), exist_ok=True)
|
||||||
|
shutil.copy(data_temp_dir_path + file, data_dir_path + file)
|
||||||
|
# Compress and move files
|
||||||
|
|
||||||
|
was_error = False
|
||||||
|
try:
|
||||||
|
for source_file_path in files_to_gzip:
|
||||||
|
print('GZIP: compressing... ' + source_file_path)
|
||||||
|
filename_subdir = remove_prefix(source_file_path, data_temp_dir_path)
|
||||||
|
target_file_path = data_dir_path + filename_subdir
|
||||||
|
os.makedirs(os.path.dirname(target_file_path), exist_ok=True)
|
||||||
|
print('GZIP: Compressed... ' + target_file_path)
|
||||||
|
gzip_file(source_file_path, target_file_path + ".gz")
|
||||||
|
except IOError as e:
|
||||||
|
was_error = True
|
||||||
|
print('GZIP: Failed to compress file: ' + source_file_path)
|
||||||
|
# print( 'GZIP: EXCEPTION... {}'.format( e ) )
|
||||||
|
if was_error:
|
||||||
|
print('GZIP: Failure/Incomplete.\n')
|
||||||
|
else:
|
||||||
|
print('GZIP: Compressed correctly.\n')
|
||||||
|
shutil.rmtree(data_temp_dir_path)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def gzip_binffiles(source, target, env):
|
||||||
|
littlefsbin = target[0].get_abspath()
|
||||||
|
targetbin = os.path.join(os.path.dirname(littlefsbin), 'filesystem.fs')
|
||||||
|
shutil.copyfile(littlefsbin, targetbin)
|
||||||
|
gzip_file(targetbin, os.path.join(str(targetbin) + '.gz'))
|
||||||
|
os.remove(targetbin)
|
||||||
|
return
|
||||||
|
|
||||||
|
# IMPORTANT, this needs to be added to call the routine
|
||||||
|
env.AddPreAction('$BUILD_DIR/littlefs.bin', gzip_webfiles)
|
||||||
|
env.AddPostAction('$BUILD_DIR/littlefs.bin', gzip_binffiles)
|
14
Software/codegen/run_pre.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Import("env") # pylint: disable=undefined-variable
|
||||||
|
env.Execute("\"$PYTHONEXE\" -m pip install jinja2")
|
||||||
|
|
||||||
|
import struct2json
|
||||||
|
import dtcs
|
||||||
|
from os import popen
|
||||||
|
|
||||||
|
git_revision = popen('git rev-parse --short HEAD').read().strip()
|
||||||
|
|
||||||
|
env.Replace(PROGNAME="firmware_%s.fw" % git_revision)
|
||||||
|
env.Append(CPPDEFINES=[('GIT_REV', '\\"{}\\"'.format(git_revision))])
|
||||||
|
|
||||||
|
struct2json.struct2json()
|
||||||
|
dtcs.build_dtcs()
|
113
Software/codegen/struct2json.py
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
import os
|
||||||
|
import time
|
||||||
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
import re
|
||||||
|
|
||||||
|
import filechecksum as fcs
|
||||||
|
|
||||||
|
# Pfad zur Eingabedatei und Ausgabedatei
|
||||||
|
input_file = "include/eeprom.h"
|
||||||
|
output_sourcefile = "src/struct2json.cpp"
|
||||||
|
output_headerfile = "include/struct2json.h"
|
||||||
|
# Liste der zu suchenden Variablen/Structs
|
||||||
|
variable_names = ['ConfigData', 'PersistenceData']
|
||||||
|
|
||||||
|
def get_types(file_content, variable_names):
|
||||||
|
result = {}
|
||||||
|
|
||||||
|
# Entferne Kommentare, um unerwünschte Störungen zu vermeiden
|
||||||
|
file_content = re.sub(r'\/\*.*?\*\/', '', file_content, flags=re.DOTALL)
|
||||||
|
file_content = re.sub(r'\/\/.*', '', file_content)
|
||||||
|
|
||||||
|
for var_name in variable_names:
|
||||||
|
# Erstelle ein reguläres Ausdrucksmuster, um den Typ der Variable zu extrahieren
|
||||||
|
pattern = re.compile(r'\b(?:extern\s+)?(\w+)\s+' + re.escape(var_name) + r'\s*;')
|
||||||
|
match = pattern.search(file_content)
|
||||||
|
|
||||||
|
if match:
|
||||||
|
# Extrahiere den Typ aus dem Treffer
|
||||||
|
type_match = match.group(1)
|
||||||
|
result[var_name] = type_match
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def extract_struct_fields(file_content, variable_types):
|
||||||
|
result = {}
|
||||||
|
|
||||||
|
# Entferne Kommentare, um unerwünschte Störungen zu vermeiden
|
||||||
|
file_content = re.sub(r'\/\*.*?\*\/', '', file_content, flags=re.DOTALL)
|
||||||
|
file_content = re.sub(r'\/\/.*', '', file_content)
|
||||||
|
|
||||||
|
for var_name, var_type in variable_types.items():
|
||||||
|
# Erstelle ein reguläres Ausdrucksmuster, um das Strukturfeld zu extrahieren
|
||||||
|
pattern = re.compile(r'typedef\s+struct\s*{([^}]*)}\s*' + re.escape(var_type) + r'\s*;')
|
||||||
|
match = pattern.search(file_content)
|
||||||
|
|
||||||
|
if match:
|
||||||
|
# Extrahiere die Felder aus dem Treffer
|
||||||
|
fields_match = re.findall(r'\b(\w+)\s+(\w+)(?:\[(\d+)\])?\s*;', match.group(1))
|
||||||
|
if fields_match:
|
||||||
|
result[var_name] = {'type': var_type, 'fields': {}}
|
||||||
|
for field_type, field_name, array_size in fields_match:
|
||||||
|
if array_size:
|
||||||
|
result[var_name]['fields'][field_name] = {'type': field_type, 'size': int(array_size)}
|
||||||
|
else:
|
||||||
|
result[var_name]['fields'][field_name] = {'type': field_type}
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def struct2json():
|
||||||
|
# Überprüfen, ob die Verzeichnisse existieren, andernfalls erstellen
|
||||||
|
output_dir_source = os.path.dirname(output_sourcefile)
|
||||||
|
if not os.path.exists(output_dir_source):
|
||||||
|
os.makedirs(output_dir_source)
|
||||||
|
output_dir_header = os.path.dirname(output_headerfile)
|
||||||
|
if not os.path.exists(output_dir_header):
|
||||||
|
os.makedirs(output_dir_header)
|
||||||
|
|
||||||
|
# Unix-Zeitstempel hinzufügen
|
||||||
|
timestamp = int(time.time())
|
||||||
|
|
||||||
|
# Parse structs
|
||||||
|
with open(input_file, 'r') as file:
|
||||||
|
content = file.read()
|
||||||
|
|
||||||
|
variable_types = get_types(content, variable_names)
|
||||||
|
structs = extract_struct_fields(content, variable_types)
|
||||||
|
checksum = fcs.calculate_checksum(structs)
|
||||||
|
|
||||||
|
env = Environment(loader=FileSystemLoader('codegen/templates', encoding='utf-8'))
|
||||||
|
# Lade das Jinja2-Template aus der Datei
|
||||||
|
template_c = env.get_template('struct2json.cpp.j2')
|
||||||
|
template_h = env.get_template('struct2json.h.j2')
|
||||||
|
|
||||||
|
# Erstelle ein Context-Dictionary mit den erforderlichen Daten
|
||||||
|
context = {
|
||||||
|
'timestamp_unix': timestamp,
|
||||||
|
'timestamp' : time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp)),
|
||||||
|
'date' : time.strftime('%d.%m.%Y', time.localtime(timestamp)),
|
||||||
|
'structs': structs,
|
||||||
|
'checksum': checksum
|
||||||
|
}
|
||||||
|
|
||||||
|
# Überprüfe, ob die Checksummen übereinstimmen
|
||||||
|
if fcs.read_and_compare_checksum(output_sourcefile, checksum):
|
||||||
|
print("Keine Änderungen in der Source-Datei erforderlich.")
|
||||||
|
else:
|
||||||
|
# Rendere das Template mit den Werten und erhalte den Source-Text
|
||||||
|
source_text = template_c.render(context)
|
||||||
|
# Schreibe den generierten Source-Text in die Source-Datei
|
||||||
|
with open(output_sourcefile, "w", encoding='utf-8') as f:
|
||||||
|
f.write(source_text)
|
||||||
|
print(f"Source-Datei wurde erstellt: {output_sourcefile}")
|
||||||
|
|
||||||
|
# Überprüfe, ob die Checksummen übereinstimmen
|
||||||
|
if fcs.read_and_compare_checksum(output_headerfile, checksum):
|
||||||
|
print("Keine Änderungen in der Header-Datei erforderlich.")
|
||||||
|
else:
|
||||||
|
# Rendere das Template mit den Werten und erhalte den Header-Text
|
||||||
|
header_text = template_h.render(context)
|
||||||
|
# Schreibe den generierten Header-Text in die Header-Datei
|
||||||
|
with open(output_headerfile, "w", encoding='utf-8') as f:
|
||||||
|
f.write(header_text)
|
||||||
|
print(f"Header-Datei wurde erstellt: {output_headerfile}")
|
54
Software/codegen/templates/dtc_defs.h.j2
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* @file dtc_defs.h
|
||||||
|
*
|
||||||
|
* @brief Header file for Diagnostic Trouble Code (DTC) definitions in the DE-Timer application.
|
||||||
|
*
|
||||||
|
* This file contains definitions for Diagnostic Trouble Codes (DTC) in the DE-Timer project.
|
||||||
|
* It includes enums for DTC active status, severity levels, and specific DTC codes.
|
||||||
|
* The file also defines an array of DTC definitions and a timestamp indicating the generation time.
|
||||||
|
*
|
||||||
|
* @note This file is auto-generated by a script on {{ timestamp }}.
|
||||||
|
*
|
||||||
|
* @author Marcel Peterkau
|
||||||
|
* @date {{ date }}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DTC_DEFS_H
|
||||||
|
#define DTC_DEFS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef uint32_t DTCNum_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DTC_INACTIVE,
|
||||||
|
DTC_ACTIVE,
|
||||||
|
DTC_PREVIOUS
|
||||||
|
} DTCActive_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DTC_NONE,
|
||||||
|
DTC_INFO,
|
||||||
|
DTC_WARN,
|
||||||
|
DTC_CRITICAL
|
||||||
|
} DTCSeverity_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DTCNum_t code;
|
||||||
|
DTCSeverity_t severity;
|
||||||
|
} DTC_t;
|
||||||
|
|
||||||
|
{% for dtc in dtc_macros -%}
|
||||||
|
{{ dtc }}
|
||||||
|
{% endfor %}
|
||||||
|
const DTC_t dtc_definitions[] = {
|
||||||
|
{% for struct in dtc_structs -%}
|
||||||
|
{{ struct }}
|
||||||
|
{% endfor -%}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DTC_DEFS_H
|
||||||
|
|
||||||
|
// CODEGENERATOR_CHECKSUM: {{ checksum }}
|
25
Software/codegen/templates/struct2json.cpp.j2
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* @file struct2json.cpp
|
||||||
|
*
|
||||||
|
* @brief Implementation file for converting structs to JSON objects.
|
||||||
|
*
|
||||||
|
* @note This file is auto-generated by a script on {{ timestamp }}.
|
||||||
|
*
|
||||||
|
* @author Marcel Peterkau
|
||||||
|
* @date {{ date }}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "struct2json.h"
|
||||||
|
|
||||||
|
{% for var_name, var_info in structs.items() -%}
|
||||||
|
void generateJsonObject_{{ var_name }}(JsonObject data)
|
||||||
|
{
|
||||||
|
{% for field_name, field_type in var_info['fields'].items() -%}
|
||||||
|
data["{{ field_name }}"] = {{ var_name }}.{{ field_name }};
|
||||||
|
{% endfor -%}
|
||||||
|
}
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
// CODEGENERATOR_CHECKSUM: {{ checksum }}
|
26
Software/codegen/templates/struct2json.h.j2
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* @file struct2json.h
|
||||||
|
*
|
||||||
|
* @brief Header file for converting structs to JSON objects.
|
||||||
|
*
|
||||||
|
* @note This file is auto-generated by a script on {{ timestamp }}.
|
||||||
|
*
|
||||||
|
* @author Marcel Peterkau
|
||||||
|
* @date {{ date }}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _STRUCT2JSON_H_
|
||||||
|
#define _STRUCT2JSON_H_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
#include "eeprom.h"
|
||||||
|
|
||||||
|
{% for var_name, var_info in structs.items() -%}
|
||||||
|
void generateJsonObject_{{ var_name }}(JsonObject data);
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
#endif /* _STRUCT2JSON_H_ */
|
||||||
|
|
||||||
|
// CODEGENERATOR_CHECKSUM: {{ checksum }}
|
381
Software/data_src/index.htm
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>KTM CAN Chain Oiler</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="static/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="static/css/custom.css">
|
||||||
|
<link rel="stylesheet" href="static/css/tweaks.css">
|
||||||
|
<script src="static/js/jquery.min.js"></script>
|
||||||
|
<script src="static/js/bootstrap.min.js"></script>
|
||||||
|
<script src="static/js/websocket.js"></script>
|
||||||
|
<script src="static/js/dtc_table.js"></script>
|
||||||
|
<script src="static/js/script.js"></script>
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="static/img/apple-touch-icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="static/img/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="static/img/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="static/img/site.webmanifest">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<!-- Connection-Overlay -->
|
||||||
|
<div id="overlay">
|
||||||
|
<div class="overlay-content">
|
||||||
|
<p>Verbinde...</p>
|
||||||
|
<span class="loader"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Connection-Overlay -->
|
||||||
|
<!-- Notification-Container -->
|
||||||
|
<div id="notification-container" class="notification-container"></div>
|
||||||
|
<!-- Notification-Container -->
|
||||||
|
|
||||||
|
<nav class="navbar fixed-top navbar-dark bg-primary" id="navbar1">
|
||||||
|
<a class="navbar-brand" href="#">
|
||||||
|
<img src="static/img/logo.png" width="30" height="30" class="d-inline-block align-top mr-1" alt="">
|
||||||
|
DE Airsoft Timer
|
||||||
|
</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsingNavbar"
|
||||||
|
aria-controls="collapsingNavbar" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse" id="collapsingNavbar">
|
||||||
|
<ul class="navbar-nav nav mr-auto mt-2 mt-lg-0">
|
||||||
|
|
||||||
|
<li class="nav-item"><a class="nav-link active" role="tab" data-toggle="tab" href="#tab_home">Home</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" role="tab" data-toggle="tab" href="#tab_maintenance">Wartung</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" role="tab" data-toggle="tab" href="#tab_source">Einstellungen</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" role="tab" data-toggle="tab" href="#tab_fwupdate">Update</a></li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="container">
|
||||||
|
|
||||||
|
<!-- Tabs Content -->
|
||||||
|
<div class="tab-content">
|
||||||
|
<!-- Div Tab Home-->
|
||||||
|
<div id="tab_home" class="tab-pane fade show active" role="tabpanel">
|
||||||
|
<div class="col text-center">
|
||||||
|
<div class="jumbotron">
|
||||||
|
<img src="static/img/logo.png" width="120" height="120" class="img-fluid" alt="">
|
||||||
|
<h3 class="pt-3">KTM CAN Chain Lube</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Div Group Battery remain -->
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<h4>Akkuladestand</h4>
|
||||||
|
<div class="progress">
|
||||||
|
<div id="battery_level" class="data-battery_level progress-bar text-light" role="progressbar" aria-valuenow="0"
|
||||||
|
aria-valuemin="0" aria-valuemax="100" style="width: 0%">
|
||||||
|
0
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
<!-- Div Group Battery remain -->
|
||||||
|
<!-- Div Group current Mode -->
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<h4>aktueller Modus</h4>
|
||||||
|
<input class="data-systemstatus form-control" type="text" id="sysstatus" readonly>
|
||||||
|
</p>
|
||||||
|
<!-- Div Group current Mode -->
|
||||||
|
<!-- Div Group Faction Points -->
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<h4>aktueller Punktestand</h4>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div id="header_faction1" class="col text-center data-name_faction1 text-white p-3">%NAME_FAC_1%</div>
|
||||||
|
<div id="header_faction2" class="col text-center data-name_faction2 text-white p-3">%NAME_FAC_2%</div>
|
||||||
|
<div id="header_faction3" class="col text-center data-name_faction3 text-white p-3">%NAME_FAC_3%</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col bg-dark text-white p-3"><img src="static/img/logo_fac1.png"
|
||||||
|
class="rounded mx-auto img-fluid d-block" alt="...">
|
||||||
|
</div>
|
||||||
|
<div class="col bg-dark text-white p-3"><img src="static/img/logo_fac2.png"
|
||||||
|
class="rounded mx-auto img-fluid d-block" alt="...">
|
||||||
|
</div>
|
||||||
|
<div class="col bg-dark text-white p-3"><img src="static/img/logo_fac3.png"
|
||||||
|
class="rounded mx-auto img-fluid d-block" alt="...">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div id="time_faction1" class="data-time_faction1 col text-center bg-secondary text-white p-3 format-time">0</div>
|
||||||
|
<div id="time_faction2" class="data-time_faction2 col text-center bg-secondary text-white p-3 format-time">0</div>
|
||||||
|
<div id="time_faction3" class="data-time_faction3 col text-center bg-secondary text-white p-3 format-time">0</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
<!-- Div GroupFaction Points -->
|
||||||
|
<!-- Div Group DTC Table -->
|
||||||
|
<div id="dtc_container" hidden>
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<h4>Fehlercodes</h4>
|
||||||
|
<table class="table" id="dtc_table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th class="col-6" scope="col">Zeitstempel</th>
|
||||||
|
<th class="col-2" scope="col">Fehlercode</th>
|
||||||
|
<th class="col-2" scope="col">Schwere</th>
|
||||||
|
<th class="col-2" scope="col">Aktiv</th>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<!-- Div Group DTC Table -->
|
||||||
|
</div>
|
||||||
|
<!-- Div Tab Home-->
|
||||||
|
|
||||||
|
<!-- Div Tab Maintenance -->
|
||||||
|
<div id="tab_maintenance" class="tab-pane fade" role="tabpanel">
|
||||||
|
<h3>Wartung</h3>
|
||||||
|
<!-- Div Group Reset Timers -->
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<h4>Punkte zurücksetzen</h4>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col text-center">
|
||||||
|
<button id="reset-timer" class="btn-wsevent btn btn-outline-primary ml-2">Timer zurücksetzen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
<!-- Div Group Reset Timers -->
|
||||||
|
<!-- Div Group LiveDebug -->
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<h4>Live Debug</h4>
|
||||||
|
<div class="form-group row">
|
||||||
|
<textarea class="form-control" spellcheck="false" id="livedebug-out" rows="3" readonly></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col text-center">
|
||||||
|
<button id="debugstart" class="btn-wsevent btn btn-outline-primary ml-2">Start</button>
|
||||||
|
<button id="debugstop" class="btn-wsevent btn btn-outline-primary ml-2">Stop</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
<!-- Div Group LiveDebug -->
|
||||||
|
<!-- Div Group Device Reboot -->
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<h4>Gerät neustarten</h4>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col text-center">
|
||||||
|
<button id="reboot" class="btn-wsevent confirm btn btn-outline-primary">Reboot</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
<!-- Div Group Device Reboot -->
|
||||||
|
</div>
|
||||||
|
<!-- Div Tab Maintenance -->
|
||||||
|
|
||||||
|
<!-- Div Tab Settings-->
|
||||||
|
<div id="tab_source" class="tab-pane fade" role="tabpanel">
|
||||||
|
<h3>Einstellungen</h3>
|
||||||
|
<!-- Div Group Battery Type -->
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<h4>Akku</h4>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="batterytype" class="control-label col-4">Akku-Variante</label>
|
||||||
|
<div class="col-8">
|
||||||
|
<select id="batterytype" class="set-wsevent data-batterytype select form-control">
|
||||||
|
<option value="Undefined">Undefined</option>
|
||||||
|
<option value="LiPo3S">LiPo 3S</option>
|
||||||
|
<option value="LiPo2S">LiPo 2S</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
<!-- Div Group Battery Type -->
|
||||||
|
<!-- Div Group Timer Settings -->
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<h4>Timer Einstellungen</h4>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="active_faction_on_reboot" class="control-label col-4">Aktive Fraktion wiederherstellen</label>
|
||||||
|
<div class="col-8">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="set-wsevent data-active_faction_on_reboot form-check-input" type="checkbox" id="active_faction_on_reboot">
|
||||||
|
<label class="form-check-label" for="active_faction_on_reboot">
|
||||||
|
aktivieren
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="name_faction1" class="control-label col-4">Faktion 1</label>
|
||||||
|
<div class="col-8">
|
||||||
|
<input id="name_faction1" type="text" class="set-wsevent data-name_faction1 form-control" required="required">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<span class="input-group-text">max. 32 Zeichen</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="name_faction2" class="control-label col-4">Faktion 2</label>
|
||||||
|
<div class="col-8">
|
||||||
|
<input id="name_faction2" type="text" class="set-wsevent data-name_faction2 form-control" required="required">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<span class="input-group-text">max. 32 Zeichen</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="name_faction3" class="control-label col-4">Faktion 3</label>
|
||||||
|
<div class="col-8">
|
||||||
|
<input id="name_faction3" type="text" class="set-wsevent data-name_faction3 form-control" required="required">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<span class="input-group-text">max. 32 Zeichen</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Div Group Timer Settings -->
|
||||||
|
<!-- Div Group Save Button-->
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col text-center">
|
||||||
|
<button id="settingssave" class="btn-wsevent btn btn-outline-primary">Speichern</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<!-- Div Tab Settings -->
|
||||||
|
|
||||||
|
<!-- Div Tab Firmware Update-->
|
||||||
|
<div id="tab_fwupdate" class="tab-pane fade" role="tabpanel">
|
||||||
|
<h3>Firmware</h3>
|
||||||
|
<!-- Div Group VersionInfo -->
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<h4>Version-Info</h4>
|
||||||
|
<table class="table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th class="col-7" scope="col">Parameter</td>
|
||||||
|
<th class="col-5" scope="col">Value</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Firmware Version</td>
|
||||||
|
<td>%SW_VERSION%</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Flash Version</td>
|
||||||
|
<td>%FS_VERSION%</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Git Revision</td>
|
||||||
|
<td>%GIT_REV%</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</p>
|
||||||
|
<!-- Div Group VersionInfo -->
|
||||||
|
<!-- Div Group EEPROM Backup -->
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<h4>EEPROM-Backup</h4>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col text-center">
|
||||||
|
<a class="btn btn-outline-primary" href="eejson" role="button" id="ee-backup-download">Download</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
<!-- Div Group EEPROM Backup -->
|
||||||
|
<!-- Div Group EEPROM Restore -->
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<h4>EEPROM-Restore</h4>
|
||||||
|
<form method='POST' action='eeRestore' enctype='multipart/form-data'>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="custom-file">
|
||||||
|
<input type="file" name="ee-restore-file" class="custom-file-input" id="ee-restore-file" accept=".ee.json"
|
||||||
|
required />
|
||||||
|
<label class="custom-file-label" for="ee-restore-file">EEPROM-Backup auswählen</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col text-center">
|
||||||
|
<button name="submit" type="submit" class="btn btn-outline-primary">Restore starten</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</p>
|
||||||
|
<!-- Div Group EEPROM Restore -->
|
||||||
|
<!-- Div Group Firmware Update -->
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<h4>Firmware-Update</h4>
|
||||||
|
<form method='POST' action='doUpdate' enctype='multipart/form-data'>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="custom-file">
|
||||||
|
<input type="file" name="fw-update-file" class="custom-file-input" id="fw-update-file"
|
||||||
|
accept=".fw.bin,.fs.gz" required />
|
||||||
|
<label class="custom-file-label" for="fw-update-file">Firmware-Update auswählen</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col text-center">
|
||||||
|
<button name="submit" type="submit" class="btn btn-outline-primary">Update starten</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</p>
|
||||||
|
<!-- Div Group Firmware Update -->
|
||||||
|
</div>
|
||||||
|
<!-- Div Tab Firmware Update-->
|
||||||
|
</div>
|
||||||
|
<!-- Tabs Content -->
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
|
||||||
|
<footer class="page-footer navbar-dark bg-primary font-small fixed-bottom">
|
||||||
|
<div class="container-fluid text-center">
|
||||||
|
<div class="footer-copyright text-center py-3">
|
||||||
|
<span class="text-muted">© 2023 -
|
||||||
|
<a class="text-reset fw-bold" href="https://eventronics.de/">Marcel Peterkau</a></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
|
||||||
|
<!-- Modal Dialog -->
|
||||||
|
|
||||||
|
<div class="modal fade" id="dtcModal" tabindex="-1" role="dialog" aria-labelledby="dtcModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="dtcModalLabel">DTC-Description</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p class="dtc-desc">DTC Description</p>
|
||||||
|
<p class="dtc-debugval">DTC DebugVal</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal Dialog -->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
10003
Software/data_src/static/css/bootstrap.min.css
vendored
Normal file
8441
Software/data_src/static/css/custom.css
Normal file
90
Software/data_src/static/css/tweaks.css
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Comfortaa';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 300;
|
||||||
|
src: url(../fonts/comfortaa.woff2) format('woff2');
|
||||||
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
padding-top: 70px;
|
||||||
|
margin-bottom: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
height: 2px;
|
||||||
|
border-width: 0;
|
||||||
|
color: gray;
|
||||||
|
background-color: gray
|
||||||
|
}
|
||||||
|
|
||||||
|
.dtc-debugval {
|
||||||
|
color: #F2771A;
|
||||||
|
font: 0.8rem Inconsolata, monospace;
|
||||||
|
background-color: black;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#overlay {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.8); /* Dunkler Hintergrund mit Transparenz */
|
||||||
|
color: white; /* Textfarbe */
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 9999; /* Stellen Sie sicher, dass es über anderen Elementen liegt */
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay-content {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
width: 96px;
|
||||||
|
height: 96px;
|
||||||
|
border: 12px solid #FFF;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
animation: rotation 1s linear infinite;
|
||||||
|
}
|
||||||
|
.loader::after {
|
||||||
|
content: '';
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 12px solid transparent;
|
||||||
|
border-bottom-color: #FF3D00;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotation {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 30%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification {
|
||||||
|
margin-bottom: 20px; /* Fügen Sie bei Bedarf weitere Stile hinzu */
|
||||||
|
}
|
96
Software/data_src/static/dtc_table.json
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
"codegenerator_checksum": "313d59949b074024df3c5d796f65e3bd518e34f0bb171185c30f008f21c19d30",
|
||||||
|
"timestamp": "2024-05-30 21:56:51",
|
||||||
|
"dtc_table_data": [
|
||||||
|
{
|
||||||
|
"num": 0,
|
||||||
|
"title": "No Error",
|
||||||
|
"description": "No Error"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 1,
|
||||||
|
"title": "Akku leer",
|
||||||
|
"description": "Akku ist komplett leer. Den Akku aufladen!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 2,
|
||||||
|
"title": "Akku niedrig",
|
||||||
|
"description": "Akku ist unter der Warnschwelle. Den Akku demnächst aufladen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 3,
|
||||||
|
"title": "kein EEPROM erkannt",
|
||||||
|
"description": "Es wurde kein EEPROM gefunden. Dies lässt einen Hardware-Defekt vermuten."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 4,
|
||||||
|
"title": "EEPROM CFG Checksumme",
|
||||||
|
"description": "Die Checksumme der Config-Partition des EEPROM ist ungültig. Setzen sie den EEPROM-Bereich 'CFG' im Menu 'Wartung' zurück"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 5,
|
||||||
|
"title": "EEPROM PDS Checksumme",
|
||||||
|
"description": "Die Checksumme der Betriebsdaten-Partition des EEPROM ist ungültig. Setzen sie den EEPROM-Bereich 'PDS' im Menu 'Wartung' zurück"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 6,
|
||||||
|
"title": "EEPROM PDS Adresse",
|
||||||
|
"description": "Die Adresse der Betriebsdaten-Partition im EEPROM ist ungültig. Setzen sie den EEPROM-Bereich 'PDS' im Menu 'Wartung' zurück"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 7,
|
||||||
|
"title": "EEPROM Version falsch",
|
||||||
|
"description": "Die Layout-Version des EEPROM stimmt nicht mit der Firmware-Version überein. Setzen sie den EEPROM-Bereich 'CFG' im Menu 'Wartung' zurück"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 8,
|
||||||
|
"title": "Flashspeicher Fehler",
|
||||||
|
"description": "Der Flashspeicher konnte nicht initialisiert werden. Aktualisieren sie Flash & Firmware"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 9,
|
||||||
|
"title": "Flashversion falsch",
|
||||||
|
"description": "Die Version des Flashspeicher stimmt nicht mit der Firmware-Version überein. Aktualisieren sie den Flash mit der passenden Update-Datei"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 10,
|
||||||
|
"title": "Keine Akkuüberwachung",
|
||||||
|
"description": "Es wurde keine Akkuüberwachung über I2C gefunden, Prüfen sie die Hardware!"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 11,
|
||||||
|
"title": "LoRa-Transceiver Error",
|
||||||
|
"description": "Es konnte keine Verbindung zum LoRa-Transceiver hergestellt werden. Prüfen Sie die Hardware auf Defekte"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 12,
|
||||||
|
"title": "Config-Validierung",
|
||||||
|
"description": "Ein oder mehrer Einstellungswerte sind ausserhalb plausibler Werte. Prüfen Sie Ihre Einstellungen"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 13,
|
||||||
|
"title": "EEPROM-Migration",
|
||||||
|
"description": "Es wurde ein altes EEPROm Image erkannt, konnte aber nicht migriert werden. EEPROM manuell zurück setzen und neue Einstellunge speichern."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 14,
|
||||||
|
"title": "Dummy-DTC Info",
|
||||||
|
"description": "Ein Dummy-DTC der Schwere \"Info\" für Debugging-Zwecke"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 15,
|
||||||
|
"title": "Dummy-DTC Warnung",
|
||||||
|
"description": "Ein Dummy-DTC der Schwere \"Warnung\" für Debugging-Zwecke"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 16,
|
||||||
|
"title": "Dummy-DTC Kritisch",
|
||||||
|
"description": "Ein Dummy-DTC der Schwere \"Kritisch\" für Debugging-Zwecke"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"num": 17,
|
||||||
|
"title": "Last Error",
|
||||||
|
"description": "Last Error"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
BIN
Software/data_src/static/fonts/comfortaa.woff2
Normal file
BIN
Software/data_src/static/img/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
Software/data_src/static/img/android-chrome-256x256.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
Software/data_src/static/img/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 30 KiB |
9
Software/data_src/static/img/browserconfig.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<browserconfig>
|
||||||
|
<msapplication>
|
||||||
|
<tile>
|
||||||
|
<square150x150logo src="/mstile-150x150.png"/>
|
||||||
|
<TileColor>#da532c</TileColor>
|
||||||
|
</tile>
|
||||||
|
</msapplication>
|
||||||
|
</browserconfig>
|
BIN
Software/data_src/static/img/critical.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
Software/data_src/static/img/favicon-16x16.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
Software/data_src/static/img/favicon-32x32.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
Software/data_src/static/img/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
Software/data_src/static/img/info.png
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
Software/data_src/static/img/logo.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
Software/data_src/static/img/logo_fac1.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
Software/data_src/static/img/logo_fac2.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
Software/data_src/static/img/logo_fac3.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
Software/data_src/static/img/mstile-150x150.png
Normal file
After Width: | Height: | Size: 18 KiB |
345
Software/data_src/static/img/safari-pinned-tab.svg
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="300.000000pt" height="300.000000pt" viewBox="0 0 300.000000 300.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<metadata>
|
||||||
|
Created by potrace 1.14, written by Peter Selinger 2001-2017
|
||||||
|
</metadata>
|
||||||
|
<g transform="translate(0.000000,300.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M210 2778 c1 -198 2 -221 15 -204 13 18 17 18 41 5 31 -16 41 -36 26
|
||||||
|
-51 -8 -8 -15 -8 -25 0 -19 16 -49 -22 -53 -69 -3 -30 1 -38 16 -42 26 -7 25
|
||||||
|
-27 -1 -34 -18 -5 -20 -11 -15 -47 3 -23 6 -48 5 -56 0 -8 -2 -168 -4 -355
|
||||||
|
l-4 -340 31 -18 c29 -17 31 -16 69 5 22 12 38 27 35 33 -2 7 0 18 5 26 7 11 9
|
||||||
|
11 9 -3 0 -26 13 -23 93 25 39 24 98 58 130 76 31 18 57 38 58 44 0 7 1 63 1
|
||||||
|
125 1 87 -2 116 -14 130 -26 29 -30 59 -13 92 8 16 19 30 23 30 8 0 7 212 -2
|
||||||
|
235 -3 8 -2 15 2 15 10 0 8 62 -2 78 -4 7 -5 12 -1 12 3 0 1 9 -5 20 -6 11
|
||||||
|
-17 20 -25 20 -8 0 -15 5 -15 11 0 16 -26 39 -45 39 -12 0 -15 6 -10 21 8 26
|
||||||
|
78 139 86 139 3 0 11 -36 18 -80 13 -79 23 -101 36 -80 4 7 11 8 18 1 14 -11
|
||||||
|
36 -14 103 -12 l52 1 25 53 c15 28 40 67 56 85 29 31 31 32 51 15 27 -23 25
|
||||||
|
-37 -10 -100 l-30 -53 75 0 c41 0 74 3 74 8 -3 18 2 32 11 32 6 0 10 -9 10
|
||||||
|
-20 0 -17 7 -20 39 -20 29 0 41 5 44 18 4 15 5 15 6 0 1 -13 13 -18 54 -20 99
|
||||||
|
-6 227 3 227 15 0 7 9 23 19 37 l19 24 18 -37 c19 -39 32 -43 118 -37 30 2 60
|
||||||
|
23 49 34 -13 13 -13 48 -1 44 7 -3 14 -20 15 -38 2 -18 5 -35 7 -37 2 -2 30
|
||||||
|
-3 62 -1 53 3 57 4 41 19 -18 19 -13 29 15 29 13 0 18 -7 18 -25 0 -33 10 -32
|
||||||
|
50 10 19 19 38 35 42 35 5 0 16 -16 24 -36 13 -31 18 -35 47 -32 20 2 32 8 32
|
||||||
|
18 0 8 9 15 20 16 48 2 48 3 34 22 -13 15 -12 16 3 4 14 -11 23 -9 59 17 23
|
||||||
|
17 46 31 52 31 8 0 539 302 556 316 2 2 -186 4 -418 3 -265 0 -419 -3 -416 -9
|
||||||
|
4 -6 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 -16 10 -35 10 -24 0 -35 -4 -33 -12
|
||||||
|
1 -7 -6 -26 -17 -41 l-18 -29 -16 29 c-8 15 -14 34 -13 41 2 9 -21 12 -88 12
|
||||||
|
-70 0 -89 -3 -84 -12 6 -10 4 -10 -8 0 -23 18 -184 13 -180 -6 1 -8 -3 -12
|
||||||
|
-10 -9 -7 2 -12 10 -11 16 2 7 -16 11 -52 11 -42 0 -55 -3 -55 -15 0 -19 -34
|
||||||
|
-19 -50 0 -10 12 -45 14 -193 14 -128 0 -184 -4 -189 -12 -6 -9 -8 -9 -8 1 0
|
||||||
|
7 -13 12 -30 12 -16 0 -30 -4 -30 -10 0 -5 -5 -10 -11 -10 -5 0 -7 5 -4 10 4
|
||||||
|
7 -12 10 -44 9 -28 -1 -51 -5 -51 -9 0 -4 10 -19 21 -34 30 -38 39 -87 23
|
||||||
|
-122 -11 -26 -12 -27 -13 -6 -1 28 -81 108 -91 91 -6 -8 -10 -8 -16 2 -4 7 -3
|
||||||
|
14 3 16 6 2 -2 17 -18 34 -26 27 -33 29 -104 29 -61 0 -75 -3 -75 -15 0 -9 -7
|
||||||
|
-27 -16 -41 l-17 -25 -12 23 c-6 13 -8 28 -3 34 14 19 -4 24 -89 24 l-83 0 0
|
||||||
|
-222z m2395 192 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4
|
||||||
|
11 -10z m-107 -33 c-2 -11 -9 -12 -28 -5 -24 9 -24 10 -6 24 22 15 40 6 34
|
||||||
|
-19z m-1928 -52 c0 -5 -11 -23 -25 -40 l-24 -30 -24 26 -25 26 21 48 21 47 28
|
||||||
|
-33 c15 -19 28 -38 28 -44z m1139 13 c-5 -10 -14 -18 -19 -18 -16 0 -23 49 -9
|
||||||
|
66 11 14 14 13 25 -8 8 -15 9 -29 3 -40z m186 42 c3 -5 1 -10 -4 -10 -6 0 -11
|
||||||
|
5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m-1066 -9 c11 -7 10 -11 -5 -19 -18
|
||||||
|
-10 -16 -14 19 -47 35 -33 63 -82 53 -92 -2 -2 -25 17 -50 42 -54 52 -72 90
|
||||||
|
-55 111 13 16 19 17 38 5z m106 -1 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6
|
||||||
|
2 10 4 10 3 0 8 -4 11 -10z m169 -17 c9 -22 -12 -43 -23 -24 -10 15 -4 41 9
|
||||||
|
41 4 0 11 -8 14 -17z m391 7 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4
|
||||||
|
10 3 0 8 -4 11 -10z m465 -30 c0 -13 -5 -18 -15 -14 -8 4 -15 12 -15 20 0 8 7
|
||||||
|
14 15 14 8 0 15 -9 15 -20z m-1573 -22 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3
|
||||||
|
-3 4 -12 1 -19z m592 13 c17 -11 7 -41 -14 -41 -9 0 -15 9 -15 25 0 27 6 30
|
||||||
|
29 16z m881 -1 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10
|
||||||
|
-4 10 -10z m-1541 -31 c33 -32 37 -44 21 -54 -6 -3 -10 4 -10 17 l0 23 -18
|
||||||
|
-23 -18 -24 -18 27 c-16 25 -14 65 4 65 5 0 22 -14 39 -31z m1131 11 c0 -5 -4
|
||||||
|
-10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z m-300 -20 c0
|
||||||
|
-5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z m250
|
||||||
|
-10 c0 -11 -4 -20 -10 -20 -5 0 -10 9 -10 20 0 11 5 20 10 20 6 0 10 -9 10
|
||||||
|
-20z m116 -32 l2 -42 -19 23 c-14 17 -16 27 -9 42 17 30 25 22 26 -23z m179
|
||||||
|
22 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z
|
||||||
|
m-891 -16 c4 -9 1 -23 -6 -31 -10 -12 -13 -12 -20 1 -9 15 -1 46 12 46 4 0 11
|
||||||
|
-7 14 -16z m-106 -35 c-2 -6 -8 -10 -13 -10 -5 0 -11 4 -13 10 -2 6 4 11 13
|
||||||
|
11 9 0 15 -5 13 -11z m719 -44 c-4 -53 4 -77 18 -55 10 16 25 1 25 -24 0 -27
|
||||||
|
-44 -71 -60 -61 -6 4 -10 17 -8 30 1 12 -4 35 -12 49 -13 25 -12 31 9 72 13
|
||||||
|
24 25 44 27 44 3 0 3 -25 1 -55z m-167 29 c0 -8 -5 -12 -10 -9 -6 4 -8 11 -5
|
||||||
|
16 9 14 15 11 15 -7z m560 -30 c0 -8 -4 -14 -10 -14 -5 0 -10 9 -10 21 0 11 5
|
||||||
|
17 10 14 6 -3 10 -13 10 -21z m270 -46 c0 -23 -12 -23 -34 1 -12 13 -15 27
|
||||||
|
-11 41 l7 21 19 -22 c10 -12 19 -30 19 -41z m-1830 18 c-13 -13 -35 7 -25 24
|
||||||
|
5 8 11 8 21 -1 10 -8 12 -15 4 -23z m968 4 c9 -16 23 -30 30 -30 13 0 15 -10
|
||||||
|
6 -34 -6 -15 -8 -15 -19 1 -11 15 -13 15 -20 -6 -5 -18 -9 -20 -21 -10 -29 24
|
||||||
|
-36 48 -22 79 16 38 25 38 46 0z m-362 -88 c-6 -5 -56 44 -56 54 0 3 8 16 17
|
||||||
|
31 l17 26 14 -53 c7 -29 11 -55 8 -58z m257 72 c-7 -19 -23 -7 -23 18 0 17 3
|
||||||
|
18 14 8 8 -6 12 -18 9 -26z m-673 16 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3
|
||||||
|
6 -1 10 4 10 6 0 11 -4 11 -10z m1060 0 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10
|
||||||
|
-3 6 -1 10 4 10 6 0 11 -4 11 -10z m58 -35 c-8 -17 -15 -22 -21 -16 -7 7 -6
|
||||||
|
15 3 26 20 24 31 18 18 -10z m606 9 c3 -8 2 -12 -4 -9 -6 3 -10 10 -10 16 0
|
||||||
|
14 7 11 14 -7z m-1469 -14 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4
|
||||||
|
10 3 0 8 -4 11 -10z m-395 -21 c0 -5 -4 -9 -10 -9 -5 0 -10 7 -10 16 0 8 5 12
|
||||||
|
10 9 6 -3 10 -10 10 -16z m1044 5 c3 -8 2 -12 -4 -9 -6 3 -10 10 -10 16 0 14
|
||||||
|
7 11 14 -7z m-602 -36 c-9 -9 -12 -7 -12 12 0 19 3 21 12 12 9 -9 9 -15 0 -24z
|
||||||
|
m-432 8 c0 -2 3 -12 7 -21 5 -14 2 -16 -18 -10 -31 9 -32 11 -24 24 6 10 35
|
||||||
|
16 35 7z m111 -68 c24 -29 23 -37 -5 -71 l-22 -28 -2 61 c0 33 1 60 4 60 3 0
|
||||||
|
14 -10 25 -22z m73 -14 c3 -8 2 -12 -4 -9 -6 3 -10 10 -10 16 0 14 7 11 14 -7z
|
||||||
|
m-185 -94 c17 -22 31 -44 31 -49 0 -6 4 -11 10 -11 5 0 -2 -12 -15 -26 -14
|
||||||
|
-15 -25 -31 -25 -35 0 -5 -7 -6 -15 -3 -8 3 -13 9 -12 12 1 4 -4 22 -12 40
|
||||||
|
-10 24 -11 35 -2 46 8 10 6 19 -9 39 -25 31 -25 36 -1 30 11 -3 33 -22 50 -43z
|
||||||
|
m150 -30 c0 -44 0 -45 -14 -19 -8 14 -13 39 -11 55 5 41 5 41 16 24 5 -8 10
|
||||||
|
-35 9 -60z m-54 20 c-3 -5 -11 -10 -16 -10 -6 0 -7 5 -4 10 3 6 11 10 16 10 6
|
||||||
|
0 7 -4 4 -10z m35 -115 c11 7 29 -26 23 -42 -2 -6 1 -14 6 -18 21 -12 11 -25
|
||||||
|
-39 -49 -44 -21 -70 -21 -56 2 2 4 8 35 11 67 9 74 13 82 32 56 8 -12 18 -19
|
||||||
|
23 -16z m-80 -35 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0
|
||||||
|
10 -4 10 -10z m237 -17 c8 -12 12 -27 8 -33 -8 -13 -65 26 -65 45 0 22 41 13
|
||||||
|
57 -12z m-56 -33 c18 -10 26 -49 13 -63 -6 -5 -64 55 -64 67 0 9 29 7 51 -4z
|
||||||
|
m-78 -66 c-4 -11 -9 -12 -19 -4 -7 7 -10 18 -7 26 4 11 9 12 19 4 7 -7 10 -18
|
||||||
|
7 -26z m49 -46 c-15 -15 -27 14 -17 40 6 15 8 15 18 -6 7 -16 7 -26 -1 -34z
|
||||||
|
m87 -90 c5 -16 6 -28 1 -28 -17 0 -60 63 -60 88 l0 27 25 -30 c13 -16 29 -42
|
||||||
|
34 -57z m-235 -89 c-10 -16 -24 -9 -24 12 0 18 2 19 15 9 8 -7 12 -16 9 -21z
|
||||||
|
m-37 -65 c-1 -2 -13 6 -27 16 -23 17 -23 20 -10 45 l14 26 13 -43 c6 -23 11
|
||||||
|
-43 10 -44z m284 23 c-8 -8 -11 -3 -11 19 1 25 2 27 11 11 8 -14 8 -22 0 -30z
|
||||||
|
m-201 -8 c0 -6 -4 -7 -10 -4 -5 3 -10 11 -10 16 0 6 5 7 10 4 6 -3 10 -11 10
|
||||||
|
-16z m45 -59 c3 -11 11 -20 17 -20 7 0 7 -4 0 -13 -6 -7 -9 -23 -6 -34 3 -12
|
||||||
|
1 -30 -4 -40 -10 -17 -11 -17 -17 2 -11 33 -20 48 -30 46 -18 -4 -23 43 -7 62
|
||||||
|
20 23 39 22 47 -3z m167 -37 c-4 -24 -6 -25 -17 -9 -7 9 -11 26 -8 37 8 30 31
|
||||||
|
5 25 -28z m-102 -5 c0 -19 -2 -20 -10 -8 -13 19 -13 30 0 30 6 0 10 -10 10
|
||||||
|
-22z m-257 -49 c3 -14 1 -32 -3 -39 -7 -11 -12 -7 -21 13 -9 21 -9 30 1 42 15
|
||||||
|
19 17 17 23 -16z m157 -59 c0 -25 -4 -30 -25 -30 -31 0 -31 7 -3 37 27 29 28
|
||||||
|
29 28 -7z"/>
|
||||||
|
<path d="M2695 2824 c-44 -25 -82 -48 -85 -52 -3 -4 -11 -8 -19 -10 -7 -1 -38
|
||||||
|
-19 -70 -39 -31 -20 -60 -38 -66 -39 -5 -1 -57 -29 -113 -63 -57 -34 -118 -70
|
||||||
|
-135 -79 -18 -9 -78 -44 -134 -76 l-101 -59 18 -35 c14 -25 16 -40 9 -53 -23
|
||||||
|
-43 -42 -35 -64 26 l-13 38 -24 -24 c-13 -13 -33 -24 -43 -24 -13 0 -20 -7
|
||||||
|
-21 -20 -2 -37 -5 -40 -17 -23 -12 14 -25 9 -140 -55 l-127 -72 2 -47 c1 -55
|
||||||
|
-23 -98 -32 -58 -7 31 -26 36 -27 8 -1 -60 -3 -68 -21 -68 -26 0 -44 41 -26
|
||||||
|
58 8 7 14 22 14 32 0 19 -4 18 -57 -11 -32 -18 -64 -39 -70 -47 -7 -9 -13 -12
|
||||||
|
-13 -8 0 4 -13 0 -29 -10 -18 -11 -31 -29 -37 -53 -6 -25 -15 -36 -26 -35 -11
|
||||||
|
1 -21 -10 -29 -33 l-11 -35 -27 26 c-30 28 -53 33 -69 13 -12 -14 11 -52 31
|
||||||
|
-52 7 0 13 -12 15 -27 3 -22 -1 -28 -16 -28 -20 0 -39 16 -42 35 -3 23 -12 55
|
||||||
|
-17 55 -13 0 -133 -76 -133 -85 0 -6 -10 -15 -22 -20 -12 -6 -25 -21 -29 -35
|
||||||
|
-4 -14 -7 -18 -8 -8 -2 27 -19 31 -51 11 -28 -16 -35 -26 -31 -47 1 -4 -9 -6
|
||||||
|
-23 -2 -14 3 -30 1 -38 -6 -8 -7 -49 -31 -92 -53 -43 -22 -89 -50 -102 -62
|
||||||
|
-13 -12 -24 -20 -24 -17 0 3 -8 1 -17 -5 -10 -5 -18 -19 -18 -32 0 -12 -6 -24
|
||||||
|
-12 -26 -7 -3 -13 2 -13 11 0 21 -4 20 -61 -10 -40 -22 -48 -31 -43 -49 4 -17
|
||||||
|
-6 -31 -47 -66 -28 -24 -60 -50 -70 -57 -16 -11 -19 -27 -19 -108 0 -81 3 -96
|
||||||
|
18 -101 64 -23 134 -105 116 -135 -4 -6 4 -4 17 3 26 13 253 144 309 178 19
|
||||||
|
11 46 26 60 33 14 7 27 15 30 18 3 3 26 16 52 30 83 43 83 44 59 83 -11 19
|
||||||
|
-21 45 -21 58 0 24 37 95 45 87 10 -10 42 -118 35 -118 -5 0 -13 -14 -19 -30
|
||||||
|
l-10 -31 42 26 c23 14 95 55 160 92 109 63 117 70 112 94 -3 14 -2 36 4 50 l9
|
||||||
|
24 7 -30 c13 -58 12 -57 57 -29 24 15 45 28 47 30 2 2 -4 20 -15 39 -17 31
|
||||||
|
-17 37 -4 45 22 14 27 12 27 -7 0 -10 1 -31 2 -48 2 -29 2 -30 19 -10 9 11 23
|
||||||
|
20 30 21 29 2 33 5 30 22 -2 13 3 17 25 15 34 -2 34 7 1 38 -42 39 -55 71 -43
|
||||||
|
112 5 19 9 39 8 44 -7 40 26 44 70 8 24 -21 28 -30 22 -47 -6 -16 0 -33 22
|
||||||
|
-64 l30 -43 36 24 c20 14 52 32 71 42 19 9 63 34 98 55 34 21 66 38 71 38 4 0
|
||||||
|
5 17 2 38 -4 20 -4 55 0 77 11 60 1 99 -38 145 -31 36 -35 46 -29 78 6 40 28
|
||||||
|
62 62 62 18 0 31 -21 80 -130 33 -71 65 -130 72 -130 6 0 12 -9 12 -20 0 -23
|
||||||
|
8 -25 32 -6 14 10 15 15 5 26 -10 10 -8 10 10 1 18 -9 24 -8 32 7 7 12 6 25
|
||||||
|
-2 39 -47 81 -48 83 -34 83 25 0 65 -39 72 -70 7 -33 8 -33 107 23 36 21 69
|
||||||
|
45 72 53 3 8 11 12 17 9 5 -4 29 6 52 21 23 16 44 29 47 29 3 0 28 14 55 29
|
||||||
|
28 16 67 39 88 51 20 12 35 25 32 28 -3 4 -2 5 1 2 9 -6 84 34 84 45 0 6 7 10
|
||||||
|
16 10 8 0 35 12 60 26 36 21 44 31 44 54 0 16 -11 42 -25 59 l-26 30 23 3 c20
|
||||||
|
3 23 10 26 50 2 38 0 47 -11 42 -9 -3 -16 3 -19 14 -6 23 9 55 23 47 5 -4 9
|
||||||
|
38 9 104 0 61 -3 111 -7 111 -5 0 -44 -21 -88 -46z m33 -44 c12 -12 22 -23 22
|
||||||
|
-25 0 -11 -24 -55 -30 -55 -3 0 -11 23 -16 50 -12 55 -8 60 24 30z m42 -70 c0
|
||||||
|
-5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m-150
|
||||||
|
-52 c0 -16 -3 -19 -11 -11 -6 6 -8 16 -5 22 11 17 16 13 16 -11z m-97 -14 c-7
|
||||||
|
-18 -19 -18 -26 0 -7 18 1 26 18 19 8 -2 11 -11 8 -19z m15 -100 c12 -22 -9
|
||||||
|
-79 -33 -88 -10 -4 -13 12 -13 70 0 72 1 75 18 57 9 -11 22 -28 28 -39z m-316
|
||||||
|
-26 c-7 -7 -12 -8 -12 -2 0 6 3 14 7 17 3 4 9 5 12 2 2 -3 -1 -11 -7 -17z m20
|
||||||
|
-93 c0 -5 -5 -11 -11 -13 -6 -2 -11 4 -11 13 0 9 5 15 11 13 6 -2 11 -8 11
|
||||||
|
-13z m-212 -20 c0 -8 -2 -15 -4 -15 -2 0 -6 7 -10 15 -3 8 -1 15 4 15 6 0 10
|
||||||
|
-7 10 -15z m173 -31 c22 -22 24 -29 15 -50 -13 -27 -25 -30 -51 -10 -14 11
|
||||||
|
-17 22 -12 50 9 43 14 44 48 10z m-113 -19 c0 -9 -6 -12 -16 -8 -13 5 -13 7
|
||||||
|
-2 14 17 11 18 11 18 -6z m48 -25 c-1 -16 -6 -30 -10 -30 -9 0 -10 22 -2 44
|
||||||
|
10 25 15 19 12 -14z m182 -20 c13 -31 6 -100 -10 -100 -14 0 -40 43 -40 67 0
|
||||||
|
31 18 75 29 69 4 -3 14 -19 21 -36z m-390 -20 c0 -5 -2 -10 -4 -10 -3 0 -8 5
|
||||||
|
-11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m66 -57 c-10 -11 -25 18 -18 35 4
|
||||||
|
13 8 11 15 -6 6 -12 7 -25 3 -29z m-226 7 c0 -5 -4 -10 -10 -10 -5 0 -10 5
|
||||||
|
-10 10 0 6 5 10 10 10 6 0 10 -4 10 -10z m483 -47 c-5 -12 -7 -12 -14 -1 -5 7
|
||||||
|
-9 19 -9 27 0 11 3 11 14 1 8 -6 12 -18 9 -27z m207 16 c0 -5 -4 -9 -10 -9 -5
|
||||||
|
0 -10 7 -10 16 0 8 5 12 10 9 6 -3 10 -10 10 -16z m-123 -11 c-3 -8 -6 -5 -6
|
||||||
|
6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m-617 -15 c0 -21 -3 -24 -9 -14 -5 8 -7
|
||||||
|
20 -4 28 8 21 13 15 13 -14z m383 -22 c3 -11 2 -22 -1 -25 -9 -10 -31 15 -25
|
||||||
|
30 7 20 20 17 26 -5z m-113 -27 c0 -8 -4 -12 -10 -9 -5 3 -10 10 -10 16 0 5 5
|
||||||
|
9 10 9 6 0 10 -7 10 -16z m-273 -66 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4
|
||||||
|
-12 1 -19z m296 -22 c3 -8 0 -22 -7 -32 -13 -17 -14 -16 -20 4 -11 34 15 60
|
||||||
|
27 28z m-643 -46 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0
|
||||||
|
11 -4 11 -10z m178 -23 c13 -15 -1 -42 -17 -33 -13 8 -15 46 -2 46 5 0 13 -6
|
||||||
|
19 -13z m93 -20 c-1 -12 -15 -9 -19 4 -3 6 1 10 8 8 6 -3 11 -8 11 -12z m108
|
||||||
|
-29 c5 -13 16 -39 25 -59 l15 -37 -27 3 c-35 4 -72 16 -72 23 0 7 43 92 47 92
|
||||||
|
2 0 7 -10 12 -22z m-159 -29 c0 -18 -18 -9 -23 12 -4 16 -3 18 9 8 8 -6 14
|
||||||
|
-15 14 -20z m-95 11 c11 -17 -5 -32 -21 -19 -7 6 -11 15 -8 20 7 12 21 11 29
|
||||||
|
-1z m-128 -22 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m-31 -58
|
||||||
|
c2 -35 -6 -38 -23 -10 -11 16 -10 21 5 29 9 6 17 11 17 11 0 0 1 -13 1 -30z
|
||||||
|
m-306 -26 c0 -8 -4 -12 -10 -9 -5 3 -10 13 -10 21 0 8 5 12 10 9 6 -3 10 -13
|
||||||
|
10 -21z m573 -21 c-3 -7 -9 -13 -13 -13 -14 0 -18 24 -7 45 10 19 10 19 17 0
|
||||||
|
4 -11 5 -26 3 -32z m-337 -56 c-4 -18 1 -38 12 -55 l17 -27 -33 23 c-40 29
|
||||||
|
-64 72 -51 93 5 8 9 25 9 38 0 24 1 23 26 -10 18 -25 24 -42 20 -62z m124 57
|
||||||
|
c0 -24 -17 -15 -22 11 -4 20 -3 23 8 14 8 -6 14 -18 14 -25z m310 -8 c-15 -15
|
||||||
|
-32 7 -24 29 7 17 8 17 21 -1 9 -12 10 -21 3 -28z m-725 -12 c-3 -29 -2 -34 9
|
||||||
|
-25 11 9 15 5 18 -23 4 -33 3 -34 -13 -20 -36 33 -49 104 -19 104 6 0 8 -15 5
|
||||||
|
-36z m107 14 c6 -17 -1 -38 -13 -38 -5 0 -9 11 -9 25 0 26 14 34 22 13z m64
|
||||||
|
-53 c4 -8 1 -22 -6 -30 -9 -11 -9 -22 1 -49 11 -31 10 -41 -5 -72 l-17 -37
|
||||||
|
-24 34 c-14 18 -25 43 -25 55 0 24 30 84 43 84 4 0 7 7 7 15 0 20 19 19 26 0z
|
||||||
|
m189 6 c3 -5 1 -12 -4 -15 -5 -3 -11 1 -15 9 -6 16 9 21 19 6z m-515 -31 c0
|
||||||
|
-5 -5 -10 -11 -10 -5 0 -7 5 -4 10 3 6 8 10 11 10 2 0 4 -4 4 -10z m-45 -40
|
||||||
|
c7 -23 -2 -43 -16 -35 -12 8 -12 55 0 55 5 0 12 -9 16 -20z m205 -15 c0 -18
|
||||||
|
-4 -23 -15 -19 -15 6 -20 35 -9 47 12 11 24 -3 24 -28z m-90 -32 l-1 -58 -19
|
||||||
|
24 c-23 27 -25 44 -8 71 21 33 28 23 28 -37z m-231 -20 c1 -26 0 -45 -1 -42
|
||||||
|
-2 2 -11 13 -20 25 -16 18 -16 22 -2 42 8 12 16 22 18 22 1 0 4 -21 5 -47z
|
||||||
|
m290 1 c21 -27 36 -63 28 -70 -10 -10 -39 10 -52 37 -29 56 -13 79 24 33z m86
|
||||||
|
-4 c-5 -8 -11 -8 -17 -2 -6 6 -7 16 -3 22 5 8 11 8 17 2 6 -6 7 -16 3 -22z
|
||||||
|
m163 -52 c-7 -19 -21 -12 -23 9 -1 18 1 20 12 11 8 -6 12 -15 11 -20z m-113
|
||||||
|
-8 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m-42
|
||||||
|
-46 c-4 -11 -9 -12 -19 -4 -7 7 -10 18 -7 26 4 11 9 12 19 4 7 -7 10 -18 7
|
||||||
|
-26z m-453 -28 c0 -6 -8 -20 -16 -31 l-15 -20 -15 20 c-8 11 -20 20 -27 20 -6
|
||||||
|
0 -13 8 -15 19 -2 11 0 16 7 12 5 -4 15 3 21 15 l12 21 24 -23 c13 -12 24 -27
|
||||||
|
24 -33z m344 9 c-6 -15 -8 -15 -16 -2 -4 8 -5 23 -2 32 6 15 8 15 16 2 4 -8 5
|
||||||
|
-23 2 -32z m-152 -44 c-5 -3 -12 -13 -16 -21 -3 -8 -4 -4 -2 9 3 14 1 30 -4
|
||||||
|
36 -6 7 -3 20 8 36 l17 24 3 -39 c2 -21 -1 -42 -6 -45z m308 -1 c0 -5 -2 -10
|
||||||
|
-4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m-655 -17 c13 -12
|
||||||
|
19 -13 24 -4 14 23 6 -53 -8 -79 -13 -23 -14 -23 -21 -5 -10 27 -21 105 -16
|
||||||
|
105 3 0 12 -7 21 -17z m239 -19 c-6 -3 -10 -18 -8 -34 4 -32 -6 -39 -24 -17
|
||||||
|
-13 15 11 58 31 56 8 0 9 -2 1 -5z m50 -20 c3 -8 2 -12 -4 -9 -6 3 -10 10 -10
|
||||||
|
16 0 14 7 11 14 -7z m-71 -86 c-19 -33 -40 -39 -35 -10 4 18 29 42 45 42 5 0
|
||||||
|
1 -14 -10 -32z m-198 -102 c7 3 27 -7 44 -23 l31 -28 -26 -23 -27 -23 6 30 c6
|
||||||
|
28 5 30 -16 20 -19 -9 -22 -17 -19 -47 l3 -37 -25 40 c-25 40 -26 65 -3 94 7
|
||||||
|
8 13 9 15 3 2 -6 9 -9 17 -6z m-125 -46 c0 -22 -16 -35 -25 -20 -9 14 4 52 16
|
||||||
|
45 5 -4 9 -15 9 -25z"/>
|
||||||
|
<path d="M2720 2219 c-68 -38 -62 -31 -62 -73 0 -41 -17 -47 -46 -16 l-19 20
|
||||||
|
-24 -22 c-14 -13 -29 -23 -34 -23 -22 0 -185 -101 -181 -112 3 -7 -1 -10 -9
|
||||||
|
-6 -11 4 -109 -42 -133 -62 -1 -1 7 -23 19 -49 31 -70 24 -211 -12 -250 -9
|
||||||
|
-11 -29 34 -29 67 0 11 -9 31 -21 43 -14 15 -19 29 -14 43 3 12 11 19 16 15 5
|
||||||
|
-3 7 -9 5 -13 -3 -4 0 -13 5 -21 7 -11 9 -5 8 20 -1 19 1 59 5 88 l8 53 -24
|
||||||
|
-14 c-24 -15 -366 -215 -428 -249 -221 -125 -349 -202 -344 -209 3 -5 2 -14
|
||||||
|
-2 -21 -5 -8 -9 -7 -13 5 -6 15 -9 15 -36 -3 -19 -13 -24 -20 -14 -20 31 0 40
|
||||||
|
-24 20 -54 l-19 -28 -12 36 c-13 41 -21 43 -58 18 -15 -10 -35 -22 -45 -25
|
||||||
|
-11 -4 -21 -16 -24 -28 -4 -14 -8 -17 -13 -8 -6 8 -25 1 -71 -26 -77 -46 -100
|
||||||
|
-65 -93 -76 3 -5 0 -9 -5 -9 -6 0 -11 5 -11 11 0 5 -5 7 -10 4 -6 -4 -8 -11
|
||||||
|
-5 -16 11 -16 -5 -31 -21 -18 -11 9 -54 -12 -203 -97 -180 -103 -191 -111
|
||||||
|
-191 -139 -1 -25 -2 -27 -11 -12 -14 24 -24 22 -83 -15 -28 -17 -67 -40 -86
|
||||||
|
-50 -129 -73 -180 -103 -180 -108 0 -4 17 -16 38 -28 l39 -22 13 25 c16 29 27
|
||||||
|
32 27 7 0 -51 5 -61 39 -81 19 -12 36 -21 37 -21 1 0 11 15 21 34 13 24 23 33
|
||||||
|
34 29 11 -5 14 -2 9 10 -3 9 -3 17 2 17 8 0 12 -18 28 -118 5 -29 15 -39 87
|
||||||
|
-80 44 -26 84 -46 89 -44 4 1 7 -3 7 -8 0 -6 12 -16 28 -23 15 -6 49 -27 77
|
||||||
|
-44 27 -18 52 -33 56 -33 3 0 14 18 24 40 10 22 22 40 27 40 18 0 47 -82 38
|
||||||
|
-106 -8 -20 -4 -26 26 -45 34 -21 36 -21 49 -3 13 18 14 18 34 0 12 -11 20
|
||||||
|
-28 19 -38 -2 -14 47 -47 212 -146 118 -71 216 -128 218 -126 2 1 -2 11 -9 22
|
||||||
|
-11 17 -10 24 2 38 13 16 14 14 19 -19 l5 -36 74 44 c40 25 74 45 76 45 1 0
|
||||||
|
29 16 61 35 50 30 59 40 60 66 1 16 10 39 20 50 18 20 18 20 31 -6 8 -14 16
|
||||||
|
-25 19 -25 3 0 25 11 50 24 l45 24 -25 18 c-19 15 -24 25 -19 46 6 30 22 35
|
||||||
|
55 17 15 -8 19 -17 14 -39 -5 -28 -2 -27 124 48 71 42 130 83 130 90 0 6 10
|
||||||
|
12 22 12 16 0 85 36 127 67 2 1 -2 9 -8 17 -7 8 -9 20 -5 27 5 8 12 5 23 -9
|
||||||
|
16 -21 17 -21 209 94 l192 116 0 244 c0 134 -3 244 -6 244 -3 0 -46 -24 -97
|
||||||
|
-54 -51 -29 -112 -65 -137 -78 -119 -66 -220 -130 -216 -137 3 -4 1 -13 -4
|
||||||
|
-21 -7 -12 -10 -12 -15 2 -6 16 -9 16 -30 2 -13 -8 -29 -28 -35 -45 -11 -26
|
||||||
|
-14 -28 -25 -12 -11 15 -20 12 -96 -32 -134 -78 -127 -70 -85 -97 46 -30 60
|
||||||
|
-64 49 -119 l-9 -44 -44 2 c-25 1 -47 -3 -51 -9 -15 -25 21 -68 78 -93 52 -23
|
||||||
|
55 -27 48 -52 -13 -56 -27 -59 -94 -19 -34 20 -64 36 -67 36 -21 0 -64 77 -64
|
||||||
|
114 0 7 19 19 43 27 61 23 62 50 1 88 l-48 29 -28 -19 c-15 -11 -28 -26 -28
|
||||||
|
-34 0 -7 -9 -23 -20 -36 l-19 -24 -1 23 c0 28 -3 27 -67 -7 -52 -28 -52 -28
|
||||||
|
-33 -46 22 -20 26 -55 8 -73 -20 -20 -28 -14 -28 21 0 59 -11 62 -78 21 -34
|
||||||
|
-20 -62 -38 -62 -41 0 -2 18 -31 40 -63 22 -32 40 -61 40 -65 0 -3 -17 5 -38
|
||||||
|
18 -20 13 -45 26 -55 30 -9 4 -26 22 -37 41 -16 26 -66 61 -215 150 -107 64
|
||||||
|
-195 118 -195 120 0 2 56 36 125 75 69 40 125 76 125 80 0 16 -46 47 -68 45
|
||||||
|
-16 -1 -21 3 -18 12 3 8 1 14 -4 14 -6 0 -10 -6 -10 -12 0 -18 -20 13 -20 31
|
||||||
|
0 10 3 11 14 2 11 -9 15 -5 18 24 2 19 0 41 -4 48 -6 9 -8 8 -8 -3 -1 -12 -3
|
||||||
|
-11 -14 3 -8 10 -11 27 -8 39 5 20 6 20 18 3 8 -10 16 -16 18 -14 10 9 8 86
|
||||||
|
-3 129 -16 66 -14 79 7 52 28 -37 101 -47 160 -23 72 29 75 29 100 -1 31 -36
|
||||||
|
23 -58 -23 -59 -19 -1 -39 -3 -45 -4 -5 -1 -14 -3 -18 -4 -12 -1 -14 -93 -3
|
||||||
|
-109 4 -8 24 -17 42 -21 26 -5 35 -13 39 -33 l5 -26 125 73 c92 54 128 80 137
|
||||||
|
101 8 19 12 23 13 12 0 -10 3 -18 6 -18 16 0 143 78 173 106 36 34 38 43 40
|
||||||
|
157 1 44 3 47 20 38 20 -11 39 -54 48 -106 3 -16 6 -31 7 -32 1 -1 59 32 129
|
||||||
|
72 70 41 146 85 170 98 113 64 167 99 167 107 0 6 7 10 16 10 27 0 75 33 69
|
||||||
|
48 -3 8 1 23 9 34 14 20 14 20 21 -1 3 -12 11 -21 17 -21 13 0 128 69 128 77
|
||||||
|
0 4 -3 3 -6 0 -8 -8 -39 30 -48 59 -4 12 -2 34 4 49 10 27 11 27 30 10 20 -18
|
||||||
|
20 -17 20 65 0 72 -2 81 -13 66 -13 -18 -15 -17 -34 8 -12 14 -28 26 -38 26
|
||||||
|
-9 0 -13 5 -10 10 4 6 11 8 16 5 5 -4 9 -2 9 3 0 19 33 22 51 6 18 -17 19 -14
|
||||||
|
19 79 0 54 -3 97 -7 97 -5 0 -33 -14 -63 -31z m-42 -220 c-2 -6 -8 -10 -13
|
||||||
|
-10 -5 0 -11 4 -13 10 -2 6 4 11 13 11 9 0 15 -5 13 -11z m-246 -46 c20 -18
|
||||||
|
24 -58 8 -68 -16 -10 -60 23 -55 40 3 8 7 22 10 30 6 19 14 19 37 -2z m248
|
||||||
|
-42 c0 -3 -8 -17 -17 -31 l-17 -24 -12 35 c-18 48 -17 49 16 38 17 -6 30 -14
|
||||||
|
30 -18z m-317 -36 c-7 -21 -13 -19 -13 6 0 11 4 18 10 14 5 -3 7 -12 3 -20z
|
||||||
|
m-183 -9 c0 -11 -19 -15 -25 -6 -3 5 1 10 9 10 9 0 16 -2 16 -4z m450 -40 c-8
|
||||||
|
-8 -13 -7 -20 4 -12 20 -1 33 16 19 11 -9 12 -15 4 -23z m-500 -6 c0 -10 -5
|
||||||
|
-22 -11 -25 -6 -5 -4 -11 6 -19 15 -11 15 -14 -4 -36 l-20 -25 -2 30 c-2 17
|
||||||
|
-3 39 -4 50 -2 27 14 57 26 50 5 -4 9 -15 9 -25z m-10 -120 c0 -5 -2 -10 -4
|
||||||
|
-10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m-215 -10 c3 -5 1
|
||||||
|
-10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m152 -36 c7 3
|
||||||
|
15 1 17 -3 3 -5 18 -11 34 -14 24 -5 28 -11 30 -44 1 -21 5 -55 8 -76 5 -37 5
|
||||||
|
-38 -18 -26 -40 21 -128 82 -128 88 -1 3 -7 31 -14 62 l-14 57 36 -24 c20 -14
|
||||||
|
42 -22 49 -20z m433 6 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10
|
||||||
|
6 0 10 -4 10 -10z m-690 -93 c0 -5 -5 -5 -10 -2 -6 4 -8 10 -5 15 3 5 -4 11
|
||||||
|
-15 15 -22 7 -26 35 -8 53 10 10 15 3 25 -30 7 -24 13 -47 13 -51z m121 -25
|
||||||
|
c15 -27 15 -31 -1 -61 l-16 -33 -17 26 c-9 14 -17 31 -17 38 0 9 -3 9 -10 -2
|
||||||
|
-5 -8 -10 -11 -10 -7 0 12 40 67 48 67 4 0 14 -13 23 -28z m270 -19 c-9 -17
|
||||||
|
-10 -17 -16 0 -4 9 -4 25 0 35 6 16 7 16 16 0 7 -12 7 -24 0 -35z m-505 1 c17
|
||||||
|
-16 24 -32 21 -45 -3 -10 0 -19 6 -20 7 0 2 -4 -11 -10 -25 -10 -72 13 -72 35
|
||||||
|
0 12 23 66 28 66 2 0 14 -12 28 -26z m73 -8 c7 -8 8 -17 3 -20 -6 -3 -12 3
|
||||||
|
-15 14 -6 24 -4 25 12 6z m491 -36 c0 -5 -2 -10 -4 -10 -3 0 -8 5 -11 10 -3 6
|
||||||
|
-1 10 4 10 6 0 11 -4 11 -10z m-746 -36 c3 -8 2 -12 -4 -9 -6 3 -10 10 -10 16
|
||||||
|
0 14 7 11 14 -7z m-42 -56 c-9 -9 -12 -7 -12 12 0 19 3 21 12 12 9 -9 9 -15 0
|
||||||
|
-24z m405 10 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m-457 -59
|
||||||
|
c0 -10 -4 -19 -10 -19 -5 0 -10 12 -10 26 0 14 4 23 10 19 6 -3 10 -15 10 -26z
|
||||||
|
m203 16 c4 -8 2 -17 -2 -20 -5 -2 -11 4 -14 15 -6 23 8 27 16 5z m87 -84 c0
|
||||||
|
-11 5 -21 11 -23 5 -2 7 -11 3 -21 -5 -14 -13 -17 -33 -11 -14 4 -37 8 -51 9
|
||||||
|
-16 1 -26 9 -28 21 -3 15 -1 16 9 7 9 -10 18 -7 41 12 35 30 48 31 48 6z
|
||||||
|
m-485 -70 c-10 -16 -25 -3 -25 22 0 20 1 20 16 5 9 -9 13 -21 9 -27z m407 -88
|
||||||
|
c2 -3 -9 -7 -24 -9 -23 -2 -28 1 -29 19 0 12 -2 30 -4 40 -2 12 5 8 25 -13 16
|
||||||
|
-17 30 -34 32 -37z m-572 41 c0 -8 -5 -12 -10 -9 -6 4 -8 11 -5 16 9 14 15 11
|
||||||
|
15 -7z m-157 -46 c6 -42 -2 -49 -21 -18 -9 15 -10 26 -1 41 13 25 15 24 22
|
||||||
|
-23z m47 32 c0 -5 -4 -10 -10 -10 -5 0 -10 5 -10 10 0 6 5 10 10 10 6 0 10 -4
|
||||||
|
10 -10z m590 -36 c0 -8 -4 -14 -10 -14 -5 0 -10 9 -10 21 0 11 5 17 10 14 6
|
||||||
|
-3 10 -13 10 -21z m-537 -25 c-5 -5 -9 3 -11 19 -1 24 0 25 9 9 7 -11 7 -23 2
|
||||||
|
-28z m107 20 c0 -11 -4 -18 -10 -14 -5 3 -7 12 -3 20 7 21 13 19 13 -6z m1585
|
||||||
|
-32 c0 -26 -20 -25 -23 2 -3 16 1 22 10 19 7 -3 13 -12 13 -21z m-1897 -43 c1
|
||||||
|
-14 6 -33 11 -42 9 -18 4 -42 -8 -42 -10 0 -31 46 -31 68 0 14 17 42 25 42 0
|
||||||
|
0 2 -11 3 -26z m57 7 c3 -5 1 -12 -5 -16 -5 -3 -10 1 -10 9 0 18 6 21 15 7z
|
||||||
|
m187 -8 c10 -9 18 -23 18 -32 -1 -19 -29 -72 -30 -55 0 7 -9 14 -20 17 -14 3
|
||||||
|
-20 14 -20 32 0 19 4 26 14 22 10 -4 12 0 9 14 -6 23 4 24 29 2z m73 -32 c3
|
||||||
|
-5 1 -12 -5 -16 -5 -3 -10 1 -10 9 0 18 6 21 15 7z m1385 -67 c0 -9 -5 -12
|
||||||
|
-12 -8 -27 15 -38 27 -32 35 8 13 44 -9 44 -27z m-1552 -8 c7 1 8 0 3 -2 -6
|
||||||
|
-3 -8 -11 -6 -17 17 -56 15 -67 -7 -67 -48 1 -73 50 -52 105 6 14 9 14 28 -3
|
||||||
|
11 -11 27 -18 34 -16z m109 2 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1
|
||||||
|
-19z m105 -62 c-16 -30 -17 -30 -20 -8 -3 18 -7 21 -17 12 -10 -8 -14 -4 -18
|
||||||
|
16 -3 18 -1 22 6 15 18 -18 24 -12 19 22 l-4 32 25 -29 c25 -29 25 -30 9 -60z
|
||||||
|
m-515 58 c10 -28 -13 -37 -25 -9 -10 21 -9 25 4 25 8 0 17 -7 21 -16z m373
|
||||||
|
-49 c0 -8 -4 -17 -10 -20 -6 -4 -10 5 -10 20 0 15 4 24 10 20 6 -3 10 -12 10
|
||||||
|
-20z m-320 -16 c0 -24 -12 -24 -27 0 -10 15 -10 21 0 24 18 6 27 -2 27 -24z
|
||||||
|
m-110 -5 c0 -8 -5 -12 -10 -9 -6 4 -8 11 -5 16 9 14 15 11 15 -7z m220 12 c0
|
||||||
|
-3 -4 -8 -10 -11 -5 -3 -10 -1 -10 4 0 6 5 11 10 11 6 0 10 -2 10 -4z m1790
|
||||||
|
-38 c0 -30 0 -31 -20 -13 -19 17 -19 19 -2 31 23 18 22 18 22 -18z m-1950 -34
|
||||||
|
c0 -8 -5 -12 -10 -9 -6 4 -8 11 -5 16 9 14 15 11 15 -7z m100 6 c0 -5 -2 -10
|
||||||
|
-4 -10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m301 -16 c9 -11 8
|
||||||
|
-21 -1 -44 -16 -39 -26 -38 -33 3 -3 17 -8 40 -12 49 -5 13 -2 15 14 11 11 -3
|
||||||
|
26 -11 32 -19z m1259 -51 c0 -30 -20 -73 -35 -73 -6 0 -19 15 -27 34 -16 32
|
||||||
|
-16 35 9 71 l26 38 13 -24 c7 -13 13 -34 14 -46z m-1873 35 c-3 -8 -6 -5 -6 6
|
||||||
|
-1 11 2 17 5 13 3 -3 4 -12 1 -19z m2082 -63 c1 -50 -12 -59 -41 -28 -28 31
|
||||||
|
-29 47 -2 88 l18 28 13 -29 c7 -16 12 -42 12 -59z m-1686 38 c7 -43 3 -53 -24
|
||||||
|
-53 -10 0 -28 -9 -39 -20 -11 -11 -23 -20 -27 -20 -5 0 -9 -11 -10 -25 -1 -14
|
||||||
|
-8 -34 -16 -46 -14 -20 -16 -18 -27 38 -6 32 -12 64 -13 72 -2 14 115 89 139
|
||||||
|
90 6 1 14 -15 17 -36z m95 9 c14 -9 16 -159 1 -167 -9 -6 -59 56 -59 75 0 7 9
|
||||||
|
28 21 46 11 19 18 38 14 44 -7 12 5 13 23 2z m-535 -39 c-6 -14 -8 -14 -14 3
|
||||||
|
-12 30 -10 37 5 24 8 -6 12 -19 9 -27z m777 -88 c-6 -19 -13 -35 -15 -35 -3 0
|
||||||
|
-15 16 -29 36 -24 35 -24 38 -9 70 l16 34 24 -36 c22 -31 23 -39 13 -69z
|
||||||
|
m-313 53 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13 3 -3 4 -12 1 -19z m385 -50 c-13
|
||||||
|
-13 -26 8 -17 30 6 16 7 16 17 -1 7 -13 7 -22 0 -29z m908 2 c0 -5 -2 -10 -4
|
||||||
|
-10 -3 0 -8 5 -11 10 -3 6 -1 10 4 10 6 0 11 -4 11 -10z m-845 -53 c17 -33 17
|
||||||
|
-35 -1 -65 -10 -18 -21 -32 -24 -31 -3 0 -15 13 -28 30 l-24 29 22 35 c12 19
|
||||||
|
25 35 29 35 4 0 16 -15 26 -33z m-265 -59 l0 -32 -16 23 c-14 19 -14 25 -3 32
|
||||||
|
19 12 19 13 19 -23z m-220 -19 c0 -6 -4 -7 -10 -4 -5 3 -10 11 -10 16 0 6 5 7
|
||||||
|
10 4 6 -3 10 -11 10 -16z m436 -96 c-11 -12 -27 13 -20 32 7 17 8 17 17 -3 6
|
||||||
|
-12 7 -25 3 -29z m-52 -44 c-8 -13 -24 -1 -24 18 0 13 3 13 15 3 8 -7 12 -16
|
||||||
|
9 -21z m196 16 c0 -8 -4 -15 -10 -15 -5 0 -7 7 -4 15 4 8 8 15 10 15 2 0 4 -7
|
||||||
|
4 -15z m-93 -61 c17 -4 -4 -54 -23 -54 -9 0 -34 48 -34 66 0 2 34 -4 57 -12z
|
||||||
|
m-57 -20 c0 -8 -4 -14 -10 -14 -5 0 -10 9 -10 21 0 11 5 17 10 14 6 -3 10 -13
|
||||||
|
10 -21z m60 -60 c0 -8 -5 -12 -10 -9 -6 4 -8 11 -5 16 9 14 15 11 15 -7z m103
|
||||||
|
-40 c18 -24 18 -25 -7 -55 l-26 -31 0 26 c0 14 0 27 0 29 -1 1 -5 19 -9 39 -8
|
||||||
|
32 -7 35 8 26 9 -5 24 -21 34 -34z m364 14 c-3 -8 -6 -5 -6 6 -1 11 2 17 5 13
|
||||||
|
3 -3 4 -12 1 -19z m-247 -69 c0 -20 -15 -26 -24 -10 -8 13 4 42 15 35 5 -3 9
|
||||||
|
-14 9 -25z m-63 -64 c0 -8 -4 -12 -9 -9 -5 3 -6 10 -3 15 9 13 12 11 12 -6z"/>
|
||||||
|
<path d="M210 982 c0 -45 3 -82 6 -82 5 0 68 35 83 46 3 2 -42 62 -81 109 -4
|
||||||
|
5 -8 -28 -8 -73z"/>
|
||||||
|
<path d="M1440 1001 c-7 -15 -7 -21 0 -21 12 0 25 28 17 36 -3 3 -10 -4 -17
|
||||||
|
-15z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 24 KiB |
19
Software/data_src/static/img/site.webmanifest
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"short_name": "",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/android-chrome-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/android-chrome-256x256.png",
|
||||||
|
"sizes": "256x256",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme_color": "#ffffff",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"display": "standalone"
|
||||||
|
}
|
BIN
Software/data_src/static/img/warn.png
Normal file
After Width: | Height: | Size: 9.4 KiB |
7
Software/data_src/static/js/bootstrap.min.js
vendored
Normal file
196
Software/data_src/static/js/dtc_table.js
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
const jsonFilePath = "static/dtc_table.json";
|
||||||
|
|
||||||
|
var dtcState = {};
|
||||||
|
|
||||||
|
async function processDTCNotifications(dtcArray) {
|
||||||
|
if (dtcArray.length === 0 || dtcArray[0] == "0") {
|
||||||
|
dtcState = {};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < dtcArray.length; i++) {
|
||||||
|
var dtcInfo = dtcArray[i].split(",");
|
||||||
|
var errorCode = parseInt(dtcInfo[1]);
|
||||||
|
var activity = parseInt(dtcInfo[3]);
|
||||||
|
var severity = parseInt(dtcInfo[2]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var { title, description } = await getDescriptionForDTCNumber(errorCode);
|
||||||
|
|
||||||
|
switch (severity) {
|
||||||
|
case 1:
|
||||||
|
severity = "info";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
severity = "warning";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
severity = "danger";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dtcState[errorCode]) {
|
||||||
|
// Überprüfen, ob sich der Zustand von "previous" auf "active" geändert hat
|
||||||
|
if (activity !== dtcState[errorCode]) {
|
||||||
|
dtcState[errorCode] = activity;
|
||||||
|
if (activity === 1) showNotification(description, severity);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// DTC ist neu, Zustand speichern und Benachrichtigung anzeigen
|
||||||
|
dtcState[errorCode] = activity;
|
||||||
|
showNotification(description, severity);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error processing DTC:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDescriptionForDTCNumber(number) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
fetch(jsonFilePath)
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
const dtcList = data.dtc_table_data;
|
||||||
|
const foundEntry = dtcList.find((entry) => entry.num === number);
|
||||||
|
|
||||||
|
if (foundEntry) {
|
||||||
|
const description = foundEntry.description;
|
||||||
|
const title = foundEntry.title;
|
||||||
|
resolve({ title, description });
|
||||||
|
} else {
|
||||||
|
// Wenn die Nummer nicht gefunden wurde, geben Sie einen Fehler zurück
|
||||||
|
reject(`Beschreibung für Nummer ${number} nicht gefunden.`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
// Im Fehlerfall geben Sie den Fehler zurück
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function showDTCModal(event) {
|
||||||
|
var dtc = parseInt(event.currentTarget.getAttribute("data-dtc"));
|
||||||
|
var debugval = event.currentTarget.getAttribute("data-debugval");
|
||||||
|
var modal = $("#dtcModal");
|
||||||
|
|
||||||
|
try {
|
||||||
|
var { title, description } = await getDescriptionForDTCNumber(dtc);
|
||||||
|
|
||||||
|
modal.find(".modal-title").text(title);
|
||||||
|
modal.find(".dtc-desc").text(description);
|
||||||
|
|
||||||
|
if (debugval > 0) {
|
||||||
|
modal.find(".dtc-debugval").text("Debugvalue: " + debugval);
|
||||||
|
} else {
|
||||||
|
modal.find(".dtc-debugval").remove();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Fehler beim Abrufen der Beschreibung:", error);
|
||||||
|
modal.find(".modal-title").text("Fehler");
|
||||||
|
modal.find(".dtc-desc").text("DTC-Beschreibung konnte nicht geladen werden");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modal anzeigen
|
||||||
|
modal.modal("show");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function fillDTCTable(dtcArray) {
|
||||||
|
// Referenz auf das Tabellen-Element
|
||||||
|
var table = document.getElementById("dtc_table");
|
||||||
|
var tablediv = document.getElementById("dtc_container");
|
||||||
|
|
||||||
|
// Prüfen, ob DTC vorhanden sind
|
||||||
|
if (dtcArray.length === 0 || dtcArray[0] == "0") {
|
||||||
|
// Verstecke das Tabellen-Div, wenn keine DTC vorhanden sind
|
||||||
|
tablediv.hidden = true;
|
||||||
|
table.innerHTML = "";
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Zeige das Tabellen-Div, wenn DTC vorhanden sind
|
||||||
|
tablediv.hidden = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tabelle leeren, bevor sie neu gefüllt wird
|
||||||
|
table.innerHTML = "";
|
||||||
|
|
||||||
|
// Überschriften für die Tabelle erstellen
|
||||||
|
var headerRow = table.insertRow(0);
|
||||||
|
|
||||||
|
// Definition der Klassen und Scopes für die Spalten
|
||||||
|
var columnDefinitions = [
|
||||||
|
{ class: "col-6", scope: "Zeitstempel" },
|
||||||
|
{ class: "col-2", scope: "Fehlercode" },
|
||||||
|
{ class: "col-2", scope: "Schwere" },
|
||||||
|
{ class: "col-2", scope: "Aktiv" },
|
||||||
|
];
|
||||||
|
|
||||||
|
for (var i = 0; i < columnDefinitions.length; i++) {
|
||||||
|
var headerCell = headerRow.insertCell(i);
|
||||||
|
headerCell.className = `th ${columnDefinitions[i].class}`;
|
||||||
|
headerCell.scope = columnDefinitions[i].scope;
|
||||||
|
headerCell.innerHTML = columnDefinitions[i].scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DTC-Daten in die Tabelle einfügen
|
||||||
|
for (var i = 0; i < dtcArray.length; i++) {
|
||||||
|
var dtcInfo = dtcArray[i].split(",");
|
||||||
|
|
||||||
|
var row = table.insertRow(i + 1); // +1 wegen der Überschriftenzeile
|
||||||
|
|
||||||
|
// Zeitstempel
|
||||||
|
var timestampCell = row.insertCell(0);
|
||||||
|
timestampCell.innerHTML = formatTimestamp(parseInt(dtcInfo[0]));
|
||||||
|
|
||||||
|
// Fehlercode
|
||||||
|
var errorCodeCell = row.insertCell(1);
|
||||||
|
errorCodeCell.innerHTML = dtcInfo[1];
|
||||||
|
|
||||||
|
// Schwere
|
||||||
|
var severityCell = row.insertCell(2);
|
||||||
|
var severity = parseInt(dtcInfo[2]);
|
||||||
|
|
||||||
|
// Schwere
|
||||||
|
switch (severity) {
|
||||||
|
case 1:
|
||||||
|
severityCell.innerHTML = '<img src="static/img/info.png" alt="Info" />';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
severityCell.innerHTML =
|
||||||
|
'<img src="static/img/warn.png" alt="Warnung" />';
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
severityCell.innerHTML =
|
||||||
|
'<img src="static/img/critical.png" alt="Kritisch" />';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
severityCell.innerHTML =
|
||||||
|
'<img src="static/img/none.png" alt="Unbekannt" />';
|
||||||
|
}
|
||||||
|
|
||||||
|
row.setAttribute("data-dtc", dtcInfo[1]);
|
||||||
|
row.setAttribute("data-debugval", dtcInfo[4]);
|
||||||
|
row.addEventListener("click", showDTCModal);
|
||||||
|
|
||||||
|
// Aktivität
|
||||||
|
var activityCell = row.insertCell(3);
|
||||||
|
activityCell.innerHTML = parseInt(dtcInfo[3]) === 1 ? "active" : "previous";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatTimestamp(milliseconds) {
|
||||||
|
const date = new Date(milliseconds);
|
||||||
|
|
||||||
|
const days = String(date.getUTCDate() - 1).padStart(2, "0");
|
||||||
|
const hours = String(date.getUTCHours()).padStart(2, "0");
|
||||||
|
const minutes = String(date.getUTCMinutes()).padStart(2, "0");
|
||||||
|
const seconds = String(date.getUTCSeconds()).padStart(2, "0");
|
||||||
|
const millisecondsFormatted = String(date.getUTCMilliseconds()).padStart(
|
||||||
|
3,
|
||||||
|
"0"
|
||||||
|
);
|
||||||
|
|
||||||
|
return `${days}-${hours}:${minutes}:${seconds}:${millisecondsFormatted}`;
|
||||||
|
}
|
2
Software/data_src/static/js/jquery.min.js
vendored
Normal file
5
Software/data_src/static/js/popper.min.js
vendored
Normal file
27
Software/data_src/static/js/script.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
$(document).ready(function () {
|
||||||
|
$(".navbar-nav a").on("click", function () {
|
||||||
|
$(".navbar-collapse").collapse("hide");
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#show_hide_password a").on("click", function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
if ($("#show_hide_password input").attr("type") == "text") {
|
||||||
|
$("#show_hide_password input").attr("type", "password");
|
||||||
|
$("#show_hide_password i").addClass("fa-eye-slash");
|
||||||
|
$("#show_hide_password i").removeClass("fa-eye");
|
||||||
|
} else if ($("#show_hide_password input").attr("type") == "password") {
|
||||||
|
$("#show_hide_password input").attr("type", "text");
|
||||||
|
$("#show_hide_password i").removeClass("fa-eye-slash");
|
||||||
|
$("#show_hide_password i").addClass("fa-eye");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelector(".custom-file-input")
|
||||||
|
.addEventListener("change", function (e) {
|
||||||
|
var fileName = document.getElementById("fw-update-file").files[0].name;
|
||||||
|
var nextSibling = e.target.nextElementSibling;
|
||||||
|
nextSibling.innerText = fileName;
|
||||||
|
});
|
||||||
|
|
240
Software/data_src/static/js/websocket.js
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
var gateway = `ws://${window.location.hostname}/ws`;
|
||||||
|
var websocket;
|
||||||
|
|
||||||
|
var statusMapping;
|
||||||
|
var staticMapping;
|
||||||
|
var overlay;
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
// Ihr JavaScript-Code hier, einschließlich der onLoad-Funktion
|
||||||
|
overlay = document.getElementById("overlay");
|
||||||
|
onLoad();
|
||||||
|
});
|
||||||
|
|
||||||
|
function initWebSocket() {
|
||||||
|
console.log("Trying to open a WebSocket connection...");
|
||||||
|
websocket = new WebSocket(gateway);
|
||||||
|
websocket.onopen = onOpen;
|
||||||
|
websocket.onclose = onClose;
|
||||||
|
websocket.onmessage = onMessage; // <-- add this line
|
||||||
|
}
|
||||||
|
|
||||||
|
function initButtons() {
|
||||||
|
var elements = document.getElementsByClassName("btn-wsevent");
|
||||||
|
|
||||||
|
if (elements.length > 0) {
|
||||||
|
for (var i = 0; i < elements.length; i++) {
|
||||||
|
let element = elements[i];
|
||||||
|
element.addEventListener("click", sendButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initSettingInputs() {
|
||||||
|
var elements = document.getElementsByClassName("set-wsevent");
|
||||||
|
|
||||||
|
if (elements.length > 0) {
|
||||||
|
for (var i = 0; i < elements.length; i++) {
|
||||||
|
let element = elements[i];
|
||||||
|
element.addEventListener("change", function () {
|
||||||
|
websocket_sendevent("set-" + element.id, element.value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onOpen(event) {
|
||||||
|
console.log("Connection opened");
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClose(event) {
|
||||||
|
console.log("Connection closed");
|
||||||
|
setTimeout(initWebSocket, 1000);
|
||||||
|
overlay.style.display = "flex";
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendButton(event) {
|
||||||
|
var targetElement = event.target;
|
||||||
|
|
||||||
|
if (
|
||||||
|
targetElement.classList.contains("confirm") &&
|
||||||
|
window.confirm("Sicher?") == false
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
websocket_sendevent("btn-" + targetElement.id, targetElement.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMessage(event) {
|
||||||
|
var data = event.data;
|
||||||
|
|
||||||
|
if (data.startsWith("NOTIFY:")) {
|
||||||
|
var notify_data = data.slice(7).split(";")[1];
|
||||||
|
var notify_type = data.slice(7).split(";")[0];
|
||||||
|
showNotification(notify_data, notify_type);
|
||||||
|
} else if (data.startsWith("DEBUG:")) {
|
||||||
|
var addtext = data.slice(6);
|
||||||
|
var livedebug_out = document.getElementById("livedebug-out");
|
||||||
|
livedebug_out.value += addtext;
|
||||||
|
livedebug_out.scrollTop = livedebug_out.scrollHeight;
|
||||||
|
do_resize(livedebug_out);
|
||||||
|
} else if (data.startsWith("DTC:")) {
|
||||||
|
const dtcs = data.slice(4);
|
||||||
|
const dtcArray = dtcs.trim() !== "" ? dtcs.split(";").filter(Boolean) : [];
|
||||||
|
|
||||||
|
processDTCNotifications(dtcArray);
|
||||||
|
fillDTCTable(dtcArray);
|
||||||
|
|
||||||
|
} else if (data.startsWith("MAPPING_STATUS:")) {
|
||||||
|
const data_sliced = data.slice(15);
|
||||||
|
statusMapping = createMapping(data_sliced);
|
||||||
|
} else if (data.startsWith("MAPPING_STATIC:")) {
|
||||||
|
const data_sliced = data.slice(15);
|
||||||
|
staticMapping = createMapping(data_sliced);
|
||||||
|
console.log(staticMapping);
|
||||||
|
} else if (data.startsWith("STATUS:")) {
|
||||||
|
const data_sliced = data.slice(7);
|
||||||
|
const result = processDataString(data_sliced, statusMapping);
|
||||||
|
fillValuesToHTML(result);
|
||||||
|
} else if (data.startsWith("STATIC:")) {
|
||||||
|
const data_sliced = data.slice(7);
|
||||||
|
const result = processDataString(data_sliced, staticMapping);
|
||||||
|
fillValuesToHTML(result);
|
||||||
|
console.log(result);
|
||||||
|
overlay.style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMapping(mappingString) {
|
||||||
|
const mappingArray = mappingString.split(";");
|
||||||
|
const mapping = [];
|
||||||
|
|
||||||
|
mappingArray.forEach((variable) => {
|
||||||
|
if (variable !== null) mapping.push(variable.trim());
|
||||||
|
});
|
||||||
|
return mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processDataString(dataString, mapping) {
|
||||||
|
const valuesArray = dataString.split(";");
|
||||||
|
const dataObject = {};
|
||||||
|
|
||||||
|
valuesArray.forEach((value, index) => {
|
||||||
|
const variable = mapping[index];
|
||||||
|
if (variable) {
|
||||||
|
dataObject[variable] = value.trim();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return dataObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onLoad(event) {
|
||||||
|
initWebSocket();
|
||||||
|
initButtons();
|
||||||
|
initSettingInputs();
|
||||||
|
overlay.style.display = "flex";
|
||||||
|
}
|
||||||
|
|
||||||
|
function websocket_sendevent(element_id, element_value) {
|
||||||
|
websocket.send(element_id + ":" + element_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function do_resize(textbox) {
|
||||||
|
var maxrows = 15;
|
||||||
|
var minrows = 3;
|
||||||
|
var txt = textbox.value;
|
||||||
|
var cols = textbox.cols;
|
||||||
|
|
||||||
|
var arraytxt = txt.split("\n");
|
||||||
|
var rows = arraytxt.length;
|
||||||
|
|
||||||
|
for (i = 0; i < arraytxt.length; i++)
|
||||||
|
rows += parseInt(arraytxt[i].length / cols);
|
||||||
|
|
||||||
|
if (rows > maxrows) textbox.rows = maxrows;
|
||||||
|
else if (rows < minrows) textbox.rows = minrows;
|
||||||
|
else textbox.rows = rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillValuesToHTML(dataset) {
|
||||||
|
for (var key in dataset) {
|
||||||
|
var key_prefixed = "data-" + key;
|
||||||
|
var elements = document.getElementsByClassName(key_prefixed);
|
||||||
|
|
||||||
|
if (elements.length > 0) {
|
||||||
|
for (var i = 0; i < elements.length; i++) {
|
||||||
|
var element = elements[i];
|
||||||
|
|
||||||
|
if (element.type === "checkbox") {
|
||||||
|
// Wenn das Element ein Kontrollkästchen ist
|
||||||
|
element.checked = dataset[key] == 1 ? true : false;
|
||||||
|
} else if (element.tagName === "SELECT") {
|
||||||
|
// Wenn das Element ein Dropdown ist
|
||||||
|
setDropdownValue(element, dataset[key]);
|
||||||
|
} else if (element.classList.contains("progress-bar")) {
|
||||||
|
// Wenn das Element eine Fortschrittsleiste ist
|
||||||
|
updateProgressBar(element, dataset[key]);
|
||||||
|
} else if (element.classList.contains("hideable")) {
|
||||||
|
// Wenn das Element ein Settingsabschnitt-div ist
|
||||||
|
if (dataset[key] == 0) element.style.display = "none";
|
||||||
|
else element.style.display = "";
|
||||||
|
} else if (element.tagName === "DIV") {
|
||||||
|
if (element.classList.contains("format-time")) {
|
||||||
|
element.innerText = formatTime(dataset[key]);
|
||||||
|
} else {
|
||||||
|
element.innerText = dataset[key];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Standardmäßig für Textfelder und andere Elemente
|
||||||
|
element.value = dataset[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Funktion zum Setzen des ausgewählten Werts für Dropdowns
|
||||||
|
function setDropdownValue(selectElement, value) {
|
||||||
|
for (var i = 0; i < selectElement.options.length; i++) {
|
||||||
|
if (selectElement.options[i].value === value) {
|
||||||
|
selectElement.selectedIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funktion zum Aktualisieren der Fortschrittsleiste
|
||||||
|
function updateProgressBar(progressBar, value) {
|
||||||
|
// Wert in das aria-valuenow-Attribut einfügen
|
||||||
|
progressBar.setAttribute("aria-valuenow", value);
|
||||||
|
|
||||||
|
// Breite des Fortschrittsbalkens und inneren Text aktualisieren
|
||||||
|
progressBar.style.width = value + "%";
|
||||||
|
progressBar.textContent = value + "%";
|
||||||
|
}
|
||||||
|
|
||||||
|
function showNotification(message, type) {
|
||||||
|
// Erstellen Sie ein Bootstrap-Alert-Element
|
||||||
|
var alertElement = $(
|
||||||
|
'<div class="alert alert-' +
|
||||||
|
type +
|
||||||
|
' alert-dismissible fade show notification" role="alert">' +
|
||||||
|
"<strong>" +
|
||||||
|
message +
|
||||||
|
"</strong>" +
|
||||||
|
'<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
|
||||||
|
'<span aria-hidden="true">×</span>' +
|
||||||
|
"</button>" +
|
||||||
|
"</div>"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Fügen Sie das Alert-Element dem Container hinzu
|
||||||
|
$("#notification-container").append(alertElement);
|
||||||
|
|
||||||
|
// Nach 5 Sekunden das Alert-Element ausblenden
|
||||||
|
setTimeout(function () {
|
||||||
|
alertElement.alert("close");
|
||||||
|
}, 5000);
|
||||||
|
}
|
1
Software/data_src/version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1.05
|
@@ -1,8 +0,0 @@
|
|||||||
import subprocess
|
|
||||||
|
|
||||||
revision = (
|
|
||||||
subprocess.check_output(["git", "rev-parse", "--short=10", "HEAD"])
|
|
||||||
.strip()
|
|
||||||
.decode("utf-8")
|
|
||||||
)
|
|
||||||
print("-DGIT_REV='\"%s\"'" % revision)
|
|
74
Software/include/common.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
|
||||||
|
#ifndef _COMMON_H_
|
||||||
|
#define _COMMON_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define Q(x) #x
|
||||||
|
#define QUOTE(x) Q(x)
|
||||||
|
#define SET_BIT(value, bitPosition) ((value) |= (1U << (bitPosition)))
|
||||||
|
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
|
#ifndef HOST_NAME
|
||||||
|
#define HOST_NAME "AirsoftTimer_%08X"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SHUTDOWN_DELAY_MS 5000
|
||||||
|
#define STARTUP_DELAY_MS 20000
|
||||||
|
|
||||||
|
#define GPIO_LORA_TX D3
|
||||||
|
#define GPIO_LORA_RX D4
|
||||||
|
#define GPIO_LORA_AUX D0
|
||||||
|
|
||||||
|
#define GPIO_7SEG_EN_FAC1 D7
|
||||||
|
#define GPIO_7SEG_EN_FAC2 D6
|
||||||
|
#define GPIO_7SEG_EN_FAC3 D5
|
||||||
|
#define GPIO_7SEG_CLK D8
|
||||||
|
|
||||||
|
#define I2C_IO_BTN_FAC1 0
|
||||||
|
#define FAC_1_TRG_PRESSED LOW
|
||||||
|
#define I2C_IO_BTN_FAC2 1
|
||||||
|
#define FAC_2_TRG_PRESSED LOW
|
||||||
|
#define I2C_IO_BTN_FAC3 2
|
||||||
|
#define FAC_3_TRG_PRESSED LOW
|
||||||
|
|
||||||
|
#define I2C_IO_LORA_M0 4
|
||||||
|
#define I2C_IO_LORA_M1 3
|
||||||
|
|
||||||
|
#define EEPROM_TYPE 24LC64
|
||||||
|
|
||||||
|
#define I2C_IO_ADDRESS 0x38
|
||||||
|
#define I2C_POWER_ADDRESS 0x40
|
||||||
|
#define I2C_EEPROM_ADDRESS 0x50
|
||||||
|
|
||||||
|
#ifndef OTA_DELAY
|
||||||
|
#define OTA_DELAY 50 // ticks -> 10ms / tick
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum eSystem_Status
|
||||||
|
{
|
||||||
|
sysStat_Init,
|
||||||
|
sysStat_Startup,
|
||||||
|
sysStat_Normal,
|
||||||
|
sysStat_Error,
|
||||||
|
sysStat_Shutdown
|
||||||
|
} tSystem_Status;
|
||||||
|
|
||||||
|
typedef enum batteryType_e
|
||||||
|
{
|
||||||
|
BATTERY_UNDEFINED,
|
||||||
|
BATTERY_LIPO_2S,
|
||||||
|
BATTERY_LIPO_3S
|
||||||
|
} batteryType_t;
|
||||||
|
|
||||||
|
// String representation of SpeedSource enum
|
||||||
|
extern const char *BatteryString[];
|
||||||
|
extern const size_t BatteryString_Elements;
|
||||||
|
|
||||||
|
#define STARTUP_DELAY 2500
|
||||||
|
#define SHUTDOWN_DELAY_MS 2500
|
||||||
|
|
||||||
|
#endif
|
61
Software/include/debugger.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
* @file debugger.h
|
||||||
|
*
|
||||||
|
* @brief Header file for debugging functions and status in the DE-Timer application.
|
||||||
|
*
|
||||||
|
* This file declares functions and status definitions for debugging purposes in the DE-Timer project.
|
||||||
|
* It includes functions to print system information, WiFi information, format EEPROM data,
|
||||||
|
* handle debug messages, and manage the status of different debug ports.
|
||||||
|
*
|
||||||
|
* @author Marcel Peterkau
|
||||||
|
* @date 09.01.2024
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DEBUGGER_H_
|
||||||
|
#define _DEBUGGER_H_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "webui.h"
|
||||||
|
const char PROGMEM helpCmd[] = "sysinfo - System Info\n"
|
||||||
|
"reboot - System Reboot\n"
|
||||||
|
"netinfo - WiFi Info\n"
|
||||||
|
"formatPDS - Format Persistence EEPROM Data\n"
|
||||||
|
"formatCFG - Format Configuration EEPROM Data\n"
|
||||||
|
"checkEE - Check EEPROM with checksum\n"
|
||||||
|
"dumpEE1k - dump the first 1kb of EEPROM to Serial\n"
|
||||||
|
"dumpEE - dump the whole EPPROM to Serial\n"
|
||||||
|
"killEE - kill the first 1024 byte of EEPROM\n"
|
||||||
|
"zeroEE - zero the first 1024 byte of EEPROM\n"
|
||||||
|
"resetPageEE - Reset the PersistenceData Page\n"
|
||||||
|
"dumpCFG - print Config struct\n"
|
||||||
|
"dumpPDS - print PersistanceStruct\n"
|
||||||
|
"saveEE - save EE-Data\n"
|
||||||
|
"showdtc - Show all DTCs\n"
|
||||||
|
"dumpGlobals - print globals\n";
|
||||||
|
|
||||||
|
typedef enum DebugStatus_e
|
||||||
|
{
|
||||||
|
disabled,
|
||||||
|
enabled
|
||||||
|
} DebugStatus_t;
|
||||||
|
|
||||||
|
typedef enum DebugPorts_e
|
||||||
|
{
|
||||||
|
dbg_Serial,
|
||||||
|
dbg_Webui,
|
||||||
|
dbg_cntElements
|
||||||
|
} DebugPorts_t;
|
||||||
|
|
||||||
|
const char sDebugPorts[dbg_cntElements][7] = {
|
||||||
|
"Serial",
|
||||||
|
"WebUI"};
|
||||||
|
|
||||||
|
extern DebugStatus_t DebuggerStatus[dbg_cntElements];
|
||||||
|
|
||||||
|
void initDebugger();
|
||||||
|
void pushCANDebug(uint32_t id, uint8_t dlc, uint8_t *data);
|
||||||
|
void Debug_pushMessage(const char *format, ...);
|
||||||
|
void SetDebugportStatus(DebugPorts_t port, DebugStatus_t status);
|
||||||
|
void Debug_Process();
|
||||||
|
|
||||||
|
#endif
|
39
Software/include/dtc.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* @file dtc.h
|
||||||
|
*
|
||||||
|
* @brief Header file for handling Diagnostic Trouble Codes (DTC) in the DE-Timer application.
|
||||||
|
*
|
||||||
|
* This file provides definitions and functions for handling Diagnostic Trouble Codes (DTC)
|
||||||
|
* in the DE-Timer project. It includes structures for DTC entries, severity levels,
|
||||||
|
* and functions for DTC maintenance and processing. DTCs are used to track system errors and issues.
|
||||||
|
*
|
||||||
|
* @author Marcel Peterkau
|
||||||
|
* @date 09.01.2024
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DTC_H_
|
||||||
|
#define _DTC_H_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "dtc_defs.h"
|
||||||
|
|
||||||
|
#define MAX_DTC_STORAGE 12
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
DTCNum_t Number;
|
||||||
|
uint32_t timestamp;
|
||||||
|
DTCActive_t active;
|
||||||
|
uint32_t debugVal;
|
||||||
|
} DTCEntry_t;
|
||||||
|
|
||||||
|
void MaintainDTC(DTCNum_t DTC_no, boolean active, uint32_t DebugValue = 0);
|
||||||
|
void ClearDTC(DTCNum_t DTC_no);
|
||||||
|
void ClearAllDTC();
|
||||||
|
DTCNum_t getlastDTC(boolean only_active);
|
||||||
|
DTCNum_t ActiveDTCseverity(DTCSeverity_t severity);
|
||||||
|
DTCSeverity_t getSeverityForDTC(DTCNum_t targetCode);
|
||||||
|
void DTC_Process();
|
||||||
|
|
||||||
|
extern DTCEntry_t DTCStorage[MAX_DTC_STORAGE];
|
||||||
|
#endif
|
85
Software/include/dtc_defs.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* @file dtc_defs.h
|
||||||
|
*
|
||||||
|
* @brief Header file for Diagnostic Trouble Code (DTC) definitions in the DE-Timer application.
|
||||||
|
*
|
||||||
|
* This file contains definitions for Diagnostic Trouble Codes (DTC) in the DE-Timer project.
|
||||||
|
* It includes enums for DTC active status, severity levels, and specific DTC codes.
|
||||||
|
* The file also defines an array of DTC definitions and a timestamp indicating the generation time.
|
||||||
|
*
|
||||||
|
* @note This file is auto-generated by a script on 2024-05-30 21:56:51.
|
||||||
|
*
|
||||||
|
* @author Marcel Peterkau
|
||||||
|
* @date 30.05.2024
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DTC_DEFS_H
|
||||||
|
#define DTC_DEFS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef uint32_t DTCNum_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DTC_INACTIVE,
|
||||||
|
DTC_ACTIVE,
|
||||||
|
DTC_PREVIOUS
|
||||||
|
} DTCActive_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DTC_NONE,
|
||||||
|
DTC_INFO,
|
||||||
|
DTC_WARN,
|
||||||
|
DTC_CRITICAL
|
||||||
|
} DTCSeverity_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DTCNum_t code;
|
||||||
|
DTCSeverity_t severity;
|
||||||
|
} DTC_t;
|
||||||
|
|
||||||
|
#define DTC_NO_DTC 0
|
||||||
|
#define DTC_BAT_CRITICAL 1
|
||||||
|
#define DTC_BAT_LOW 2
|
||||||
|
#define DTC_NO_EEPROM_FOUND 3
|
||||||
|
#define DTC_EEPROM_CFG_BAD 4
|
||||||
|
#define DTC_EEPROM_PDS_BAD 5
|
||||||
|
#define DTC_EEPROM_PDSADRESS_BAD 6
|
||||||
|
#define DTC_EEPROM_VERSION_BAD 7
|
||||||
|
#define DTC_FLASHFS_ERROR 8
|
||||||
|
#define DTC_FLASHFS_VERSION_ERROR 9
|
||||||
|
#define DTC_NO_BATMNON_FOUND 10
|
||||||
|
#define DTC_NO_LORA_FOUND 11
|
||||||
|
#define DTC_EEPROM_CFG_SANITY 12
|
||||||
|
#define DTC_EEPROM_MIGRATE_FAILED 13
|
||||||
|
#define DTC_FAKE_DTC_INFO 14
|
||||||
|
#define DTC_FAKE_DTC_WARN 15
|
||||||
|
#define DTC_FAKE_DTC_CRIT 16
|
||||||
|
#define DTC_LAST_DTC 17
|
||||||
|
|
||||||
|
const DTC_t dtc_definitions[] = {
|
||||||
|
{ DTC_NO_DTC , DTC_NONE }, // No Error
|
||||||
|
{ DTC_BAT_CRITICAL , DTC_CRITICAL }, // Akku ist komplett leer. Den Akku aufladen!
|
||||||
|
{ DTC_BAT_LOW , DTC_WARN }, // Akku ist unter der Warnschwelle. Den Akku demnächst aufladen
|
||||||
|
{ DTC_NO_EEPROM_FOUND , DTC_CRITICAL }, // Es wurde kein EEPROM gefunden. Dies lässt einen Hardware-Defekt vermuten.
|
||||||
|
{ DTC_EEPROM_CFG_BAD , DTC_CRITICAL }, // Die Checksumme der Config-Partition des EEPROM ist ungültig. Setzen sie den EEPROM-Bereich 'CFG' im Menu 'Wartung' zurück
|
||||||
|
{ DTC_EEPROM_PDS_BAD , DTC_CRITICAL }, // Die Checksumme der Betriebsdaten-Partition des EEPROM ist ungültig. Setzen sie den EEPROM-Bereich 'PDS' im Menu 'Wartung' zurück
|
||||||
|
{ DTC_EEPROM_PDSADRESS_BAD , DTC_CRITICAL }, // Die Adresse der Betriebsdaten-Partition im EEPROM ist ungültig. Setzen sie den EEPROM-Bereich 'PDS' im Menu 'Wartung' zurück
|
||||||
|
{ DTC_EEPROM_VERSION_BAD , DTC_CRITICAL }, // Die Layout-Version des EEPROM stimmt nicht mit der Firmware-Version überein. Setzen sie den EEPROM-Bereich 'CFG' im Menu 'Wartung' zurück
|
||||||
|
{ DTC_FLASHFS_ERROR , DTC_CRITICAL }, // Der Flashspeicher konnte nicht initialisiert werden. Aktualisieren sie Flash & Firmware
|
||||||
|
{ DTC_FLASHFS_VERSION_ERROR , DTC_CRITICAL }, // Die Version des Flashspeicher stimmt nicht mit der Firmware-Version überein. Aktualisieren sie den Flash mit der passenden Update-Datei
|
||||||
|
{ DTC_NO_BATMNON_FOUND , DTC_CRITICAL }, // Es wurde keine Akkuüberwachung über I2C gefunden, Prüfen sie die Hardware!
|
||||||
|
{ DTC_NO_LORA_FOUND , DTC_CRITICAL }, // Es konnte keine Verbindung zum LoRa-Transceiver hergestellt werden. Prüfen Sie die Hardware auf Defekte
|
||||||
|
{ DTC_EEPROM_CFG_SANITY , DTC_WARN }, // Ein oder mehrer Einstellungswerte sind ausserhalb plausibler Werte. Prüfen Sie Ihre Einstellungen
|
||||||
|
{ DTC_EEPROM_MIGRATE_FAILED , DTC_CRITICAL }, // Es wurde ein altes EEPROm Image erkannt, konnte aber nicht migriert werden. EEPROM manuell zurück setzen und neue Einstellunge speichern.
|
||||||
|
{ DTC_FAKE_DTC_INFO , DTC_INFO }, // Ein Dummy-DTC der Schwere "Info" für Debugging-Zwecke
|
||||||
|
{ DTC_FAKE_DTC_WARN , DTC_WARN }, // Ein Dummy-DTC der Schwere "Warnung" für Debugging-Zwecke
|
||||||
|
{ DTC_FAKE_DTC_CRIT , DTC_CRITICAL }, // Ein Dummy-DTC der Schwere "Kritisch" für Debugging-Zwecke
|
||||||
|
{ DTC_LAST_DTC , DTC_NONE } // Last Error
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DTC_DEFS_H
|
||||||
|
|
||||||
|
// CODEGENERATOR_CHECKSUM: 313d59949b074024df3c5d796f65e3bd518e34f0bb171185c30f008f21c19d30
|
112
Software/include/eeprom.h
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/**
|
||||||
|
* @file eeprom.h
|
||||||
|
*
|
||||||
|
* @brief Header file for configuration settings and EEPROM operations in the DE-Timer application.
|
||||||
|
*
|
||||||
|
* This file defines configuration settings for the DE-Timer project, including default values,
|
||||||
|
* EEPROM structures, and functions for EEPROM operations. It also defines enums for different Battery Types.
|
||||||
|
* Additionally, it includes functions for EEPROM handling such as storing, retrieving, and formatting configuration data.
|
||||||
|
*
|
||||||
|
* @author Marcel Peterkau
|
||||||
|
* @date 09.01.2024
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _EEPROM_H_
|
||||||
|
#define _EEPROM_H_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <I2C_eeprom.h>
|
||||||
|
#include "dtc.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define I2C_EE_ADDRESS 0x50
|
||||||
|
#define EEPROM_STRUCTURE_REVISION 4 // Increment this version when changing EEPROM structures
|
||||||
|
#define EEPROM_SIZE_BYTES I2C_DEVICESIZE_24LC256
|
||||||
|
|
||||||
|
typedef enum Factions_e
|
||||||
|
{
|
||||||
|
NONE,
|
||||||
|
FACTION_1,
|
||||||
|
FACTION_2,
|
||||||
|
FACTION_3
|
||||||
|
} Factions_t;
|
||||||
|
|
||||||
|
typedef enum EERequest_e
|
||||||
|
{
|
||||||
|
EE_IDLE,
|
||||||
|
EE_CFG_SAVE,
|
||||||
|
EE_CFG_LOAD,
|
||||||
|
EE_CFG_FORMAT,
|
||||||
|
EE_PDS_SAVE,
|
||||||
|
EE_PDS_LOAD,
|
||||||
|
EE_PDS_FORMAT,
|
||||||
|
EE_FORMAT_ALL,
|
||||||
|
EE_ALL_SAVE
|
||||||
|
|
||||||
|
} EERequest_t;
|
||||||
|
|
||||||
|
// Structure for persistence data stored in EEPROM
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t writeCycleCounter;
|
||||||
|
uint32_t faction_1_timer;
|
||||||
|
uint32_t faction_2_timer;
|
||||||
|
uint32_t faction_3_timer;
|
||||||
|
Factions_t activeFaction;
|
||||||
|
uint32_t checksum;
|
||||||
|
} persistenceData_t;
|
||||||
|
|
||||||
|
// Structure for configuration settings stored in EEPROM
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t EEPROM_Version;
|
||||||
|
batteryType_t batteryType;
|
||||||
|
bool active_faction_on_reboot;
|
||||||
|
char Faction_1_Name[33];
|
||||||
|
char Faction_2_Name[33];
|
||||||
|
char Faction_3_Name[33];
|
||||||
|
char wifi_ap_ssid[33];
|
||||||
|
char wifi_ap_password[64];
|
||||||
|
char wifi_client_ssid[33];
|
||||||
|
char wifi_client_password[64];
|
||||||
|
bool wifi_autoconnect;
|
||||||
|
uint32_t checksum;
|
||||||
|
} configData_t;
|
||||||
|
|
||||||
|
// Default configuration settings
|
||||||
|
const configData_t ConfigData_defaults = {
|
||||||
|
2, // EEPROM_Version (incerease this if anything on Layout changes!)
|
||||||
|
BATTERY_LIPO_3S, // batteryType
|
||||||
|
false, // active_faction_on_reboot
|
||||||
|
"FACTION 1", // Faction_1_Name
|
||||||
|
"FACTION 2", // Faction_2_Name
|
||||||
|
"FACTION 3", // Faction_3_Name
|
||||||
|
"ArisoftTimer",
|
||||||
|
QUOTE(WIFI_AP_PASSWORD),
|
||||||
|
QUOTE(WIFI_SSID_CLIENT),
|
||||||
|
QUOTE(WIFI_PASSWORD_CLIENT),
|
||||||
|
true,
|
||||||
|
0 // checksum
|
||||||
|
};
|
||||||
|
|
||||||
|
void InitEEPROM();
|
||||||
|
void EEPROM_Process();
|
||||||
|
void StoreConfig_EEPROM();
|
||||||
|
void GetConfig_EEPROM();
|
||||||
|
void StorePersistence_EEPROM();
|
||||||
|
void GetPersistence_EEPROM();
|
||||||
|
void FormatConfig_EEPROM();
|
||||||
|
void FormatPersistence_EEPROM();
|
||||||
|
uint32_t Checksum_EEPROM(uint8_t const *data, size_t len);
|
||||||
|
void dumpEEPROM(uint16_t memoryAddress, uint16_t length);
|
||||||
|
void MovePersistencePage_EEPROM(boolean reset);
|
||||||
|
uint32_t ConfigSanityCheck(bool autocorrect = false);
|
||||||
|
bool validateWiFiString(char *string, size_t size);
|
||||||
|
void writeSequentialToEEPROM(uint16_t memoryAddress, uint16_t length);
|
||||||
|
void writeZeroToEEPROM(uint16_t memoryAddress, uint16_t length);
|
||||||
|
|
||||||
|
extern configData_t ConfigData;
|
||||||
|
extern persistenceData_t PersistenceData;
|
||||||
|
extern uint16_t eePersistenceMarker;
|
||||||
|
#endif // _CONFIG_H_
|
44
Software/include/globals.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#ifndef _GLOBALS_H_
|
||||||
|
#define _GLOBALS_H_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "eeprom.h"
|
||||||
|
#include "common.h"
|
||||||
|
typedef struct Globals_s
|
||||||
|
{
|
||||||
|
tSystem_Status systemStatus = sysStat_Startup; /**< Current system status */
|
||||||
|
tSystem_Status resumeStatus = sysStat_Startup; /**< Status to resume after rain mode */
|
||||||
|
char systemStatustxt[16] = ""; /**< Text representation of system status */
|
||||||
|
EERequest_t requestEEAction = EE_IDLE; /**< EEPROM-related request */
|
||||||
|
char DeviceName[33]; /**< Device name */
|
||||||
|
char FlashVersion[10]; /**< Flash version */
|
||||||
|
uint16_t eePersistanceAdress; /**< EEPROM persistence address */
|
||||||
|
bool hasDTC;
|
||||||
|
int loadvoltage_mV = 0;
|
||||||
|
int battery_level = 0;
|
||||||
|
bool timer_disabled = false;
|
||||||
|
} Globals_t;
|
||||||
|
|
||||||
|
extern Globals_t globals; /**< Global variable struct */
|
||||||
|
|
||||||
|
typedef struct Constants_s
|
||||||
|
{
|
||||||
|
uint8_t FW_Version_major; /**< Firmware version major number */
|
||||||
|
uint8_t FW_Version_minor; /**< Firmware version minor number */
|
||||||
|
uint8_t Required_Flash_Version_major; /**< Required flash version major number */
|
||||||
|
uint8_t Required_Flash_Version_minor; /**< Required flash version minor number */
|
||||||
|
char GitHash[11]; /**< Git hash string */
|
||||||
|
} Constants_t;
|
||||||
|
|
||||||
|
const Constants_t constants PROGMEM = {
|
||||||
|
1, 5, // Firmware_Version
|
||||||
|
1, 5, // Required Flash Version
|
||||||
|
GIT_REV // Git-Hash-String
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes global variables.
|
||||||
|
*/
|
||||||
|
void initGlobals();
|
||||||
|
|
||||||
|
#endif // _GLOBALS_H_
|
30
Software/include/lora_messages.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#ifndef _LORA_MESSAGES_H_
|
||||||
|
#define _LORA_MESSAGES_H_
|
||||||
|
|
||||||
|
#define MESSAGES_VERSION 1.0
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef char MessageType_t[8];
|
||||||
|
typedef uint16_t NodeID_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
NodeID_t nodeid;
|
||||||
|
uint32_t millis;
|
||||||
|
uint8_t faction_active;
|
||||||
|
uint32_t faction_1_timer;
|
||||||
|
uint32_t faction_2_timer;
|
||||||
|
uint32_t faction_3_timer;
|
||||||
|
} __attribute__((packed)) MessageStatus_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
NodeID_t nodeid;
|
||||||
|
bool gpsfix;
|
||||||
|
double latitude;
|
||||||
|
double longitude;
|
||||||
|
double altitude;
|
||||||
|
} __attribute__((packed)) MessagePosition_t;
|
||||||
|
|
||||||
|
#endif
|
27
Software/include/lora_net.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef _LORA_NET_H_
|
||||||
|
#define _LORA_NET_H_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#ifdef LORA_FEATURE_ENABLED
|
||||||
|
#include <LoRa_E220.h>
|
||||||
|
#elif defined(FEATURE_ENABLE_UARTLORA)
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// local includes
|
||||||
|
#include "lora_messages.h"
|
||||||
|
#include "debugger.h"
|
||||||
|
#include "defaults.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "globals.h"
|
||||||
|
#include "dtc.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define FREQUENCY_868
|
||||||
|
|
||||||
|
bool InitLoRa(void (*MPinHelper)(int, int));
|
||||||
|
void LoRa_Process();
|
||||||
|
void sendStatus_LoRa();
|
||||||
|
|
||||||
|
#endif
|
31
Software/include/sanitycheck.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#ifndef _SANITYCHECK_H_
|
||||||
|
#define _SANITYCHECK_H_
|
||||||
|
|
||||||
|
#ifndef ADMIN_PASSWORD
|
||||||
|
#error "You need to define ADMIN_PASSWORD for OTA-Update"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WIFI_AP_SSID
|
||||||
|
#warning "No WIFI_AP_SSID defined. Using DeviceName"
|
||||||
|
#define WIFI_AP_SSID DEVICE_NAME
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef WIFI_AP_PASSWORD
|
||||||
|
#error "You must define an WIFI_AP_PASSWORD for Standalone AP-Mode"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(FEATURE_ENABLE_UARTLORA) && defined(FEATURE_ENABLE_LORA)
|
||||||
|
#error "You cannot enable LoRa and UART-Protocol at the same time!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FEATURE_ENABLE_WIFI_CLIENT
|
||||||
|
#ifndef WIFI_PASSWORD_CLIENT
|
||||||
|
#error "You must define an WIFI_PASSWORD for OTA-Update"
|
||||||
|
#endif
|
||||||
|
#ifndef WIFI_SSID_CLIENT
|
||||||
|
#error "You must define an WIFI_SSID for OTA-Update"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif //_SANITYCHECK_H_
|
26
Software/include/struct2json.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* @file struct2json.h
|
||||||
|
*
|
||||||
|
* @brief Header file for converting structs to JSON objects.
|
||||||
|
*
|
||||||
|
* @note This file is auto-generated by a script on 2024-05-30 22:54:25.
|
||||||
|
*
|
||||||
|
* @author Marcel Peterkau
|
||||||
|
* @date 30.05.2024
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _STRUCT2JSON_H_
|
||||||
|
#define _STRUCT2JSON_H_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
#include "eeprom.h"
|
||||||
|
|
||||||
|
void generateJsonObject_ConfigData(JsonObject data);
|
||||||
|
void generateJsonObject_PersistenceData(JsonObject data);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _STRUCT2JSON_H_ */
|
||||||
|
|
||||||
|
// CODEGENERATOR_CHECKSUM: 735cd4daf9a46bd773bdf5e6cd5a58d61b0d877196399bc2784a0d0ea7af717d
|
49
Software/include/webui.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* @file webui.h
|
||||||
|
*
|
||||||
|
* @brief Header file for the web-based user interface (WebUI) in the DE-Timer application.
|
||||||
|
*
|
||||||
|
* This file contains declarations for functions related to the initialization and processing of the
|
||||||
|
* web-based user interface (WebUI). It includes the necessary libraries and dependencies for handling
|
||||||
|
* web server functionality, asynchronous JSON operations, and live debugging through WebSockets.
|
||||||
|
*
|
||||||
|
* @author Marcel Peterkau
|
||||||
|
* @date 09.01.2024
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _WEBUI_H_
|
||||||
|
#define _WEBUI_H_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <FS.h>
|
||||||
|
#include <LittleFS.h>
|
||||||
|
#include <ESPAsyncTCP.h>
|
||||||
|
#include <ESPAsyncWebServer.h>
|
||||||
|
#include <Updater.h>
|
||||||
|
#include <ESP8266mDNS.h>
|
||||||
|
#include <AsyncJson.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "globals.h"
|
||||||
|
#include "dtc.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "debugger.h"
|
||||||
|
#include "struct2json.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
info,
|
||||||
|
success,
|
||||||
|
warning,
|
||||||
|
error
|
||||||
|
} NotificationType_t;
|
||||||
|
|
||||||
|
void initWebUI();
|
||||||
|
void Webserver_Process();
|
||||||
|
void Webserver_Shutdown();
|
||||||
|
|
||||||
|
void Websocket_PushLiveDebug(String Message);
|
||||||
|
void Websocket_PushNotification(String Message, NotificationType_t type);
|
||||||
|
|
||||||
|
#endif // _WEBUI_H_
|
1
Software/lib/EByte LoRa E220 library/.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
resources export-ignore
|
1
Software/lib/EByte LoRa E220 library/.piopm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"type": "library", "name": "EByte LoRa E220 library", "version": "1.0.6", "spec": {"owner": "xreef", "id": 13661, "name": "EByte LoRa E220 library", "requirements": null, "uri": null}}
|
11
Software/lib/EByte LoRa E220 library/.project
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>LoRa_E220_Series_Library</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* EBYTE LoRa E220 Series
|
||||||
|
* https://www.mischianti.org/category/my-libraries/lora-e22-devices/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Renzo Mischianti www.mischianti.org All right reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EBYTE_LORA_E220_LIBRARY_H
|
||||||
|
#define EBYTE_LORA_E220_LIBRARY_H
|
||||||
|
|
||||||
|
#include "LoRa_E220.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma once
|
24
Software/lib/EByte LoRa E220 library/LICENSE.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2017 Renzo Mischianti www.mischianti.org All right reserved.
|
||||||
|
|
||||||
|
You may copy, alter and reuse this code in any way you like, but please leave
|
||||||
|
reference to www.mischianti.org in your comments if you redistribute this code.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
1051
Software/lib/EByte LoRa E220 library/LoRa_E220.cpp
Normal file
401
Software/lib/EByte LoRa E220 library/LoRa_E220.h
Normal file
@@ -0,0 +1,401 @@
|
|||||||
|
/*
|
||||||
|
* EBYTE LoRa E220 Series
|
||||||
|
*
|
||||||
|
* AUTHOR: Renzo Mischianti
|
||||||
|
* VERSION: 1.0.6
|
||||||
|
*
|
||||||
|
* https://www.mischianti.org
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Renzo Mischianti www.mischianti.org All right reserved.
|
||||||
|
*
|
||||||
|
* You may copy, alter and reuse this code in any way you like, but please leave
|
||||||
|
* reference to www.mischianti.org in your comments if you redistribute this code.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef LoRa_E220_h
|
||||||
|
#define LoRa_E220_h
|
||||||
|
|
||||||
|
#if !defined(ARDUINO_ARCH_STM32) && !defined(ESP32) && !defined(ARDUINO_ARCH_SAMD) && !defined(ARDUINO_ARCH_MBED) && !defined(__STM32F1__) && !defined(__STM32F4__)
|
||||||
|
#define ACTIVATE_SOFTWARE_SERIAL
|
||||||
|
#endif
|
||||||
|
#if defined(ESP32)
|
||||||
|
#define HARDWARE_SERIAL_SELECTABLE_PIN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ACTIVATE_SOFTWARE_SERIAL
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <includes/statesNaming.h>
|
||||||
|
|
||||||
|
#if ARDUINO >= 100
|
||||||
|
#include "Arduino.h"
|
||||||
|
#else
|
||||||
|
#include "WProgram.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_SIZE_TX_PACKET 200
|
||||||
|
|
||||||
|
// Uncomment to enable printing out nice debug messages.
|
||||||
|
//#define LoRa_E220_DEBUG
|
||||||
|
|
||||||
|
// Define where debug output will be printed.
|
||||||
|
#define DEBUG_PRINTER Serial
|
||||||
|
|
||||||
|
// Setup debug printing macros.
|
||||||
|
#ifdef LoRa_E220_DEBUG
|
||||||
|
#define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); }
|
||||||
|
#define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); }
|
||||||
|
#else
|
||||||
|
#define DEBUG_PRINT(...) {}
|
||||||
|
#define DEBUG_PRINTLN(...) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum MODE_TYPE {
|
||||||
|
MODE_0_NORMAL = 0,
|
||||||
|
MODE_0_TRANSMISSION = 0,
|
||||||
|
MODE_1_WOR_TRANSMITTER = 1,
|
||||||
|
MODE_1_WOR = 1,
|
||||||
|
MODE_2_WOR_RECEIVER = 2,
|
||||||
|
MODE_2_POWER_SAVING = 2,
|
||||||
|
MODE_3_CONFIGURATION = 3,
|
||||||
|
MODE_3_PROGRAM = 3,
|
||||||
|
MODE_3_SLEEP = 3,
|
||||||
|
MODE_INIT = 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PROGRAM_COMMAND {
|
||||||
|
WRITE_CFG_PWR_DWN_SAVE = 0xC0,
|
||||||
|
READ_CONFIGURATION = 0xC1,
|
||||||
|
WRITE_CFG_PWR_DWN_LOSE = 0xC2,
|
||||||
|
WRONG_FORMAT = 0xFF,
|
||||||
|
RETURNED_COMMAND = 0xC1,
|
||||||
|
SPECIAL_WIFI_CONF_COMMAND = 0xCF
|
||||||
|
};
|
||||||
|
|
||||||
|
enum REGISTER_ADDRESS {
|
||||||
|
REG_ADDRESS_CFG = 0x00,
|
||||||
|
REG_ADDRESS_SPED = 0x02,
|
||||||
|
REG_ADDRESS_TRANS_MODE = 0x03,
|
||||||
|
REG_ADDRESS_CHANNEL = 0x04,
|
||||||
|
REG_ADDRESS_OPTION = 0x05,
|
||||||
|
REG_ADDRESS_CRYPT = 0x06,
|
||||||
|
REG_ADDRESS_PID = 0x08
|
||||||
|
};
|
||||||
|
|
||||||
|
enum PACKET_LENGHT {
|
||||||
|
PL_CONFIGURATION = 0x08,
|
||||||
|
|
||||||
|
PL_SPED = 0x01,
|
||||||
|
PL_OPTION = 0x01,
|
||||||
|
PL_TRANSMISSION_MODE= 0x01,
|
||||||
|
PL_CHANNEL = 0x01,
|
||||||
|
PL_CRYPT = 0x02,
|
||||||
|
PL_PID = 0x03
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct Speed {
|
||||||
|
uint8_t airDataRate :3; //bit 0-2
|
||||||
|
String getAirDataRateDescription() {
|
||||||
|
return getAirDataRateDescriptionByParams(this->airDataRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t uartParity :2; //bit 3-4
|
||||||
|
String getUARTParityDescription() {
|
||||||
|
return getUARTParityDescriptionByParams(this->uartParity);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t uartBaudRate :3; //bit 5-7
|
||||||
|
String getUARTBaudRateDescription() {
|
||||||
|
return getUARTBaudRateDescriptionByParams(this->uartBaudRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TransmissionMode {
|
||||||
|
byte WORPeriod :3; //bit 2,1,0
|
||||||
|
String getWORPeriodByParamsDescription() {
|
||||||
|
return getWORPeriodByParams(this->WORPeriod);
|
||||||
|
}
|
||||||
|
byte reserved2 :1; //bit 3
|
||||||
|
byte enableLBT :1; //bit 4
|
||||||
|
String getLBTEnableByteDescription() {
|
||||||
|
return getLBTEnableByteByParams(this->enableLBT);
|
||||||
|
}
|
||||||
|
byte reserved :1; //bit 5
|
||||||
|
|
||||||
|
byte fixedTransmission :1; //bit 6
|
||||||
|
String getFixedTransmissionDescription() {
|
||||||
|
return getFixedTransmissionDescriptionByParams(this->fixedTransmission);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte enableRSSI :1; //bit 7
|
||||||
|
String getRSSIEnableByteDescription() {
|
||||||
|
return getRSSIEnableByteByParams(this->enableRSSI);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Option {
|
||||||
|
uint8_t transmissionPower :2; //bit 0-1
|
||||||
|
String getTransmissionPowerDescription() {
|
||||||
|
return getTransmissionPowerDescriptionByParams(this->transmissionPower);
|
||||||
|
}
|
||||||
|
uint8_t reserved :3; //bit 2-4
|
||||||
|
|
||||||
|
uint8_t RSSIAmbientNoise :1; //bit 5
|
||||||
|
String getRSSIAmbientNoiseEnable() {
|
||||||
|
return getRSSIAmbientNoiseEnableByParams(this->RSSIAmbientNoise);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subPacketSetting :2; //bit 6-7
|
||||||
|
String getSubPacketSetting() {
|
||||||
|
return getSubPacketSettingByParams(this->subPacketSetting);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Crypt {
|
||||||
|
byte CRYPT_H = 0;
|
||||||
|
byte CRYPT_L = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Configuration {
|
||||||
|
byte COMMAND = 0;
|
||||||
|
byte STARTING_ADDRESS = 0;
|
||||||
|
byte LENGHT = 0;
|
||||||
|
|
||||||
|
byte ADDH = 0;
|
||||||
|
byte ADDL = 0;
|
||||||
|
|
||||||
|
struct Speed SPED;
|
||||||
|
struct Option OPTION;
|
||||||
|
|
||||||
|
byte CHAN = 0;
|
||||||
|
String getChannelDescription() {
|
||||||
|
return String(this->CHAN + OPERATING_FREQUENCY) + F("MHz");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TransmissionMode TRANSMISSION_MODE;
|
||||||
|
|
||||||
|
struct Crypt CRYPT;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ModuleInformation {
|
||||||
|
byte COMMAND = 0;
|
||||||
|
byte STARTING_ADDRESS = 0;
|
||||||
|
byte LENGHT = 0;
|
||||||
|
|
||||||
|
byte model = 0;
|
||||||
|
byte version = 0;
|
||||||
|
byte features = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ResponseStatus {
|
||||||
|
Status code;
|
||||||
|
String getResponseDescription() {
|
||||||
|
return getResponseDescriptionByParams(this->code);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ResponseStructContainer {
|
||||||
|
void *data;
|
||||||
|
byte rssi;
|
||||||
|
ResponseStatus status;
|
||||||
|
void close() {
|
||||||
|
free(this->data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct ResponseContainer {
|
||||||
|
String data;
|
||||||
|
byte rssi;
|
||||||
|
ResponseStatus status;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ConfigurationMessage
|
||||||
|
{
|
||||||
|
byte specialCommand1 = 0xCF;
|
||||||
|
byte specialCommand2 = 0xCF;
|
||||||
|
|
||||||
|
unsigned char message[];
|
||||||
|
};
|
||||||
|
|
||||||
|
//struct FixedStransmission {
|
||||||
|
// byte ADDL = 0;
|
||||||
|
// byte ADDH = 0;
|
||||||
|
// byte CHAN = 0;
|
||||||
|
// void *message;
|
||||||
|
//};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
class LoRa_E220 {
|
||||||
|
public:
|
||||||
|
#ifdef ACTIVATE_SOFTWARE_SERIAL
|
||||||
|
LoRa_E220(byte txE220pin, byte rxE220pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
|
||||||
|
LoRa_E220(byte txE220pin, byte rxE220pin, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
|
||||||
|
LoRa_E220(byte txE220pin, byte rxE220pin, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LoRa_E220(HardwareSerial* serial, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
|
||||||
|
LoRa_E220(HardwareSerial* serial, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
|
||||||
|
LoRa_E220(HardwareSerial* serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
|
||||||
|
|
||||||
|
#ifdef HARDWARE_SERIAL_SELECTABLE_PIN
|
||||||
|
LoRa_E220(byte txE220pin, byte rxE220pin, HardwareSerial* serial, UART_BPS_RATE bpsRate, uint32_t serialConfig = SERIAL_8N1);
|
||||||
|
LoRa_E220(byte txE220pin, byte rxE220pin, HardwareSerial* serial, byte auxPin, UART_BPS_RATE bpsRate, uint32_t serialConfig = SERIAL_8N1);
|
||||||
|
LoRa_E220(byte txE220pin, byte rxE220pin, HardwareSerial* serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate, uint32_t serialConfig = SERIAL_8N1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ACTIVATE_SOFTWARE_SERIAL
|
||||||
|
LoRa_E220(SoftwareSerial* serial, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
|
||||||
|
LoRa_E220(SoftwareSerial* serial, byte auxPin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
|
||||||
|
LoRa_E220(SoftwareSerial* serial, byte auxPin, byte m0Pin, byte m1Pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// LoRa_E220(byte txE220pin, byte rxE220pin, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600, MODE_TYPE mode = MODE_0_NORMAL);
|
||||||
|
// LoRa_E220(HardwareSerial* serial = &Serial, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600, MODE_TYPE mode = MODE_0_NORMAL);
|
||||||
|
// LoRa_E220(SoftwareSerial* serial, UART_BPS_RATE bpsRate = UART_BPS_RATE_9600, MODE_TYPE mode = MODE_0_NORMAL);
|
||||||
|
|
||||||
|
bool begin();
|
||||||
|
Status setMode(MODE_TYPE mode);
|
||||||
|
MODE_TYPE getMode();
|
||||||
|
|
||||||
|
ResponseStructContainer getConfiguration();
|
||||||
|
ResponseStatus setConfiguration(Configuration configuration, PROGRAM_COMMAND saveType = WRITE_CFG_PWR_DWN_LOSE);
|
||||||
|
|
||||||
|
ResponseStructContainer getModuleInformation();
|
||||||
|
ResponseStatus resetModule();
|
||||||
|
|
||||||
|
ResponseStatus sendMessage(const void *message, const uint8_t size);
|
||||||
|
|
||||||
|
ResponseContainer receiveMessageUntil(char delimiter = '\0');
|
||||||
|
ResponseStructContainer receiveMessage(const uint8_t size);
|
||||||
|
ResponseStructContainer receiveMessageRSSI(const uint8_t size);
|
||||||
|
|
||||||
|
ResponseStructContainer receiveMessageComplete(const uint8_t size, bool enableRSSI);
|
||||||
|
ResponseContainer receiveMessageComplete(bool enableRSSI);
|
||||||
|
|
||||||
|
ResponseStatus sendMessage(const String message);
|
||||||
|
ResponseContainer receiveMessage();
|
||||||
|
ResponseContainer receiveMessageRSSI();
|
||||||
|
|
||||||
|
ResponseStatus sendFixedMessage(byte ADDH, byte ADDL, byte CHAN, const String message);
|
||||||
|
|
||||||
|
ResponseStatus sendFixedMessage(byte ADDH,byte ADDL, byte CHAN, const void *message, const uint8_t size);
|
||||||
|
ResponseStatus sendBroadcastFixedMessage(byte CHAN, const void *message, const uint8_t size);
|
||||||
|
ResponseStatus sendBroadcastFixedMessage(byte CHAN, const String message);
|
||||||
|
|
||||||
|
ResponseContainer receiveInitialMessage(const uint8_t size);
|
||||||
|
|
||||||
|
ResponseStatus sendConfigurationMessage( byte ADDH,byte ADDL, byte CHAN, Configuration *configuration, PROGRAM_COMMAND programCommand = WRITE_CFG_PWR_DWN_SAVE);
|
||||||
|
|
||||||
|
int available();
|
||||||
|
|
||||||
|
void (*setMPins)(int, int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
HardwareSerial* hs;
|
||||||
|
|
||||||
|
#ifdef ACTIVATE_SOFTWARE_SERIAL
|
||||||
|
SoftwareSerial* ss;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool isSoftwareSerial = true;
|
||||||
|
|
||||||
|
int8_t txE220pin = -1;
|
||||||
|
int8_t rxE220pin = -1;
|
||||||
|
int8_t auxPin = -1;
|
||||||
|
|
||||||
|
#ifdef HARDWARE_SERIAL_SELECTABLE_PIN
|
||||||
|
uint32_t serialConfig = SERIAL_8N1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int8_t m0Pin = -1;
|
||||||
|
int8_t m1Pin = -1;
|
||||||
|
|
||||||
|
unsigned long halfKeyloqKey = 0x06660708;
|
||||||
|
unsigned long encrypt(unsigned long data);
|
||||||
|
unsigned long decrypt(unsigned long data);
|
||||||
|
|
||||||
|
UART_BPS_RATE bpsRate = UART_BPS_RATE_9600;
|
||||||
|
|
||||||
|
struct NeedsStream {
|
||||||
|
template<typename T>
|
||||||
|
void begin(T &t, uint32_t baud) {
|
||||||
|
DEBUG_PRINTLN("Begin ");
|
||||||
|
t.setTimeout(500);
|
||||||
|
t.begin(baud);
|
||||||
|
stream = &t;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HARDWARE_SERIAL_SELECTABLE_PIN
|
||||||
|
// template< typename T >
|
||||||
|
// void begin( T &t, uint32_t baud, SerialConfig config ){
|
||||||
|
// DEBUG_PRINTLN("Begin ");
|
||||||
|
// t.setTimeout(500);
|
||||||
|
// t.begin(baud, config);
|
||||||
|
// stream = &t;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
template< typename T >
|
||||||
|
void begin( T &t, uint32_t baud, uint32_t config ) {
|
||||||
|
DEBUG_PRINTLN("Begin ");
|
||||||
|
t.setTimeout(500);
|
||||||
|
t.begin(baud, config);
|
||||||
|
stream = &t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
void begin( T &t, uint32_t baud, uint32_t config, int8_t txE220pin, int8_t rxE220pin ) {
|
||||||
|
DEBUG_PRINTLN("Begin ");
|
||||||
|
t.setTimeout(500);
|
||||||
|
t.begin(baud, config, txE220pin, rxE220pin);
|
||||||
|
stream = &t;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void listen() {}
|
||||||
|
|
||||||
|
Stream *stream;
|
||||||
|
};
|
||||||
|
NeedsStream serialDef;
|
||||||
|
|
||||||
|
MODE_TYPE mode = MODE_0_NORMAL;
|
||||||
|
|
||||||
|
void managedDelay(unsigned long timeout);
|
||||||
|
Status waitCompleteResponse(unsigned long timeout = 1000, unsigned int waitNoAux = 100);
|
||||||
|
void flush();
|
||||||
|
void cleanUARTBuffer();
|
||||||
|
|
||||||
|
Status sendStruct(void *structureManaged, uint16_t size_);
|
||||||
|
Status receiveStruct(void *structureManaged, uint16_t size_);
|
||||||
|
void writeProgramCommand(PROGRAM_COMMAND cmd, REGISTER_ADDRESS addr, PACKET_LENGHT pl);
|
||||||
|
|
||||||
|
RESPONSE_STATUS checkUARTConfiguration(MODE_TYPE mode);
|
||||||
|
|
||||||
|
#ifdef LoRa_E220_DEBUG
|
||||||
|
void printParameters(struct Configuration *configuration);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
1090
Software/lib/EByte LoRa E220 library/README.md
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* LoRa E220
|
||||||
|
* Get configuration.
|
||||||
|
* You must uncommend the correct constructor.
|
||||||
|
*
|
||||||
|
* by Renzo Mischianti <https://www.mischianti.org>
|
||||||
|
*
|
||||||
|
* https://www.mischianti.org
|
||||||
|
*
|
||||||
|
* E220 ----- WeMos D1 mini ----- esp32 ----- Arduino Nano 33 IoT ----- Arduino MKR ----- Raspberry Pi Pico ----- stm32 ----- ArduinoUNO
|
||||||
|
* M0 ----- D7 (or 3.3v) ----- 19 (or 3.3v) ----- 4 (or 3.3v) ----- 2 (or 3.3v) ----- 10 (or 3.3v) ----- PB0 (or 3.3v) ----- 7 Volt div (or 3.3v)
|
||||||
|
* M1 ----- D6 (or 3.3v) ----- 21 (or 3.3v) ----- 6 (or 3.3v) ----- 4 (or 3.3v) ----- 11 (or 3.3v) ----- PB10 (or 3.3v) ----- 6 Volt div (or 3.3v)
|
||||||
|
* TX ----- D3 (PullUP) ----- TX2 (PullUP) ----- TX1 (PullUP) ----- 14 (PullUP) ----- 8 (PullUP) ----- PA2 TX2 (PullUP) ----- 4 (PullUP)
|
||||||
|
* RX ----- D4 (PullUP) ----- RX2 (PullUP) ----- RX1 (PullUP) ----- 13 (PullUP) ----- 9 (PullUP) ----- PA3 RX2 (PullUP) ----- 5 Volt div (PullUP)
|
||||||
|
* AUX ----- D5 (PullUP) ----- 18 (PullUP) ----- 2 (PullUP) ----- 0 (PullUP) ----- 2 (PullUP) ----- PA0 (PullUP) ----- 3 (PullUP)
|
||||||
|
* VCC ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v
|
||||||
|
* GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "LoRa_E220.h"
|
||||||
|
|
||||||
|
// ---------- esp8266 pins --------------
|
||||||
|
//LoRa_E220 e220ttl(RX, TX, AUX, M0, M1); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(D3, D4, D5, D7, D6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(D2, D3); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(D2, D3); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, D5, D7, D6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Arduino pins --------------
|
||||||
|
LoRa_E220 e220ttl(4, 5, 3, 7, 6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(4, 5); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(4, 5); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, 3, 7, 6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino Nano 33 IoT -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 2, 4, 6); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino MKR WiFi 1010 -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 0, 2, 4); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ---------- esp32 pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 15, 21, 19); // RX AUX M0 M1
|
||||||
|
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, 22, 4, 18, 21, 19, UART_BPS_RATE_9600); // esp32 RX <-- e220 TX, esp32 TX --> e220 RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Raspberry PI Pico pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 2, 10, 11); // RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------------- STM32 --------------------
|
||||||
|
//HardwareSerial Serial2(USART2); // PA3 (RX) PA2 (TX)
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, PA0, PB0, PB10); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
void printParameters(struct Configuration configuration);
|
||||||
|
void printModuleInformation(struct ModuleInformation moduleInformation);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
while(!Serial){};
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
|
||||||
|
// Startup all pins and UART
|
||||||
|
e220ttl.begin();
|
||||||
|
|
||||||
|
ResponseStructContainer c;
|
||||||
|
c = e220ttl.getConfiguration();
|
||||||
|
// It's important get configuration pointer before all other operation
|
||||||
|
Configuration configuration = *(Configuration*) c.data;
|
||||||
|
Serial.println(c.status.getResponseDescription());
|
||||||
|
Serial.println(c.status.code);
|
||||||
|
|
||||||
|
printParameters(configuration);
|
||||||
|
|
||||||
|
ResponseStructContainer cMi;
|
||||||
|
cMi = e220ttl.getModuleInformation();
|
||||||
|
// It's important get information pointer before all other operation
|
||||||
|
ModuleInformation mi = *(ModuleInformation*)cMi.data;
|
||||||
|
|
||||||
|
Serial.println(cMi.status.getResponseDescription());
|
||||||
|
Serial.println(cMi.status.code);
|
||||||
|
|
||||||
|
printModuleInformation(mi);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
}
|
||||||
|
void printParameters(struct Configuration configuration) {
|
||||||
|
Serial.println("----------------------------------------");
|
||||||
|
|
||||||
|
Serial.print(F("HEAD : ")); Serial.print(configuration.COMMAND, HEX);Serial.print(" ");Serial.print(configuration.STARTING_ADDRESS, HEX);Serial.print(" ");Serial.println(configuration.LENGHT, HEX);
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("AddH : ")); Serial.println(configuration.ADDH, HEX);
|
||||||
|
Serial.print(F("AddL : ")); Serial.println(configuration.ADDL, HEX);
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("Chan : ")); Serial.print(configuration.CHAN, DEC); Serial.print(" -> "); Serial.println(configuration.getChannelDescription());
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("SpeedParityBit : ")); Serial.print(configuration.SPED.uartParity, BIN);Serial.print(" -> "); Serial.println(configuration.SPED.getUARTParityDescription());
|
||||||
|
Serial.print(F("SpeedUARTDatte : ")); Serial.print(configuration.SPED.uartBaudRate, BIN);Serial.print(" -> "); Serial.println(configuration.SPED.getUARTBaudRateDescription());
|
||||||
|
Serial.print(F("SpeedAirDataRate : ")); Serial.print(configuration.SPED.airDataRate, BIN);Serial.print(" -> "); Serial.println(configuration.SPED.getAirDataRateDescription());
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("OptionSubPacketSett: ")); Serial.print(configuration.OPTION.subPacketSetting, BIN);Serial.print(" -> "); Serial.println(configuration.OPTION.getSubPacketSetting());
|
||||||
|
Serial.print(F("OptionTranPower : ")); Serial.print(configuration.OPTION.transmissionPower, BIN);Serial.print(" -> "); Serial.println(configuration.OPTION.getTransmissionPowerDescription());
|
||||||
|
Serial.print(F("OptionRSSIAmbientNo: ")); Serial.print(configuration.OPTION.RSSIAmbientNoise, BIN);Serial.print(" -> "); Serial.println(configuration.OPTION.getRSSIAmbientNoiseEnable());
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("TransModeWORPeriod : ")); Serial.print(configuration.TRANSMISSION_MODE.WORPeriod, BIN);Serial.print(" -> "); Serial.println(configuration.TRANSMISSION_MODE.getWORPeriodByParamsDescription());
|
||||||
|
Serial.print(F("TransModeEnableLBT : ")); Serial.print(configuration.TRANSMISSION_MODE.enableLBT, BIN);Serial.print(" -> "); Serial.println(configuration.TRANSMISSION_MODE.getLBTEnableByteDescription());
|
||||||
|
Serial.print(F("TransModeEnableRSSI: ")); Serial.print(configuration.TRANSMISSION_MODE.enableRSSI, BIN);Serial.print(" -> "); Serial.println(configuration.TRANSMISSION_MODE.getRSSIEnableByteDescription());
|
||||||
|
Serial.print(F("TransModeFixedTrans: ")); Serial.print(configuration.TRANSMISSION_MODE.fixedTransmission, BIN);Serial.print(" -> "); Serial.println(configuration.TRANSMISSION_MODE.getFixedTransmissionDescription());
|
||||||
|
|
||||||
|
|
||||||
|
Serial.println("----------------------------------------");
|
||||||
|
}
|
||||||
|
void printModuleInformation(struct ModuleInformation moduleInformation) {
|
||||||
|
Serial.println("----------------------------------------");
|
||||||
|
Serial.print(F("HEAD: ")); Serial.print(moduleInformation.COMMAND, HEX);Serial.print(" ");Serial.print(moduleInformation.STARTING_ADDRESS, HEX);Serial.print(" ");Serial.println(moduleInformation.LENGHT, DEC);
|
||||||
|
|
||||||
|
Serial.print(F("Model no.: ")); Serial.println(moduleInformation.model, HEX);
|
||||||
|
Serial.print(F("Version : ")); Serial.println(moduleInformation.version, HEX);
|
||||||
|
Serial.print(F("Features : ")); Serial.println(moduleInformation.features, HEX);
|
||||||
|
Serial.println("----------------------------------------");
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,417 @@
|
|||||||
|
/*
|
||||||
|
* LoRa E220
|
||||||
|
* Set configuration.
|
||||||
|
*
|
||||||
|
* You must uncommend the correct constructor.
|
||||||
|
*
|
||||||
|
* by Renzo Mischianti <https://www.mischianti.org>
|
||||||
|
*
|
||||||
|
* https://www.mischianti.org
|
||||||
|
*
|
||||||
|
* E220 ----- WeMos D1 mini ----- esp32 ----- Arduino Nano 33 IoT ----- Arduino MKR ----- Raspberry Pi Pico ----- stm32 ----- ArduinoUNO
|
||||||
|
* M0 ----- D7 (or 3.3v) ----- 19 (or 3.3v) ----- 4 (or 3.3v) ----- 2 (or 3.3v) ----- 10 (or 3.3v) ----- PB0 (or 3.3v) ----- 7 Volt div (or 3.3v)
|
||||||
|
* M1 ----- D6 (or 3.3v) ----- 21 (or 3.3v) ----- 6 (or 3.3v) ----- 4 (or 3.3v) ----- 11 (or 3.3v) ----- PB10 (or 3.3v) ----- 6 Volt div (or 3.3v)
|
||||||
|
* TX ----- D3 (PullUP) ----- TX2 (PullUP) ----- TX1 (PullUP) ----- 14 (PullUP) ----- 8 (PullUP) ----- PA2 TX2 (PullUP) ----- 4 (PullUP)
|
||||||
|
* RX ----- D4 (PullUP) ----- RX2 (PullUP) ----- RX1 (PullUP) ----- 13 (PullUP) ----- 9 (PullUP) ----- PA3 RX2 (PullUP) ----- 5 Volt div (PullUP)
|
||||||
|
* AUX ----- D5 (PullUP) ----- 18 (PullUP) ----- 2 (PullUP) ----- 0 (PullUP) ----- 2 (PullUP) ----- PA0 (PullUP) ----- 3 (PullUP)
|
||||||
|
* VCC ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v
|
||||||
|
* GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "LoRa_E220.h"
|
||||||
|
|
||||||
|
// ---------- esp8266 pins --------------
|
||||||
|
//LoRa_E220 e220ttl(RX, TX, AUX, M0, M1); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(D3, D4, D5, D7, D6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(D2, D3); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(D2, D3); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, D5, D7, D6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Arduino pins --------------
|
||||||
|
LoRa_E220 e220ttl(4, 5, 3, 7, 6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(4, 5); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(4, 5); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, 3, 7, 6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino Nano 33 IoT -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 2, 4, 6); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino MKR WiFi 1010 -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 0, 2, 4); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ---------- esp32 pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 15, 21, 19); // RX AUX M0 M1
|
||||||
|
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, 22, 4, 18, 21, 19, UART_BPS_RATE_9600); // esp32 RX <-- e220 TX, esp32 TX --> e220 RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Raspberry PI Pico pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 2, 10, 11); // RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------------- STM32 --------------------
|
||||||
|
//HardwareSerial Serial2(USART2); // PA3 (RX) PA2 (TX)
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, PA0, PB0, PB10); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
void printParameters(struct Configuration configuration);
|
||||||
|
void printModuleInformation(struct ModuleInformation moduleInformation);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
while(!Serial){};
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
|
||||||
|
// Startup all pins and UART
|
||||||
|
e220ttl.begin();
|
||||||
|
|
||||||
|
ResponseStructContainer c;
|
||||||
|
c = e220ttl.getConfiguration();
|
||||||
|
// It's important get configuration pointer before all other operation
|
||||||
|
Configuration configuration = *(Configuration*) c.data;
|
||||||
|
Serial.println(c.status.getResponseDescription());
|
||||||
|
Serial.println(c.status.code);
|
||||||
|
|
||||||
|
printParameters(configuration);
|
||||||
|
|
||||||
|
// ----------------------- DEFAULT TRANSPARENT -----------------------
|
||||||
|
configuration.ADDL = 0x03; // First part of address
|
||||||
|
configuration.ADDH = 0x00; // Second part
|
||||||
|
|
||||||
|
configuration.CHAN = 23; // Communication channel
|
||||||
|
|
||||||
|
configuration.SPED.uartBaudRate = UART_BPS_9600; // Serial baud rate
|
||||||
|
configuration.SPED.airDataRate = AIR_DATA_RATE_010_24; // Air baud rate
|
||||||
|
configuration.SPED.uartParity = MODE_00_8N1; // Parity bit
|
||||||
|
|
||||||
|
configuration.OPTION.subPacketSetting = SPS_200_00; // Packet size
|
||||||
|
configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED; // Need to send special command
|
||||||
|
configuration.OPTION.transmissionPower = POWER_22; // Device power
|
||||||
|
|
||||||
|
configuration.TRANSMISSION_MODE.enableRSSI = RSSI_DISABLED; // Enable RSSI info
|
||||||
|
configuration.TRANSMISSION_MODE.fixedTransmission = FT_TRANSPARENT_TRANSMISSION; // Enable repeater mode
|
||||||
|
configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED; // Check interference
|
||||||
|
configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011; // WOR timing
|
||||||
|
// ----------------------- DEFAULT TRANSPARENT WITH RSSI -----------------------
|
||||||
|
// configuration.ADDL = 0x03;
|
||||||
|
// configuration.ADDH = 0x00;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_ENABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_TRANSPARENT_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
// ----------------------- FIXED SENDER -----------------------
|
||||||
|
// configuration.ADDL = 0x02;
|
||||||
|
// configuration.ADDH = 0x00;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
//
|
||||||
|
// ----------------------- FIXED RECEIVER -----------------------
|
||||||
|
// configuration.ADDL = 0x03;
|
||||||
|
// configuration.ADDH = 0x00;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
// ----------------------- FIXED SENDER RSSI -----------------------
|
||||||
|
// configuration.ADDL = 0x02;
|
||||||
|
// configuration.ADDH = 0x00;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_ENABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
//
|
||||||
|
// ----------------------- FIXED RECEIVER RSSI -----------------------
|
||||||
|
// configuration.ADDL = 0x03;
|
||||||
|
// configuration.ADDH = 0x00;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_ENABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
//
|
||||||
|
// ----------------------- WOR SENDER -----------------------
|
||||||
|
// configuration.ADDL = 0x02;
|
||||||
|
// configuration.ADDH = 0x00;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
//
|
||||||
|
// ----------------------- WOR RECEIVER -----------------------
|
||||||
|
// configuration.ADDL = 0x03;
|
||||||
|
// configuration.ADDH = 0x00;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
// ----------------------- BROADCAST MESSAGE 1 -----------------------
|
||||||
|
// configuration.ADDL = 0x04;
|
||||||
|
// configuration.ADDH = 0x00;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
// ----------------------- BROADCAST MESSAGE 2 -----------------------
|
||||||
|
// configuration.ADDL = 0x05;
|
||||||
|
// configuration.ADDH = 0x00;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
// ----------------------- BROADCAST MESSAGE 3 -----------------------
|
||||||
|
// configuration.ADDL = 0x06;
|
||||||
|
// configuration.ADDH = 0x00;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
// ----------------------- BROADCAST MESSAGE RSSI 1 -----------------------
|
||||||
|
// configuration.ADDL = 0x04;
|
||||||
|
// configuration.ADDH = 0x00;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_ENABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
// ----------------------- BROADCAST MESSAGE RSSI 2 -----------------------
|
||||||
|
// configuration.ADDL = 0x05;
|
||||||
|
// configuration.ADDH = 0x00;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_ENABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
// ----------------------- BROADCAST MESSAGE RSSI 3 -----------------------
|
||||||
|
// configuration.ADDL = 0x06;
|
||||||
|
// configuration.ADDH = 0x00;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_ENABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
// ----------------------- MONITORING -----------------------
|
||||||
|
// configuration.ADDL = BROADCAST_ADDRESS;
|
||||||
|
// configuration.ADDH = BROADCAST_ADDRESS;
|
||||||
|
//
|
||||||
|
// configuration.CHAN = 23;
|
||||||
|
//
|
||||||
|
// configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
// configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
// configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
//
|
||||||
|
// configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
// configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_DISABLED;
|
||||||
|
// configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
//
|
||||||
|
// configuration.TRANSMISSION_MODE.enableRSSI = RSSI_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
// configuration.TRANSMISSION_MODE.enableLBT = LBT_DISABLED;
|
||||||
|
// configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
|
||||||
|
// Set configuration changed and set to not hold the configuration
|
||||||
|
ResponseStatus rs = e220ttl.setConfiguration(configuration, WRITE_CFG_PWR_DWN_SAVE);
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
Serial.println(rs.code);
|
||||||
|
|
||||||
|
c = e220ttl.getConfiguration();
|
||||||
|
// It's important get configuration pointer before all other operation
|
||||||
|
configuration = *(Configuration*) c.data;
|
||||||
|
Serial.println(c.status.getResponseDescription());
|
||||||
|
Serial.println(c.status.code);
|
||||||
|
|
||||||
|
printParameters(configuration);
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
}
|
||||||
|
void printParameters(struct Configuration configuration) {
|
||||||
|
DEBUG_PRINTLN("----------------------------------------");
|
||||||
|
|
||||||
|
DEBUG_PRINT(F("HEAD : ")); DEBUG_PRINT(configuration.COMMAND, HEX);DEBUG_PRINT(" ");DEBUG_PRINT(configuration.STARTING_ADDRESS, HEX);DEBUG_PRINT(" ");DEBUG_PRINTLN(configuration.LENGHT, HEX);
|
||||||
|
DEBUG_PRINTLN(F(" "));
|
||||||
|
DEBUG_PRINT(F("AddH : ")); DEBUG_PRINTLN(configuration.ADDH, HEX);
|
||||||
|
DEBUG_PRINT(F("AddL : ")); DEBUG_PRINTLN(configuration.ADDL, HEX);
|
||||||
|
DEBUG_PRINTLN(F(" "));
|
||||||
|
DEBUG_PRINT(F("Chan : ")); DEBUG_PRINT(configuration.CHAN, DEC); DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.getChannelDescription());
|
||||||
|
DEBUG_PRINTLN(F(" "));
|
||||||
|
DEBUG_PRINT(F("SpeedParityBit : ")); DEBUG_PRINT(configuration.SPED.uartParity, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.SPED.getUARTParityDescription());
|
||||||
|
DEBUG_PRINT(F("SpeedUARTDatte : ")); DEBUG_PRINT(configuration.SPED.uartBaudRate, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.SPED.getUARTBaudRateDescription());
|
||||||
|
DEBUG_PRINT(F("SpeedAirDataRate : ")); DEBUG_PRINT(configuration.SPED.airDataRate, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.SPED.getAirDataRateDescription());
|
||||||
|
DEBUG_PRINTLN(F(" "));
|
||||||
|
DEBUG_PRINT(F("OptionSubPacketSett: ")); DEBUG_PRINT(configuration.OPTION.subPacketSetting, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.OPTION.getSubPacketSetting());
|
||||||
|
DEBUG_PRINT(F("OptionTranPower : ")); DEBUG_PRINT(configuration.OPTION.transmissionPower, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.OPTION.getTransmissionPowerDescription());
|
||||||
|
DEBUG_PRINT(F("OptionRSSIAmbientNo: ")); DEBUG_PRINT(configuration.OPTION.RSSIAmbientNoise, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.OPTION.getRSSIAmbientNoiseEnable());
|
||||||
|
DEBUG_PRINTLN(F(" "));
|
||||||
|
DEBUG_PRINT(F("TransModeWORPeriod : ")); DEBUG_PRINT(configuration.TRANSMISSION_MODE.WORPeriod, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.TRANSMISSION_MODE.getWORPeriodByParamsDescription());
|
||||||
|
DEBUG_PRINT(F("TransModeEnableLBT : ")); DEBUG_PRINT(configuration.TRANSMISSION_MODE.enableLBT, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.TRANSMISSION_MODE.getLBTEnableByteDescription());
|
||||||
|
DEBUG_PRINT(F("TransModeEnableRSSI: ")); DEBUG_PRINT(configuration.TRANSMISSION_MODE.enableRSSI, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.TRANSMISSION_MODE.getRSSIEnableByteDescription());
|
||||||
|
DEBUG_PRINT(F("TransModeFixedTrans: ")); DEBUG_PRINT(configuration.TRANSMISSION_MODE.fixedTransmission, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.TRANSMISSION_MODE.getFixedTransmissionDescription());
|
||||||
|
|
||||||
|
|
||||||
|
DEBUG_PRINTLN("----------------------------------------");
|
||||||
|
}
|
||||||
|
void printModuleInformation(struct ModuleInformation moduleInformation) {
|
||||||
|
Serial.println("----------------------------------------");
|
||||||
|
DEBUG_PRINT(F("HEAD: ")); DEBUG_PRINT(moduleInformation.COMMAND, HEX);DEBUG_PRINT(" ");DEBUG_PRINT(moduleInformation.STARTING_ADDRESS, HEX);DEBUG_PRINT(" ");DEBUG_PRINTLN(moduleInformation.LENGHT, DEC);
|
||||||
|
|
||||||
|
Serial.print(F("Model no.: ")); Serial.println(moduleInformation.model, HEX);
|
||||||
|
Serial.print(F("Version : ")); Serial.println(moduleInformation.version, HEX);
|
||||||
|
Serial.print(F("Features : ")); Serial.println(moduleInformation.features, HEX);
|
||||||
|
Serial.println("----------------------------------------");
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* EBYTE LoRa E220
|
||||||
|
* send a transparent message, you must check that the transmitter and receiver have the same
|
||||||
|
* CHANNEL ADDL and ADDH
|
||||||
|
*
|
||||||
|
* Pay attention e220 support RSSI, if you want use that functionality you must enable RSSI on configuration
|
||||||
|
* configuration.TRANSMISSION_MODE.enableRSSI = RSSI_ENABLED;
|
||||||
|
*
|
||||||
|
* and uncomment #define ENABLE_RSSI true in this sketch
|
||||||
|
*
|
||||||
|
* You must uncommend the correct constructor.
|
||||||
|
*
|
||||||
|
* by Renzo Mischianti <https://www.mischianti.org>
|
||||||
|
*
|
||||||
|
* https://www.mischianti.org
|
||||||
|
*
|
||||||
|
* E220 ----- WeMos D1 mini ----- esp32 ----- Arduino Nano 33 IoT ----- Arduino MKR ----- Raspberry Pi Pico ----- stm32 ----- ArduinoUNO
|
||||||
|
* M0 ----- D7 (or GND) ----- 19 (or GND) ----- 4 (or GND) ----- 2 (or GND) ----- 10 (or GND) ----- PB0 (or GND) ----- 7 Volt div (or GND)
|
||||||
|
* M1 ----- D6 (or GND) ----- 21 (or GND) ----- 6 (or GND) ----- 4 (or GND) ----- 11 (or GND) ----- PB10 (or GND) ----- 6 Volt div (or GND)
|
||||||
|
* TX ----- D3 (PullUP) ----- TX2 (PullUP) ----- TX1 (PullUP) ----- 14 (PullUP) ----- 8 (PullUP) ----- PA2 TX2 (PullUP) ----- 4 (PullUP)
|
||||||
|
* RX ----- D4 (PullUP) ----- RX2 (PullUP) ----- RX1 (PullUP) ----- 13 (PullUP) ----- 9 (PullUP) ----- PA3 RX2 (PullUP) ----- 5 Volt div (PullUP)
|
||||||
|
* AUX ----- D5 (PullUP) ----- 18 (PullUP) ----- 2 (PullUP) ----- 0 (PullUP) ----- 2 (PullUP) ----- PA0 (PullUP) ----- 3 (PullUP)
|
||||||
|
* VCC ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v
|
||||||
|
* GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define ENABLE_RSSI true
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "LoRa_E220.h"
|
||||||
|
|
||||||
|
// ---------- esp8266 pins --------------
|
||||||
|
//LoRa_E220 e220ttl(RX, TX, AUX, M0, M1); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(D3, D4, D5, D7, D6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(D2, D3); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(D2, D3); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, D5, D7, D6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Arduino pins --------------
|
||||||
|
LoRa_E220 e220ttl(4, 5, 3, 7, 6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(4, 5); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(4, 5); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, 3, 7, 6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino Nano 33 IoT -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 2, 4, 6); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino MKR WiFi 1010 -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 0, 2, 4); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ---------- esp32 pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 15, 21, 19); // RX AUX M0 M1
|
||||||
|
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, 22, 4, 18, 21, 19, UART_BPS_RATE_9600); // esp32 RX <-- e220 TX, esp32 TX --> e220 RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Raspberry PI Pico pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 2, 10, 11); // RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------------- STM32 --------------------
|
||||||
|
//HardwareSerial Serial2(USART2); // PA3 (RX) PA2 (TX)
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, PA0, PB0, PB10); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// Startup all pins and UART
|
||||||
|
e220ttl.begin();
|
||||||
|
|
||||||
|
// If you have ever change configuration you must restore It
|
||||||
|
|
||||||
|
Serial.println("Hi, I'm going to send message!");
|
||||||
|
// Send message
|
||||||
|
ResponseStatus rs = e220ttl.sendMessage("Hello, world?");
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// If something available
|
||||||
|
if (e220ttl.available()>1) {
|
||||||
|
// read the String message
|
||||||
|
#ifdef ENABLE_RSSI
|
||||||
|
ResponseContainer rc = e220ttl.receiveMessageRSSI();
|
||||||
|
#else
|
||||||
|
ResponseContainer rc = e220ttl.receiveMessage();
|
||||||
|
#endif
|
||||||
|
// Is something goes wrong print error
|
||||||
|
if (rc.status.code!=1){
|
||||||
|
Serial.println(rc.status.getResponseDescription());
|
||||||
|
}else{
|
||||||
|
// Print the data received
|
||||||
|
Serial.println(rc.status.getResponseDescription());
|
||||||
|
Serial.println(rc.data);
|
||||||
|
#ifdef ENABLE_RSSI
|
||||||
|
Serial.print("RSSI: "); Serial.println(rc.rssi, DEC);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Serial.available()) {
|
||||||
|
String input = Serial.readString();
|
||||||
|
e220ttl.sendMessage(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
* EBYTE LoRa E220
|
||||||
|
* Send a string message to a fixed point ADDH ADDL CHAN
|
||||||
|
*
|
||||||
|
* You must configure 2 device: one as SENDER (with FIXED SENDER config) and uncomment the relative
|
||||||
|
* define with the correct DESTINATION_ADDL, and one as RECEIVER (with FIXED RECEIVER config)
|
||||||
|
* and uncomment the relative define with the correct DESTINATION_ADDL.
|
||||||
|
*
|
||||||
|
* Write a string on serial monitor or reset to resend default value.
|
||||||
|
*
|
||||||
|
* Pai attention e220 support RSSI, if you want use that functionality you must enable RSSI on configuration
|
||||||
|
* configuration.TRANSMISSION_MODE.enableRSSI = RSSI_ENABLED;
|
||||||
|
*
|
||||||
|
* and uncomment #define ENABLE_RSSI true in this sketch
|
||||||
|
*
|
||||||
|
* You must uncommend the correct constructor.
|
||||||
|
*
|
||||||
|
* by Renzo Mischianti <https://www.mischianti.org>
|
||||||
|
*
|
||||||
|
* https://www.mischianti.org
|
||||||
|
*
|
||||||
|
* E220 ----- WeMos D1 mini ----- esp32 ----- Arduino Nano 33 IoT ----- Arduino MKR ----- Raspberry Pi Pico ----- stm32 ----- ArduinoUNO
|
||||||
|
* M0 ----- D7 (or GND) ----- 19 (or GND) ----- 4 (or GND) ----- 2 (or GND) ----- 10 (or GND) ----- PB0 (or GND) ----- 7 Volt div (or GND)
|
||||||
|
* M1 ----- D6 (or GND) ----- 21 (or GND) ----- 6 (or GND) ----- 4 (or GND) ----- 11 (or GND) ----- PB10 (or GND) ----- 6 Volt div (or GND)
|
||||||
|
* TX ----- D3 (PullUP) ----- TX2 (PullUP) ----- TX1 (PullUP) ----- 14 (PullUP) ----- 8 (PullUP) ----- PA2 TX2 (PullUP) ----- 4 (PullUP)
|
||||||
|
* RX ----- D4 (PullUP) ----- RX2 (PullUP) ----- RX1 (PullUP) ----- 13 (PullUP) ----- 9 (PullUP) ----- PA3 RX2 (PullUP) ----- 5 Volt div (PullUP)
|
||||||
|
* AUX ----- D5 (PullUP) ----- 18 (PullUP) ----- 2 (PullUP) ----- 0 (PullUP) ----- 2 (PullUP) ----- PA0 (PullUP) ----- 3 (PullUP)
|
||||||
|
* VCC ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v
|
||||||
|
* GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// With FIXED SENDER configuration
|
||||||
|
// #define DESTINATION_ADDL 3
|
||||||
|
|
||||||
|
// With FIXED RECEIVER configuration
|
||||||
|
#define DESTINATION_ADDL 2
|
||||||
|
|
||||||
|
// If you want use RSSI uncomment //#define ENABLE_RSSI true
|
||||||
|
// and use relative configuration with RSSI enabled
|
||||||
|
//#define ENABLE_RSSI true
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "LoRa_E220.h"
|
||||||
|
|
||||||
|
// ---------- esp8266 pins --------------
|
||||||
|
//LoRa_E220 e220ttl(RX, TX, AUX, M0, M1); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(D3, D4, D5, D7, D6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(D2, D3); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(D2, D3); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, D5, D7, D6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Arduino pins --------------
|
||||||
|
LoRa_E220 e220ttl(4, 5, 3, 7, 6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(4, 5); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(4, 5); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, 3, 7, 6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino Nano 33 IoT -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 2, 4, 6); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino MKR WiFi 1010 -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 0, 2, 4); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ---------- esp32 pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 15, 21, 19); // RX AUX M0 M1
|
||||||
|
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, 22, 4, 18, 21, 19, UART_BPS_RATE_9600); // esp32 RX <-- e220 TX, esp32 TX --> e220 RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Raspberry PI Pico pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 2, 10, 11); // RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------------- STM32 --------------------
|
||||||
|
//HardwareSerial Serial2(USART2); // PA3 (RX) PA2 (TX)
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, PA0, PB0, PB10); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
void printParameters(struct Configuration configuration);
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// Startup all pins and UART
|
||||||
|
e220ttl.begin();
|
||||||
|
|
||||||
|
ResponseStructContainer c;
|
||||||
|
c = e220ttl.getConfiguration();
|
||||||
|
// It's important get configuration pointer before all other operation
|
||||||
|
Configuration configuration = *(Configuration*) c.data;
|
||||||
|
Serial.println(c.status.getResponseDescription());
|
||||||
|
Serial.println(c.status.code);
|
||||||
|
|
||||||
|
printParameters(configuration);
|
||||||
|
c.close();
|
||||||
|
|
||||||
|
Serial.println("Hi, I'm going to send message!");
|
||||||
|
|
||||||
|
// Send message
|
||||||
|
ResponseStatus rs = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 23, "Hello, world?");
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// If something available
|
||||||
|
if (e220ttl.available()>1) {
|
||||||
|
// read the String message
|
||||||
|
#ifdef ENABLE_RSSI
|
||||||
|
ResponseContainer rc = e220ttl.receiveMessageRSSI();
|
||||||
|
#else
|
||||||
|
ResponseContainer rc = e220ttl.receiveMessage();
|
||||||
|
#endif
|
||||||
|
// Is something goes wrong print error
|
||||||
|
if (rc.status.code!=1){
|
||||||
|
Serial.println(rc.status.getResponseDescription());
|
||||||
|
}else{
|
||||||
|
// Print the data received
|
||||||
|
Serial.println(rc.status.getResponseDescription());
|
||||||
|
Serial.println(rc.data);
|
||||||
|
#ifdef ENABLE_RSSI
|
||||||
|
Serial.print("RSSI: "); Serial.println(rc.rssi, DEC);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Serial.available()) {
|
||||||
|
String input = Serial.readString();
|
||||||
|
ResponseStatus rs = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 23, input);
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void printParameters(struct Configuration configuration) {
|
||||||
|
Serial.println("----------------------------------------");
|
||||||
|
|
||||||
|
Serial.print(F("HEAD : ")); Serial.print(configuration.COMMAND, HEX);Serial.print(" ");Serial.print(configuration.STARTING_ADDRESS, HEX);Serial.print(" ");Serial.println(configuration.LENGHT, HEX);
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("AddH : ")); Serial.println(configuration.ADDH, HEX);
|
||||||
|
Serial.print(F("AddL : ")); Serial.println(configuration.ADDL, HEX);
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("Chan : ")); Serial.print(configuration.CHAN, DEC); Serial.print(" -> "); Serial.println(configuration.getChannelDescription());
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("SpeedParityBit : ")); Serial.print(configuration.SPED.uartParity, BIN);Serial.print(" -> "); Serial.println(configuration.SPED.getUARTParityDescription());
|
||||||
|
Serial.print(F("SpeedUARTDatte : ")); Serial.print(configuration.SPED.uartBaudRate, BIN);Serial.print(" -> "); Serial.println(configuration.SPED.getUARTBaudRateDescription());
|
||||||
|
Serial.print(F("SpeedAirDataRate : ")); Serial.print(configuration.SPED.airDataRate, BIN);Serial.print(" -> "); Serial.println(configuration.SPED.getAirDataRateDescription());
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("OptionSubPacketSett: ")); Serial.print(configuration.OPTION.subPacketSetting, BIN);Serial.print(" -> "); Serial.println(configuration.OPTION.getSubPacketSetting());
|
||||||
|
Serial.print(F("OptionTranPower : ")); Serial.print(configuration.OPTION.transmissionPower, BIN);Serial.print(" -> "); Serial.println(configuration.OPTION.getTransmissionPowerDescription());
|
||||||
|
Serial.print(F("OptionRSSIAmbientNo: ")); Serial.print(configuration.OPTION.RSSIAmbientNoise, BIN);Serial.print(" -> "); Serial.println(configuration.OPTION.getRSSIAmbientNoiseEnable());
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("TransModeWORPeriod : ")); Serial.print(configuration.TRANSMISSION_MODE.WORPeriod, BIN);Serial.print(" -> "); Serial.println(configuration.TRANSMISSION_MODE.getWORPeriodByParamsDescription());
|
||||||
|
Serial.print(F("TransModeEnableLBT : ")); Serial.print(configuration.TRANSMISSION_MODE.enableLBT, BIN);Serial.print(" -> "); Serial.println(configuration.TRANSMISSION_MODE.getLBTEnableByteDescription());
|
||||||
|
Serial.print(F("TransModeEnableRSSI: ")); Serial.print(configuration.TRANSMISSION_MODE.enableRSSI, BIN);Serial.print(" -> "); Serial.println(configuration.TRANSMISSION_MODE.getRSSIEnableByteDescription());
|
||||||
|
Serial.print(F("TransModeFixedTrans: ")); Serial.print(configuration.TRANSMISSION_MODE.fixedTransmission, BIN);Serial.print(" -> "); Serial.println(configuration.TRANSMISSION_MODE.getFixedTransmissionDescription());
|
||||||
|
|
||||||
|
Serial.println("----------------------------------------");
|
||||||
|
}
|
@@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* EBYTE LoRa E220
|
||||||
|
* send a structured message to the device that have ADDH ADDL CHAN -> 0 DESTINATION_ADDL 23
|
||||||
|
*
|
||||||
|
* write the int humidity value on serial (or reset device that send default message)
|
||||||
|
*
|
||||||
|
* You must configure 2 device: one as SENDER (with FIXED SENDER config) and uncomment the relative
|
||||||
|
* define with the correct DESTINATION_ADDL, and one as RECEIVER (with FIXED RECEIVER config)
|
||||||
|
* and uncomment the relative define with the correct DESTINATION_ADDL.
|
||||||
|
*
|
||||||
|
* Write a string on serial monitor or reset to resend default value.
|
||||||
|
*
|
||||||
|
* Pay attention e220 support RSSI, if you want use that functionality you must enable RSSI on configuration
|
||||||
|
* configuration.TRANSMISSION_MODE.enableRSSI = RSSI_ENABLED;
|
||||||
|
*
|
||||||
|
* and uncomment #define ENABLE_RSSI true in this sketch
|
||||||
|
*
|
||||||
|
* You must uncommend the correct constructor and set the correct AUX_PIN define.
|
||||||
|
*
|
||||||
|
* by Renzo Mischianti <https://www.mischianti.org>
|
||||||
|
*
|
||||||
|
* https://www.mischianti.org
|
||||||
|
*
|
||||||
|
* E220 ----- WeMos D1 mini ----- esp32 ----- Arduino Nano 33 IoT ----- Arduino MKR ----- Raspberry Pi Pico ----- stm32 ----- ArduinoUNO
|
||||||
|
* M0 ----- D7 (or GND) ----- 19 (or GND) ----- 4 (or GND) ----- 2 (or GND) ----- 10 (or GND) ----- PB0 (or GND) ----- 7 Volt div (or GND)
|
||||||
|
* M1 ----- D6 (or GND) ----- 21 (or GND) ----- 6 (or GND) ----- 4 (or GND) ----- 11 (or GND) ----- PB10 (or GND) ----- 6 Volt div (or GND)
|
||||||
|
* TX ----- D3 (PullUP) ----- TX2 (PullUP) ----- TX1 (PullUP) ----- 14 (PullUP) ----- 8 (PullUP) ----- PA2 TX2 (PullUP) ----- 4 (PullUP)
|
||||||
|
* RX ----- D4 (PullUP) ----- RX2 (PullUP) ----- RX1 (PullUP) ----- 13 (PullUP) ----- 9 (PullUP) ----- PA3 RX2 (PullUP) ----- 5 Volt div (PullUP)
|
||||||
|
* AUX ----- D5 (PullUP) ----- 18 (PullUP) ----- 2 (PullUP) ----- 0 (PullUP) ----- 2 (PullUP) ----- PA0 (PullUP) ----- 3 (PullUP)
|
||||||
|
* VCC ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v
|
||||||
|
* GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// With FIXED SENDER configuration
|
||||||
|
#define DESTINATION_ADDL 3
|
||||||
|
#define ROOM "Kitchen"
|
||||||
|
|
||||||
|
// With FIXED RECEIVER configuration
|
||||||
|
//#define DESTINATION_ADDL 2
|
||||||
|
//#define ROOM "Bath"
|
||||||
|
|
||||||
|
// If you want use RSSI uncomment //#define ENABLE_RSSI true
|
||||||
|
// and use relative configuration with RSSI enabled
|
||||||
|
// #define ENABLE_RSSI true
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "LoRa_E220.h"
|
||||||
|
|
||||||
|
// ---------- esp8266 pins --------------
|
||||||
|
//LoRa_E220 e220ttl(RX, TX, AUX, M0, M1); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(D3, D4, D5, D7, D6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(D2, D3); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(D2, D3); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, D5, D7, D6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Arduino pins --------------
|
||||||
|
//LoRa_E220 e220ttl(4, 5, 3, 7, 6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(4, 5); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(4, 5); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, 3, 7, 6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino Nano 33 IoT -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 2, 4, 6); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino MKR WiFi 1010 -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 0, 2, 4); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ---------- esp32 pins --------------
|
||||||
|
LoRa_E220 e220ttl(&Serial2, 15, 21, 19); // RX AUX M0 M1
|
||||||
|
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, 22, 4, 18, 21, 19, UART_BPS_RATE_9600); // esp32 RX <-- e220 TX, esp32 TX --> e220 RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Raspberry PI Pico pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 2, 10, 11); // RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------------- STM32 --------------------
|
||||||
|
//HardwareSerial Serial2(USART2); // PA3 (RX) PA2 (TX)
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, PA0, PB0, PB10); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
struct Message {
|
||||||
|
char type[5];
|
||||||
|
char message[8];
|
||||||
|
float temperature;
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// Startup all pins and UART
|
||||||
|
e220ttl.begin();
|
||||||
|
|
||||||
|
Serial.println("Hi, I'm going to send message!");
|
||||||
|
|
||||||
|
struct Message message = {"TEMP", ROOM, 19.2};
|
||||||
|
|
||||||
|
// Send message
|
||||||
|
ResponseStatus rs = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 23, &message, sizeof(Message));
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// If something available
|
||||||
|
if (e220ttl.available()>1) {
|
||||||
|
// read the String message
|
||||||
|
#ifdef ENABLE_RSSI
|
||||||
|
ResponseStructContainer rsc = e220ttl.receiveMessageRSSI(sizeof(Message));
|
||||||
|
#else
|
||||||
|
ResponseStructContainer rsc = e220ttl.receiveMessage(sizeof(Message));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Is something goes wrong print error
|
||||||
|
if (rsc.status.code!=1){
|
||||||
|
Serial.println(rsc.status.getResponseDescription());
|
||||||
|
}else{
|
||||||
|
// Print the data received
|
||||||
|
Serial.println(rsc.status.getResponseDescription());
|
||||||
|
struct Message message = *(Message*) rsc.data;
|
||||||
|
Serial.println(message.type);
|
||||||
|
Serial.println(message.message);
|
||||||
|
Serial.println(message.temperature);
|
||||||
|
|
||||||
|
#ifdef ENABLE_RSSI
|
||||||
|
Serial.print("RSSI: "); Serial.println(rsc.rssi, DEC);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Serial.available()) {
|
||||||
|
struct Message message = { "TEMP", ROOM, 0 };
|
||||||
|
message.temperature = Serial.parseFloat();
|
||||||
|
|
||||||
|
// Send message
|
||||||
|
ResponseStatus rs = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 23, &message, sizeof(Message));
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
* EBYTE LoRa E220
|
||||||
|
* send a structured message to the device that have ADDH ADDL CHAN -> 0 DESTINATION_ADDL 23
|
||||||
|
*
|
||||||
|
* The receiver read the first part of the packet and undestand the type.
|
||||||
|
* If the type is HUMI read the message and the humidity as int
|
||||||
|
* else read the temperature as float.
|
||||||
|
* I use byte array because some microcontroller can have different size for float
|
||||||
|
*
|
||||||
|
* You must configure 2 device: one as SENDER (with FIXED SENDER config) and uncomment the relative
|
||||||
|
* define with the correct DESTINATION_ADDL, and one as RECEIVER (with FIXED RECEIVER config)
|
||||||
|
* and uncomment the relative define with the correct DESTINATION_ADDL.
|
||||||
|
*
|
||||||
|
* Write a string on serial monitor or reset to resend default value.
|
||||||
|
*
|
||||||
|
* You must uncommend the correct constructor and set the correct AUX_PIN define.
|
||||||
|
*
|
||||||
|
* by Renzo Mischianti <https://www.mischianti.org>
|
||||||
|
*
|
||||||
|
* https://www.mischianti.org
|
||||||
|
*
|
||||||
|
* E220 ----- WeMos D1 mini ----- esp32 ----- Arduino Nano 33 IoT ----- Arduino MKR ----- Raspberry Pi Pico ----- stm32 ----- ArduinoUNO
|
||||||
|
* M0 ----- D7 (or GND) ----- 19 (or GND) ----- 4 (or GND) ----- 2 (or GND) ----- 10 (or GND) ----- PB0 (or GND) ----- 7 Volt div (or GND)
|
||||||
|
* M1 ----- D6 (or GND) ----- 21 (or GND) ----- 6 (or GND) ----- 4 (or GND) ----- 11 (or GND) ----- PB10 (or GND) ----- 6 Volt div (or GND)
|
||||||
|
* TX ----- D3 (PullUP) ----- TX2 (PullUP) ----- TX1 (PullUP) ----- 14 (PullUP) ----- 8 (PullUP) ----- PA2 TX2 (PullUP) ----- 4 (PullUP)
|
||||||
|
* RX ----- D4 (PullUP) ----- RX2 (PullUP) ----- RX1 (PullUP) ----- 13 (PullUP) ----- 9 (PullUP) ----- PA3 RX2 (PullUP) ----- 5 Volt div (PullUP)
|
||||||
|
* AUX ----- D5 (PullUP) ----- 18 (PullUP) ----- 2 (PullUP) ----- 0 (PullUP) ----- 2 (PullUP) ----- PA0 (PullUP) ----- 3 (PullUP)
|
||||||
|
* VCC ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v
|
||||||
|
* GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MESSAGE_TYPE "HUMI"
|
||||||
|
|
||||||
|
// With FIXED SENDER configuration
|
||||||
|
//#define DESTINATION_ADDL 3
|
||||||
|
//#define ROOM "Kitchen"
|
||||||
|
|
||||||
|
// With FIXED RECEIVER configuration
|
||||||
|
#define DESTINATION_ADDL 2
|
||||||
|
#define ROOM "Bathroo"
|
||||||
|
|
||||||
|
// If you want use RSSI uncomment //#define ENABLE_RSSI true
|
||||||
|
// and use relative configuration with RSSI enabled
|
||||||
|
// #define ENABLE_RSSI true
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "LoRa_E220.h"
|
||||||
|
|
||||||
|
// ---------- esp8266 pins --------------
|
||||||
|
//LoRa_E220 e220ttl(RX, TX, AUX, M0, M1); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(D3, D4, D5, D7, D6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(D2, D3); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(D2, D3); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, D5, D7, D6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Arduino pins --------------
|
||||||
|
//LoRa_E220 e220ttl(4, 5, 3, 7, 6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(4, 5); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(4, 5); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, 3, 7, 6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino Nano 33 IoT -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 2, 4, 6); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino MKR WiFi 1010 -------------
|
||||||
|
LoRa_E220 e220ttl(&Serial1, 0, 2, 4); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ---------- esp32 pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 15, 21, 19); // RX AUX M0 M1
|
||||||
|
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, 22, 4, 18, 21, 19, UART_BPS_RATE_9600); // esp32 RX <-- e220 TX, esp32 TX --> e220 RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Raspberry PI Pico pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 2, 10, 11); // RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------------- STM32 --------------------
|
||||||
|
//HardwareSerial Serial2(USART2); // PA3 (RX) PA2 (TX)
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, PA0, PB0, PB10); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
struct MessageTemperature {
|
||||||
|
char type[5];
|
||||||
|
char message[8];
|
||||||
|
byte temperature[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MessageHumidity {
|
||||||
|
char type[5];
|
||||||
|
char message[8];
|
||||||
|
byte humidity;
|
||||||
|
};
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// Startup all pins and UART
|
||||||
|
e220ttl.begin();
|
||||||
|
|
||||||
|
Serial.println("Hi, I'm going to send message!");
|
||||||
|
|
||||||
|
struct MessageHumidity message = { "HUMI", ROOM, 80 };
|
||||||
|
// Send message
|
||||||
|
ResponseStatus rs = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 23, &message, sizeof(MessageHumidity));
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
|
||||||
|
struct MessageTemperature messageT = { "TEMP", ROOM, 0 };
|
||||||
|
*(float*)(messageT.temperature) = 19.2;
|
||||||
|
|
||||||
|
// Send message
|
||||||
|
ResponseStatus rsT = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 23, &messageT, sizeof(MessageTemperature));
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rsT.getResponseDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// If something available
|
||||||
|
if (e220ttl.available() > 1) {
|
||||||
|
// read the String message
|
||||||
|
char type[5]; // first part of structure
|
||||||
|
ResponseContainer rs = e220ttl.receiveInitialMessage(sizeof(type));
|
||||||
|
String typeStr = rs.data;
|
||||||
|
|
||||||
|
// Is something goes wrong print error
|
||||||
|
if (rs.status.code != 1) {
|
||||||
|
Serial.println(rs.status.getResponseDescription());
|
||||||
|
} else {
|
||||||
|
Serial.println(typeStr);
|
||||||
|
if (typeStr == "TEMP") {
|
||||||
|
struct MessageTemperaturePartial {
|
||||||
|
char message[8];
|
||||||
|
byte temperature[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
ResponseStructContainer rsc = e220ttl.receiveMessage( sizeof(MessageTemperaturePartial));
|
||||||
|
struct MessageTemperaturePartial message = *(MessageTemperaturePartial*) rsc.data;
|
||||||
|
|
||||||
|
Serial.println(*(float*)(message.temperature));
|
||||||
|
Serial.println(message.message);
|
||||||
|
rsc.close();
|
||||||
|
} else if (typeStr == "HUMI") {
|
||||||
|
struct MessageHumidityPartial {
|
||||||
|
char message[8];
|
||||||
|
byte humidity;
|
||||||
|
};
|
||||||
|
|
||||||
|
ResponseStructContainer rsc = e220ttl.receiveMessage(sizeof(MessageHumidityPartial));
|
||||||
|
struct MessageHumidityPartial message = *(MessageHumidityPartial*) rsc.data;
|
||||||
|
|
||||||
|
Serial.println(message.humidity);
|
||||||
|
Serial.println(message.message);
|
||||||
|
rsc.close();
|
||||||
|
} else {
|
||||||
|
Serial.println("Something goes wrong!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Serial.available()) {
|
||||||
|
if (MESSAGE_TYPE == "HUMI") {
|
||||||
|
struct MessageHumidity message = { "HUMI", ROOM, 0 };
|
||||||
|
message.humidity = Serial.parseInt();
|
||||||
|
|
||||||
|
// Send message
|
||||||
|
ResponseStatus rs = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 23, &message, sizeof(MessageHumidity));
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
} else {
|
||||||
|
struct MessageTemperature message = { "TEMP", ROOM, 0 };
|
||||||
|
*(float*)(message.temperature) = Serial.parseFloat();
|
||||||
|
|
||||||
|
// Send message
|
||||||
|
ResponseStatus rs = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 23, &message, sizeof(MessageTemperature));
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* EBYTE LoRa E220
|
||||||
|
* Send wake up WOR message to a device in Sleep (WOR transmitter)
|
||||||
|
*
|
||||||
|
* You must configure the address with 0 3 23 (FIXED SENDER configuration)
|
||||||
|
* and pay attention that WOR period must be the same of receiver
|
||||||
|
*
|
||||||
|
* by Renzo Mischianti <https://www.mischianti.org>
|
||||||
|
*
|
||||||
|
* https://www.mischianti.org
|
||||||
|
*
|
||||||
|
* E220 ----- WeMos D1 mini ----- esp32 ----- Arduino Nano 33 IoT ----- Arduino MKR ----- Raspberry Pi Pico ----- stm32 ----- ArduinoUNO
|
||||||
|
* M0 ----- D7 (or 3.3v) ----- 19 (or 3.3v) ----- 4 (or 3.3v) ----- 2 (or 3.3v) ----- 10 (or 3.3v) ----- PB0 (or 3.3v) ----- 7 Volt div (or 3.3v)
|
||||||
|
* M1 ----- D6 (or GND) ----- 21 (or GND) ----- 6 (or GND) ----- 4 (or GND) ----- 11 (or GND) ----- PB10 (or GND) ----- 6 Volt div (or GND)
|
||||||
|
* TX ----- D3 (PullUP) ----- TX2 (PullUP) ----- TX1 (PullUP) ----- 14 (PullUP) ----- 8 (PullUP) ----- PA2 TX2 (PullUP) ----- 4 (PullUP)
|
||||||
|
* RX ----- D4 (PullUP) ----- RX2 (PullUP) ----- RX1 (PullUP) ----- 13 (PullUP) ----- 9 (PullUP) ----- PA3 RX2 (PullUP) ----- 5 Volt div (PullUP)
|
||||||
|
* AUX ----- D5 (PullUP) ----- 18 (PullUP) ----- 2 (PullUP) ----- 0 (PullUP) ----- 2 (PullUP) ----- PA0 (PullUP) ----- 3 (PullUP)
|
||||||
|
* VCC ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v
|
||||||
|
* GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// With FIXED SENDER configuration
|
||||||
|
#define DESTINATION_ADDL 3
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "LoRa_E220.h"
|
||||||
|
|
||||||
|
// ---------- esp8266 pins --------------
|
||||||
|
//LoRa_E220 e220ttl(RX, TX, AUX, M0, M1); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(D3, D4, D5, D7, D6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(D2, D3); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(D2, D3); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, D5, D7, D6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Arduino pins --------------
|
||||||
|
LoRa_E220 e220ttl(4, 5, 3, 7, 6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(4, 5); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(4, 5); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, 3, 7, 6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino Nano 33 IoT -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 2, 4, 6); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino MKR WiFi 1010 -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 0, 2, 4); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ---------- esp32 pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 15, 21, 19); // RX AUX M0 M1
|
||||||
|
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, 22, 4, 18, 21, 19, UART_BPS_RATE_9600); // esp32 RX <-- e220 TX, esp32 TX --> e220 RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Raspberry PI Pico pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 2, 10, 11); // RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------------- STM32 --------------------
|
||||||
|
//HardwareSerial Serial2(USART2); // PA3 (RX) PA2 (TX)
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, PA0, PB0, PB10); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// Startup all pins and UART
|
||||||
|
e220ttl.begin();
|
||||||
|
|
||||||
|
|
||||||
|
e220ttl.setMode(MODE_1_WOR_TRANSMITTER);
|
||||||
|
|
||||||
|
Serial.println("Hi, I'm going to send WOR message!");
|
||||||
|
|
||||||
|
// Send message
|
||||||
|
ResponseStatus rs = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 23, "Hello, world? WOR!");
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
|
||||||
|
// e220ttl.setMode(MODE_0_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// If something available
|
||||||
|
if (e220ttl.available()>1) {
|
||||||
|
// read the String message
|
||||||
|
ResponseContainer rc = e220ttl.receiveMessage();
|
||||||
|
// Is something goes wrong print error
|
||||||
|
if (rc.status.code!=1){
|
||||||
|
Serial.println(rc.status.getResponseDescription());
|
||||||
|
}else{
|
||||||
|
// Print the data received
|
||||||
|
Serial.println(rc.status.getResponseDescription());
|
||||||
|
Serial.println(rc.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Serial.available()) {
|
||||||
|
String input = Serial.readString();
|
||||||
|
ResponseStatus rs = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 23, input);
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* EBYTE LoRa E220
|
||||||
|
* Stay in sleep mode and wait a wake up WOR message
|
||||||
|
*
|
||||||
|
* You must configure the address with 0 2 23 (FIXED RECEIVER configuration)
|
||||||
|
* and pay attention that WOR period must be the same of sender
|
||||||
|
*
|
||||||
|
* You must uncommend the correct constructor and set the correct AUX_PIN define.
|
||||||
|
*
|
||||||
|
* by Renzo Mischianti <https://www.mischianti.org>
|
||||||
|
*
|
||||||
|
* https://www.mischianti.org
|
||||||
|
*
|
||||||
|
* E220 ----- WeMos D1 mini ----- esp32 ----- Arduino Nano 33 IoT ----- Arduino MKR ----- stm32 ----- ArduinoUNO
|
||||||
|
* M0 ----- D7 (or GND) ----- 19 (or GND) ----- 4 (or GND) ----- 2 (or GND) ----- PB0 (or GND) ----- 7 Volt div (or GND)
|
||||||
|
* M1 ----- D6 (or 3.3v) ----- 21 (or 3.3v) ----- 6 (or 3.3v) ----- 4 (or 3.3v) ----- PB10 (or 3.3v) ----- 6 Volt div (or 3.3v)
|
||||||
|
* TX ----- D3 (PullUP) ----- TX2 (PullUP) ----- TX1 (PullUP) ----- 14 (PullUP) ----- PA2 TX2 (PullUP) ----- 4 (PullUP)
|
||||||
|
* RX ----- D4 (PullUP) ----- RX2 (PullUP) ----- RX1 (PullUP) ----- 13 (PullUP) ----- PA3 RX2 (PullUP) ----- 5 Volt div (PullUP)
|
||||||
|
* AUX ----- D5 (PullUP) ----- 18 (PullUP) ----- 2 (PullUP) ----- 0 (PullUP) ----- PA0 (PullUP) ----- 3 (PullUP)
|
||||||
|
* VCC ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v
|
||||||
|
* GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// With FIXED RECEIVER configuration
|
||||||
|
#define DESTINATION_ADDL 2
|
||||||
|
|
||||||
|
#define AUX_PIN 15
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "LoRa_E220.h"
|
||||||
|
|
||||||
|
// ---------- esp8266 pins --------------
|
||||||
|
//LoRa_E220 e220ttl(RX, TX, AUX, M0, M1); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(D3, D4, D5, D7, D6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(D2, D3); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(D2, D3); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, D5, D7, D6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Arduino pins --------------
|
||||||
|
LoRa_E220 e220ttl(4, 5, 3, 7, 6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(4, 5); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(4, 5); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, 3, 7, 6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino Nano 33 IoT -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 2, 4, 6); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino MKR WiFi 1010 -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 0, 2, 4); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ---------- esp32 pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 15, 21, 19); // RX AUX M0 M1
|
||||||
|
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, 22, 4, 18, 21, 19, UART_BPS_RATE_9600); // esp32 RX <-- e220 TX, esp32 TX --> e220 RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------------- STM32 --------------------
|
||||||
|
//HardwareSerial Serial2(USART2); // PA3 (RX) PA2 (TX)
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, PA0, PB0, PB10); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
bool interruptExecuted = false;
|
||||||
|
#ifdef ESP32
|
||||||
|
void IRAM_ATTR wakeUp() {
|
||||||
|
// Do not use Serial on interrupt callback
|
||||||
|
interruptExecuted = true;
|
||||||
|
detachInterrupt(AUX_PIN);
|
||||||
|
}
|
||||||
|
#elif define(ESP8266)
|
||||||
|
ICACHE_RAM_ATTR void wakeUp() {
|
||||||
|
// Do not use Serial on interrupt callback
|
||||||
|
interruptExecuted = true;
|
||||||
|
detachInterrupt(AUX_PIN);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void wakeUp() {
|
||||||
|
// Do not use Serial on interrupt callback
|
||||||
|
interruptExecuted = true;
|
||||||
|
detachInterrupt(AUX_PIN);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//The setup function is called once at startup of the sketch
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
while (!Serial) {
|
||||||
|
; // wait for serial port to connect. Needed for native USB
|
||||||
|
}
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
e220ttl.begin();
|
||||||
|
|
||||||
|
e220ttl.setMode(MODE_2_WOR_RECEIVER);
|
||||||
|
|
||||||
|
delay(1000);
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("Start sleep!");
|
||||||
|
delay(100);
|
||||||
|
attachInterrupt(AUX_PIN, wakeUp, FALLING);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The loop function is called in an endless loop
|
||||||
|
void loop() {
|
||||||
|
if (e220ttl.available() > 1) {
|
||||||
|
Serial.println("Message arrived!");
|
||||||
|
ResponseContainer rs = e220ttl.receiveMessage();
|
||||||
|
// First of all get the data
|
||||||
|
String message = rs.data;
|
||||||
|
|
||||||
|
Serial.println(rs.status.getResponseDescription());
|
||||||
|
Serial.println(message);
|
||||||
|
|
||||||
|
// Work only with full connection
|
||||||
|
e220ttl.setMode(MODE_0_NORMAL);
|
||||||
|
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
ResponseStatus rsSend = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 23, "We have received the message!");
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rsSend.getResponseDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(interruptExecuted) {
|
||||||
|
Serial.println("WakeUp Callback, AUX pin go LOW and start receive message!");
|
||||||
|
Serial.flush();
|
||||||
|
interruptExecuted = false;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* EBYTE LoRa E220
|
||||||
|
*
|
||||||
|
* Receive messages on CHANNEL 23
|
||||||
|
* Uncomment #define ENABLE_RSSI true in this sketch
|
||||||
|
* if the sender send RSSI also
|
||||||
|
*
|
||||||
|
* by Renzo Mischianti <https://www.mischianti.org>
|
||||||
|
*
|
||||||
|
* https://www.mischianti.org
|
||||||
|
*
|
||||||
|
* E220 ----- WeMos D1 mini ----- esp32 ----- Arduino Nano 33 IoT ----- Arduino MKR ----- Raspberry Pi Pico ----- stm32 ----- ArduinoUNO
|
||||||
|
* M0 ----- D7 (or GND) ----- 19 (or GND) ----- 4 (or GND) ----- 2 (or GND) ----- 10 (or GND) ----- PB0 (or GND) ----- 7 Volt div (or GND)
|
||||||
|
* M1 ----- D6 (or GND) ----- 21 (or GND) ----- 6 (or GND) ----- 4 (or GND) ----- 11 (or GND) ----- PB10 (or GND) ----- 6 Volt div (or GND)
|
||||||
|
* TX ----- D3 (PullUP) ----- TX2 (PullUP) ----- TX1 (PullUP) ----- 14 (PullUP) ----- 8 (PullUP) ----- PA2 TX2 (PullUP) ----- 4 (PullUP)
|
||||||
|
* RX ----- D4 (PullUP) ----- RX2 (PullUP) ----- RX1 (PullUP) ----- 13 (PullUP) ----- 9 (PullUP) ----- PA3 RX2 (PullUP) ----- 5 Volt div (PullUP)
|
||||||
|
* AUX ----- D5 (PullUP) ----- 18 (PullUP) ----- 2 (PullUP) ----- 0 (PullUP) ----- 2 (PullUP) ----- PA0 (PullUP) ----- 3 (PullUP)
|
||||||
|
* VCC ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v
|
||||||
|
* GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// If you want use RSSI uncomment
|
||||||
|
//#define ENABLE_RSSI true
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "LoRa_E220.h"
|
||||||
|
|
||||||
|
// ---------- esp8266 pins --------------
|
||||||
|
//LoRa_E220 e220ttl(RX, TX, AUX, M0, M1); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
LoRa_E220 e220ttl(D3, D4, D5, D7, D6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(D2, D3); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(D2, D3); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, D5, D7, D6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Arduino pins --------------
|
||||||
|
//LoRa_E220 e220ttl(4, 5, 3, 7, 6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(4, 5); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(4, 5); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, 3, 7, 6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino Nano 33 IoT -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 2, 4, 6); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino MKR WiFi 1010 -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 0, 2, 4); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ---------- esp32 pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 15, 21, 19); // RX AUX M0 M1
|
||||||
|
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, 22, 4, 18, 21, 19, UART_BPS_RATE_9600); // esp32 RX <-- e220 TX, esp32 TX --> e220 RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Raspberry PI Pico pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 2, 10, 11); // RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------------- STM32 --------------------
|
||||||
|
//HardwareSerial Serial2(USART2); // PA3 (RX) PA2 (TX)
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, PA0, PB0, PB10); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// Startup all pins and UART
|
||||||
|
e220ttl.begin();
|
||||||
|
|
||||||
|
Serial.println("Start receiving!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// If something available
|
||||||
|
if (e220ttl.available()>1) {
|
||||||
|
Serial.println("Message received!");
|
||||||
|
|
||||||
|
// read the String message
|
||||||
|
#ifdef ENABLE_RSSI
|
||||||
|
ResponseContainer rc = e220ttl.receiveMessageRSSI();
|
||||||
|
#else
|
||||||
|
ResponseContainer rc = e220ttl.receiveMessage();
|
||||||
|
#endif
|
||||||
|
// Is something goes wrong print error
|
||||||
|
if (rc.status.code!=1){
|
||||||
|
Serial.println(rc.status.getResponseDescription());
|
||||||
|
}else{
|
||||||
|
// Print the data received
|
||||||
|
Serial.println(rc.status.getResponseDescription());
|
||||||
|
Serial.println(rc.data);
|
||||||
|
#ifdef ENABLE_RSSI
|
||||||
|
Serial.print("RSSI: "); Serial.println(rc.rssi, DEC);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* EBYTE LoRa E220
|
||||||
|
*
|
||||||
|
* Send a string message to all devices of the Channel CHAN 23
|
||||||
|
*
|
||||||
|
* Write a string on serial monitor or reset to send the string to all device on channel 23.
|
||||||
|
*
|
||||||
|
* Send a fixed message, you must check that the transmitter and receiver have different
|
||||||
|
* ADDL or ADDH, check the configuration down
|
||||||
|
*
|
||||||
|
* For the test you can use
|
||||||
|
* - BROADCAST MESSAGE 1
|
||||||
|
* - BROADCAST MESSAGE 2
|
||||||
|
* - BROADCAST MESSAGE 3
|
||||||
|
*
|
||||||
|
* Pai attention e220 support RSSI, if you want use that functionality you must enable RSSI on configuration
|
||||||
|
* configuration.TRANSMISSION_MODE.enableRSSI = RSSI_ENABLED;
|
||||||
|
*
|
||||||
|
* and uncomment #define ENABLE_RSSI true in this sketch
|
||||||
|
*
|
||||||
|
* by Renzo Mischianti <https://www.mischianti.org>
|
||||||
|
*
|
||||||
|
* https://www.mischianti.org
|
||||||
|
*
|
||||||
|
* E220 ----- WeMos D1 mini ----- esp32 ----- Arduino Nano 33 IoT ----- Arduino MKR ----- Raspberry Pi Pico ----- stm32 ----- ArduinoUNO
|
||||||
|
* M0 ----- D7 (or GND) ----- 19 (or GND) ----- 4 (or GND) ----- 2 (or GND) ----- 10 (or GND) ----- PB0 (or GND) ----- 7 Volt div (or GND)
|
||||||
|
* M1 ----- D6 (or GND) ----- 21 (or GND) ----- 6 (or GND) ----- 4 (or GND) ----- 11 (or GND) ----- PB10 (or GND) ----- 6 Volt div (or GND)
|
||||||
|
* TX ----- D3 (PullUP) ----- TX2 (PullUP) ----- TX1 (PullUP) ----- 14 (PullUP) ----- 8 (PullUP) ----- PA2 TX2 (PullUP) ----- 4 (PullUP)
|
||||||
|
* RX ----- D4 (PullUP) ----- RX2 (PullUP) ----- RX1 (PullUP) ----- 13 (PullUP) ----- 9 (PullUP) ----- PA3 RX2 (PullUP) ----- 5 Volt div (PullUP)
|
||||||
|
* AUX ----- D5 (PullUP) ----- 18 (PullUP) ----- 2 (PullUP) ----- 0 (PullUP) ----- 2 (PullUP) ----- PA0 (PullUP) ----- 3 (PullUP)
|
||||||
|
* VCC ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v ----- 3.3v/5v
|
||||||
|
* GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND ----- GND
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// If you want use RSSI uncomment //#define ENABLE_RSSI true
|
||||||
|
// and use relative configuration with RSSI enabled
|
||||||
|
//#define ENABLE_RSSI true
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "LoRa_E220.h"
|
||||||
|
|
||||||
|
// ---------- esp8266 pins --------------
|
||||||
|
//LoRa_E220 e220ttl(RX, TX, AUX, M0, M1); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
LoRa_E220 e220ttl(D3, D4, D5, D7, D6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(D2, D3); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(D2, D3); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, D5, D7, D6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Arduino pins --------------
|
||||||
|
//LoRa_E220 e220ttl(4, 5, 3, 7, 6); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
//LoRa_E220 e220ttl(4, 5); // Config without connect AUX and M0 M1
|
||||||
|
|
||||||
|
//#include <SoftwareSerial.h>
|
||||||
|
//SoftwareSerial mySerial(4, 5); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX
|
||||||
|
//LoRa_E220 e220ttl(&mySerial, 3, 7, 6); // AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino Nano 33 IoT -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 2, 4, 6); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ------------- Arduino MKR WiFi 1010 -------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial1, 0, 2, 4); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
// ---------- esp32 pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 15, 21, 19); // RX AUX M0 M1
|
||||||
|
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, 22, 4, 18, 21, 19, UART_BPS_RATE_9600); // esp32 RX <-- e220 TX, esp32 TX --> e220 RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------- Raspberry PI Pico pins --------------
|
||||||
|
// LoRa_E220 e220ttl(&Serial2, 2, 10, 11); // RX AUX M0 M1
|
||||||
|
// -------------------------------------
|
||||||
|
|
||||||
|
// ---------------- STM32 --------------------
|
||||||
|
//HardwareSerial Serial2(USART2); // PA3 (RX) PA2 (TX)
|
||||||
|
//LoRa_E220 e220ttl(&Serial2, PA0, PB0, PB10); // RX AUX M0 M1
|
||||||
|
// -------------------------------------------------
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(9600);
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// Startup all pins and UART
|
||||||
|
e220ttl.begin();
|
||||||
|
|
||||||
|
Serial.println("Hi, I'm going to send message!");
|
||||||
|
|
||||||
|
// Send message
|
||||||
|
ResponseStatus rs = e220ttl.sendBroadcastFixedMessage(23, "Hello, world?");
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// If something available
|
||||||
|
if (e220ttl.available()>1) {
|
||||||
|
// read the String message
|
||||||
|
#ifdef ENABLE_RSSI
|
||||||
|
ResponseContainer rc = e220ttl.receiveMessageRSSI();
|
||||||
|
#else
|
||||||
|
ResponseContainer rc = e220ttl.receiveMessage();
|
||||||
|
#endif
|
||||||
|
// Is something goes wrong print error
|
||||||
|
if (rc.status.code!=1){
|
||||||
|
Serial.println(rc.status.getResponseDescription());
|
||||||
|
}else{
|
||||||
|
// Print the data received
|
||||||
|
Serial.println(rc.status.getResponseDescription());
|
||||||
|
Serial.println(rc.data);
|
||||||
|
#ifdef ENABLE_RSSI
|
||||||
|
Serial.print("RSSI: "); Serial.println(rc.rssi, DEC);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Serial.available()) {
|
||||||
|
String input = Serial.readString();
|
||||||
|
ResponseStatus rs = e220ttl.sendBroadcastFixedMessage(23, input);
|
||||||
|
// Check If there is some problem of succesfully send
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
461
Software/lib/EByte LoRa E220 library/includes/statesNaming.h
Normal file
@@ -0,0 +1,461 @@
|
|||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
#ifdef FREQUENCY_433
|
||||||
|
#define OPERATING_FREQUENCY 410
|
||||||
|
#elif defined(FREQUENCY_400)
|
||||||
|
#define OPERATING_FREQUENCY 410
|
||||||
|
#elif defined(FREQUENCY_230)
|
||||||
|
#define OPERATING_FREQUENCY 220
|
||||||
|
#elif defined(FREQUENCY_868)
|
||||||
|
#define OPERATING_FREQUENCY 850
|
||||||
|
#elif defined(FREQUENCY_915)
|
||||||
|
#define OPERATING_FREQUENCY 850
|
||||||
|
#else
|
||||||
|
#define OPERATING_FREQUENCY 410
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BROADCAST_ADDRESS 255
|
||||||
|
|
||||||
|
typedef enum RESPONSE_STATUS {
|
||||||
|
#ifndef ARDUINO_ARCH_STM32
|
||||||
|
SUCCESS = 1,
|
||||||
|
#endif
|
||||||
|
E220_SUCCESS = 1,
|
||||||
|
ERR_E220_UNKNOWN, /* something shouldn't happened */
|
||||||
|
ERR_E220_NOT_SUPPORT,
|
||||||
|
ERR_E220_NOT_IMPLEMENT,
|
||||||
|
ERR_E220_NOT_INITIAL,
|
||||||
|
ERR_E220_INVALID_PARAM,
|
||||||
|
ERR_E220_DATA_SIZE_NOT_MATCH,
|
||||||
|
ERR_E220_BUF_TOO_SMALL,
|
||||||
|
ERR_E220_TIMEOUT,
|
||||||
|
ERR_E220_HARDWARE,
|
||||||
|
ERR_E220_HEAD_NOT_RECOGNIZED,
|
||||||
|
ERR_E220_NO_RESPONSE_FROM_DEVICE,
|
||||||
|
ERR_E220_WRONG_UART_CONFIG,
|
||||||
|
ERR_E220_WRONG_FORMAT,
|
||||||
|
ERR_E220_PACKET_TOO_BIG
|
||||||
|
} Status;
|
||||||
|
|
||||||
|
static String getResponseDescriptionByParams(byte status){
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case E220_SUCCESS:
|
||||||
|
return F("Success");
|
||||||
|
break;
|
||||||
|
case ERR_E220_UNKNOWN:
|
||||||
|
return F("Unknown");
|
||||||
|
break;
|
||||||
|
case ERR_E220_NOT_SUPPORT:
|
||||||
|
return F("Not support!");
|
||||||
|
break;
|
||||||
|
case ERR_E220_NOT_IMPLEMENT:
|
||||||
|
return F("Not implement");
|
||||||
|
break;
|
||||||
|
case ERR_E220_NOT_INITIAL:
|
||||||
|
return F("Not initial!");
|
||||||
|
break;
|
||||||
|
case ERR_E220_INVALID_PARAM:
|
||||||
|
return F("Invalid param!");
|
||||||
|
break;
|
||||||
|
case ERR_E220_DATA_SIZE_NOT_MATCH:
|
||||||
|
return F("Data size not match!");
|
||||||
|
break;
|
||||||
|
case ERR_E220_BUF_TOO_SMALL:
|
||||||
|
return F("Buff too small!");
|
||||||
|
break;
|
||||||
|
case ERR_E220_TIMEOUT:
|
||||||
|
return F("Timeout!!");
|
||||||
|
break;
|
||||||
|
case ERR_E220_HARDWARE:
|
||||||
|
return F("Hardware error!");
|
||||||
|
break;
|
||||||
|
case ERR_E220_HEAD_NOT_RECOGNIZED:
|
||||||
|
return F("Save mode returned not recognized!");
|
||||||
|
break;
|
||||||
|
case ERR_E220_NO_RESPONSE_FROM_DEVICE:
|
||||||
|
return F("No response from device! (Check wiring)");
|
||||||
|
break;
|
||||||
|
case ERR_E220_WRONG_UART_CONFIG:
|
||||||
|
return F("Wrong UART configuration! (BPS must be 9600 for configuration)");
|
||||||
|
break;
|
||||||
|
case ERR_E220_PACKET_TOO_BIG:
|
||||||
|
return F("The device support only 200byte of data transmission!");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return F("Invalid status!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UART_PARITY
|
||||||
|
{
|
||||||
|
MODE_00_8N1 = 0b00,
|
||||||
|
MODE_01_8O1 = 0b01,
|
||||||
|
MODE_10_8E1 = 0b10,
|
||||||
|
MODE_11_8N1 = 0b11
|
||||||
|
};
|
||||||
|
|
||||||
|
static String getUARTParityDescriptionByParams(byte uartParity){
|
||||||
|
switch (uartParity)
|
||||||
|
{
|
||||||
|
case MODE_00_8N1:
|
||||||
|
return F("8N1 (Default)");
|
||||||
|
break;
|
||||||
|
case MODE_01_8O1:
|
||||||
|
return F("8O1");
|
||||||
|
break;
|
||||||
|
case MODE_10_8E1:
|
||||||
|
return F("8E1");
|
||||||
|
break;
|
||||||
|
case MODE_11_8N1:
|
||||||
|
return F("8N1 (equal to 00");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return F("Invalid UART Parity!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UART_BPS_TYPE
|
||||||
|
{
|
||||||
|
UART_BPS_1200 = 0b000,
|
||||||
|
UART_BPS_2400 = 0b001,
|
||||||
|
UART_BPS_4800 = 0b010,
|
||||||
|
UART_BPS_9600 = 0b011,
|
||||||
|
UART_BPS_19200 = 0b100,
|
||||||
|
UART_BPS_38400 = 0b101,
|
||||||
|
UART_BPS_57600 = 0b110,
|
||||||
|
UART_BPS_115200 = 0b111
|
||||||
|
};
|
||||||
|
|
||||||
|
enum UART_BPS_RATE
|
||||||
|
{
|
||||||
|
UART_BPS_RATE_1200 = 1200,
|
||||||
|
UART_BPS_RATE_2400 = 2400,
|
||||||
|
UART_BPS_RATE_4800 = 4800,
|
||||||
|
UART_BPS_RATE_9600 = 9600,
|
||||||
|
UART_BPS_RATE_19200 = 19200,
|
||||||
|
UART_BPS_RATE_38400 = 38400,
|
||||||
|
UART_BPS_RATE_57600 = 57600,
|
||||||
|
UART_BPS_RATE_115200 = 115200
|
||||||
|
};
|
||||||
|
|
||||||
|
static String getUARTBaudRateDescriptionByParams(byte uartBaudRate)
|
||||||
|
{
|
||||||
|
switch (uartBaudRate)
|
||||||
|
{
|
||||||
|
case UART_BPS_1200:
|
||||||
|
return F("1200bps");
|
||||||
|
break;
|
||||||
|
case UART_BPS_2400:
|
||||||
|
return F("2400bps");
|
||||||
|
break;
|
||||||
|
case UART_BPS_4800:
|
||||||
|
return F("4800bps");
|
||||||
|
break;
|
||||||
|
case UART_BPS_9600:
|
||||||
|
return F("9600bps (default)");
|
||||||
|
break;
|
||||||
|
case UART_BPS_19200:
|
||||||
|
return F("19200bps");
|
||||||
|
break;
|
||||||
|
case UART_BPS_38400:
|
||||||
|
return F("38400bps");
|
||||||
|
break;
|
||||||
|
case UART_BPS_57600:
|
||||||
|
return F("57600bps");
|
||||||
|
break;
|
||||||
|
case UART_BPS_115200:
|
||||||
|
return F("115200bps");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return F("Invalid UART Baud Rate!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AIR_DATA_RATE
|
||||||
|
{
|
||||||
|
AIR_DATA_RATE_000_24 = 0b000,
|
||||||
|
AIR_DATA_RATE_001_24 = 0b001,
|
||||||
|
AIR_DATA_RATE_010_24 = 0b010,
|
||||||
|
AIR_DATA_RATE_011_48 = 0b011,
|
||||||
|
AIR_DATA_RATE_100_96 = 0b100,
|
||||||
|
AIR_DATA_RATE_101_192 = 0b101,
|
||||||
|
AIR_DATA_RATE_110_384 = 0b110,
|
||||||
|
AIR_DATA_RATE_111_625 = 0b111
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static String getAirDataRateDescriptionByParams(byte airDataRate)
|
||||||
|
{
|
||||||
|
switch (airDataRate)
|
||||||
|
{
|
||||||
|
case AIR_DATA_RATE_000_24:
|
||||||
|
return F("2.4kbps");
|
||||||
|
break;
|
||||||
|
case AIR_DATA_RATE_001_24:
|
||||||
|
return F("2.4kbps");
|
||||||
|
break;
|
||||||
|
case AIR_DATA_RATE_010_24:
|
||||||
|
return F("2.4kbps (default)");
|
||||||
|
break;
|
||||||
|
case AIR_DATA_RATE_011_48:
|
||||||
|
return F("4.8kbps");
|
||||||
|
break;
|
||||||
|
case AIR_DATA_RATE_100_96:
|
||||||
|
return F("9.6kbps");
|
||||||
|
break;
|
||||||
|
case AIR_DATA_RATE_101_192:
|
||||||
|
return F("19.2kbps");
|
||||||
|
break;
|
||||||
|
case AIR_DATA_RATE_110_384:
|
||||||
|
return F("38.4kbps");
|
||||||
|
break;
|
||||||
|
case AIR_DATA_RATE_111_625:
|
||||||
|
return F("62.5kbps");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return F("Invalid Air Data Rate!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SUB_PACKET_SETTING {
|
||||||
|
SPS_200_00 = 0b00,
|
||||||
|
SPS_128_01 = 0b01,
|
||||||
|
SPS_064_10 = 0b10,
|
||||||
|
SPS_032_11 = 0b11
|
||||||
|
|
||||||
|
};
|
||||||
|
static String getSubPacketSettingByParams(byte subPacketSetting)
|
||||||
|
{
|
||||||
|
switch (subPacketSetting)
|
||||||
|
{
|
||||||
|
case SPS_200_00:
|
||||||
|
return F("200bytes (default)");
|
||||||
|
break;
|
||||||
|
case SPS_128_01:
|
||||||
|
return F("128bytes");
|
||||||
|
break;
|
||||||
|
case SPS_064_10:
|
||||||
|
return F("64bytes");
|
||||||
|
break;
|
||||||
|
case SPS_032_11:
|
||||||
|
return F("32bytes");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return F("Invalid Sub Packet Setting!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RSSI_AMBIENT_NOISE_ENABLE {
|
||||||
|
RSSI_AMBIENT_NOISE_ENABLED = 0b1,
|
||||||
|
RSSI_AMBIENT_NOISE_DISABLED = 0b0
|
||||||
|
};
|
||||||
|
static String getRSSIAmbientNoiseEnableByParams(byte rssiAmbientNoiseEnabled)
|
||||||
|
{
|
||||||
|
switch (rssiAmbientNoiseEnabled)
|
||||||
|
{
|
||||||
|
case RSSI_AMBIENT_NOISE_ENABLED:
|
||||||
|
return F("Enabled");
|
||||||
|
break;
|
||||||
|
case RSSI_AMBIENT_NOISE_DISABLED:
|
||||||
|
return F("Disabled (default)");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return F("Invalid RSSI Ambient Noise enabled!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum WOR_PERIOD {
|
||||||
|
WOR_500_000 = 0b000,
|
||||||
|
WOR_1000_001 = 0b001,
|
||||||
|
WOR_1500_010 = 0b010,
|
||||||
|
WOR_2000_011 = 0b011,
|
||||||
|
WOR_2500_100 = 0b100,
|
||||||
|
WOR_3000_101 = 0b101,
|
||||||
|
WOR_3500_110 = 0b110,
|
||||||
|
WOR_4000_111 = 0b111
|
||||||
|
|
||||||
|
};
|
||||||
|
static String getWORPeriodByParams(byte WORPeriod)
|
||||||
|
{
|
||||||
|
switch (WORPeriod)
|
||||||
|
{
|
||||||
|
case WOR_500_000:
|
||||||
|
return F("500ms");
|
||||||
|
break;
|
||||||
|
case WOR_1000_001:
|
||||||
|
return F("1000ms");
|
||||||
|
break;
|
||||||
|
case WOR_1500_010:
|
||||||
|
return F("1500ms");
|
||||||
|
break;
|
||||||
|
case WOR_2000_011:
|
||||||
|
return F("2000ms (default)");
|
||||||
|
break;
|
||||||
|
case WOR_2500_100:
|
||||||
|
return F("2500ms");
|
||||||
|
break;
|
||||||
|
case WOR_3000_101:
|
||||||
|
return F("3000ms");
|
||||||
|
break;
|
||||||
|
case WOR_3500_110:
|
||||||
|
return F("3500ms");
|
||||||
|
break;
|
||||||
|
case WOR_4000_111:
|
||||||
|
return F("4000ms");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return F("Invalid WOR period!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enum LBT_ENABLE_BYTE {
|
||||||
|
LBT_ENABLED = 0b1,
|
||||||
|
LBT_DISABLED = 0b0
|
||||||
|
};
|
||||||
|
static String getLBTEnableByteByParams(byte LBTEnableByte)
|
||||||
|
{
|
||||||
|
switch (LBTEnableByte)
|
||||||
|
{
|
||||||
|
case LBT_ENABLED:
|
||||||
|
return F("Enabled");
|
||||||
|
break;
|
||||||
|
case LBT_DISABLED:
|
||||||
|
return F("Disabled (default)");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return F("Invalid LBT enable byte!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum RSSI_ENABLE_BYTE {
|
||||||
|
RSSI_ENABLED = 0b1,
|
||||||
|
RSSI_DISABLED = 0b0
|
||||||
|
};
|
||||||
|
static String getRSSIEnableByteByParams(byte RSSIEnableByte)
|
||||||
|
{
|
||||||
|
switch (RSSIEnableByte)
|
||||||
|
{
|
||||||
|
case RSSI_ENABLED:
|
||||||
|
return F("Enabled");
|
||||||
|
break;
|
||||||
|
case RSSI_DISABLED:
|
||||||
|
return F("Disabled (default)");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return F("Invalid RSSI enable byte!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FIDEX_TRANSMISSION
|
||||||
|
{
|
||||||
|
FT_TRANSPARENT_TRANSMISSION = 0b0,
|
||||||
|
FT_FIXED_TRANSMISSION = 0b1
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static String getFixedTransmissionDescriptionByParams(byte fixedTransmission)
|
||||||
|
{
|
||||||
|
switch (fixedTransmission)
|
||||||
|
{
|
||||||
|
case FT_TRANSPARENT_TRANSMISSION:
|
||||||
|
return F("Transparent transmission (default)");
|
||||||
|
break;
|
||||||
|
case FT_FIXED_TRANSMISSION:
|
||||||
|
return F("Fixed transmission (first three bytes can be used as high/low address and channel)");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return F("Invalid fixed transmission param!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef E220_22
|
||||||
|
enum TRANSMISSION_POWER
|
||||||
|
{
|
||||||
|
POWER_22 = 0b00,
|
||||||
|
POWER_17 = 0b01,
|
||||||
|
POWER_13 = 0b10,
|
||||||
|
POWER_10 = 0b11
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static String getTransmissionPowerDescriptionByParams(byte transmissionPower)
|
||||||
|
{
|
||||||
|
switch (transmissionPower)
|
||||||
|
{
|
||||||
|
case POWER_22:
|
||||||
|
return F("22dBm (Default)");
|
||||||
|
break;
|
||||||
|
case POWER_17:
|
||||||
|
return F("17dBm");
|
||||||
|
break;
|
||||||
|
case POWER_13:
|
||||||
|
return F("13dBm");
|
||||||
|
break;
|
||||||
|
case POWER_10:
|
||||||
|
return F("10dBm");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return F("Invalid transmission power param");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif defined(E220_30)
|
||||||
|
enum TRANSMISSION_POWER
|
||||||
|
{
|
||||||
|
POWER_30 = 0b00,
|
||||||
|
POWER_27 = 0b01,
|
||||||
|
POWER_24 = 0b10,
|
||||||
|
POWER_21 = 0b11
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static String getTransmissionPowerDescriptionByParams(byte transmissionPower)
|
||||||
|
{
|
||||||
|
switch (transmissionPower)
|
||||||
|
{
|
||||||
|
case POWER_30:
|
||||||
|
return F("30dBm (Default)");
|
||||||
|
break;
|
||||||
|
case POWER_27:
|
||||||
|
return F("27dBm");
|
||||||
|
break;
|
||||||
|
case POWER_24:
|
||||||
|
return F("24dBm");
|
||||||
|
break;
|
||||||
|
case POWER_21:
|
||||||
|
return F("21dBm");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return F("Invalid transmission power param");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
enum TRANSMISSION_POWER
|
||||||
|
{
|
||||||
|
POWER_22 = 0b00,
|
||||||
|
POWER_17 = 0b01,
|
||||||
|
POWER_13 = 0b10,
|
||||||
|
POWER_10 = 0b11
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static String getTransmissionPowerDescriptionByParams(byte transmissionPower)
|
||||||
|
{
|
||||||
|
switch (transmissionPower)
|
||||||
|
{
|
||||||
|
case POWER_22:
|
||||||
|
return F("22dBm (Default)");
|
||||||
|
break;
|
||||||
|
case POWER_17:
|
||||||
|
return F("17dBm");
|
||||||
|
break;
|
||||||
|
case POWER_13:
|
||||||
|
return F("13dBm");
|
||||||
|
break;
|
||||||
|
case POWER_10:
|
||||||
|
return F("10dBm");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return F("Invalid transmission power param");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
30
Software/lib/EByte LoRa E220 library/keywords.txt
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
###########################################
|
||||||
|
# Syntax Coloring Map For LoRa_E32_Series-library
|
||||||
|
###########################################
|
||||||
|
|
||||||
|
###########################################
|
||||||
|
# Datatypes (KEYWORD1)
|
||||||
|
###########################################
|
||||||
|
|
||||||
|
LoRa_E220 KEYWORD1
|
||||||
|
|
||||||
|
###########################################
|
||||||
|
# Methods and Functions (KEYWORD2)
|
||||||
|
###########################################
|
||||||
|
|
||||||
|
begin KEYWORD2
|
||||||
|
|
||||||
|
getConfiguration KEYWORD2
|
||||||
|
setConfiguration KEYWORD2
|
||||||
|
|
||||||
|
getModuleInformation KEYWORD2
|
||||||
|
printParameters KEYWORD2
|
||||||
|
resetModule KEYWORD2
|
||||||
|
|
||||||
|
sendMessage KEYWORD2
|
||||||
|
receiveMessage KEYWORD2
|
||||||
|
|
||||||
|
sendFixedMessage KEYWORD2
|
||||||
|
sendBroadcastFixedMessage KEYWORD2
|
||||||
|
|
||||||
|
receiveInitialMessage KEYWORD2
|
11
Software/lib/EByte LoRa E220 library/library.properties
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
name=EByte LoRa E220 library
|
||||||
|
version=1.0.6
|
||||||
|
author=Renzo Mischianti <renzo.mischianti@gmail.com>
|
||||||
|
maintainer=Renzo Mischianti <renzo.mischianti@gmail.com>
|
||||||
|
sentence=LoRa EBYTE E220 device library complete and tested with Arduino, esp8266, esp32, STM32 and Raspberry Pi Pico. LLCC68
|
||||||
|
paragraph=Ebyte E220 LoRa (Long Range) library device very cheap and very long range (from 5Km to 10Km). Arduino LoRa EBYTE E220 device library complete and tested with Arduino, esp8266, esp32, STM32 and Raspberry Pi Pico. LLCC68
|
||||||
|
category=Communication
|
||||||
|
url=https://www.mischianti.org/category/my-libraries/ebyte-lora-e22-devices/
|
||||||
|
repository=https://github.com/xreef/EByte_LoRa_E220_Series_Library
|
||||||
|
architectures=*
|
||||||
|
includes=LoRa_E220.h
|
@@ -13,49 +13,50 @@ extra_configs =
|
|||||||
wifi_credentials.ini
|
wifi_credentials.ini
|
||||||
|
|
||||||
[env:de-timer]
|
[env:de-timer]
|
||||||
platform = espressif32
|
platform = espressif8266
|
||||||
board = ttgo-lora32-v1
|
framework = arduino
|
||||||
board_build.filesystem = littlefs
|
board = d1_mini
|
||||||
;board_build.f_flash = 80000000L
|
|
||||||
;board_build.ldscript = eagle.flash.4m1m.ld
|
|
||||||
|
|
||||||
monitor_filters = esp32_exception_decoder
|
|
||||||
monitor_speed = 115200
|
|
||||||
|
|
||||||
upload_protocol = esptool
|
upload_protocol = esptool
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
;upload_port = 10.0.1.48
|
;upload_port = 10.0.1.48
|
||||||
;upload_protocol = espota
|
;upload_flags =
|
||||||
;upload_flags =
|
; --port=8266
|
||||||
; --auth=${wifi_cred.admin_password}
|
; --auth=${wifi_cred.admin_password}
|
||||||
|
|
||||||
build_type = debug
|
|
||||||
|
|
||||||
build_flags=
|
build_flags=
|
||||||
!python git_rev_macro.py
|
-DATOMIC_FS_UPDATE
|
||||||
-DSERIAL_DEBUG
|
-DFEATURE_ENABLE_WIFI_CLIENT
|
||||||
;-DWIFI_CLIENT
|
;-DFEATURE_ENABLE_LORA
|
||||||
;-DCAPTIVE
|
-DFEATURE_ENABLE_UARTLORA
|
||||||
-DWIFI_AP_IP_GW=10,0,1,1
|
-DWIFI_AP_IP_GW=10,0,0,1
|
||||||
|
-DADMIN_PASSWORD=${wifi_cred.admin_password}
|
||||||
|
-DWIFI_SSID_CLIENT=${wifi_cred.wifi_ssid_client}
|
||||||
|
-DWIFI_PASSWORD_CLIENT=${wifi_cred.wifi_password_client}
|
||||||
-DADMIN_PASSWORD=${wifi_cred.admin_password}
|
-DADMIN_PASSWORD=${wifi_cred.admin_password}
|
||||||
-DWIFI_SSID=${wifi_cred.wifi_ssid}
|
|
||||||
-DWIFI_PASSWORD=${wifi_cred.wifi_password}
|
|
||||||
-DWIFI_AP_PASSWORD=${wifi_cred.wifi_ap_password}
|
-DWIFI_AP_PASSWORD=${wifi_cred.wifi_ap_password}
|
||||||
-DDEVICE_NAME='"Dark Emergency Timer"'
|
-DDEVICE_NAME='"Dark Emergency Timer"'
|
||||||
-DFACTION_1_NAME='"GOF"'
|
|
||||||
-DFACTION_2_NAME='"MILIZ"'
|
|
||||||
-DFACTION_3_NAME='"KGG"'
|
|
||||||
|
|
||||||
framework = arduino
|
;build_type = debug
|
||||||
lib_deps =
|
|
||||||
smougenot/TM1637@0.0.0-alpha+sha.9486982048
|
board_build.filesystem = littlefs
|
||||||
;me-no-dev/ESP Async WebServer @ ^1.2.3 ; local version included due to bug
|
board_build.ldscript = eagle.flash.4m1m.ld
|
||||||
me-no-dev/AsyncTCP @ ^1.1.1
|
extra_scripts =
|
||||||
sstaub/Ticker @ ^4.2.0
|
post:codegen/prepare_littlefs.py
|
||||||
adafruit/Adafruit INA219 @ ^1.1.1
|
pre:codegen/run_pre.py
|
||||||
robtillaart/I2C_EEPROM @ ^1.5.2
|
|
||||||
sandeepmistry/LoRa @ ^0.8.0
|
monitor_filters = esp8266_exception_decoder
|
||||||
adafruit/Adafruit SSD1306 @ ^2.4.0
|
monitor_speed = 115200
|
||||||
adafruit/Adafruit GFX Library @ ^1.10.1
|
|
||||||
adafruit/Adafruit BusIO @ ^1.5.0
|
lib_ldf_mode = deep
|
||||||
bblanchon/ArduinoJson @ ^6.19.4
|
lib_deps =
|
||||||
|
;xreef/EByte LoRa E220 library@^1.0.6 ; made Lib local, due to changes for I2C-controller M0,M1-Pins
|
||||||
|
sstaub/Ticker@^4.4.0
|
||||||
|
robtillaart/PCF8574 @ ^0.3.7
|
||||||
|
adafruit/Adafruit INA219 @ ^1.1.1
|
||||||
|
akj7/TM1637 Driver @ ^2.1.2
|
||||||
|
sstaub/Ticker @ ^4.4.0
|
||||||
|
robtillaart/I2C_EEPROM @ ^1.8.2
|
||||||
|
esphome/ESPAsyncWebServer-esphome @ ^3.2.2
|
||||||
|
sandeepmistry/LoRa @ ^0.8.0
|
||||||
|
bblanchon/ArduinoJson @ ^7.0.4
|
8
Software/src/common.cpp
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
const char *BatteryString[] = {
|
||||||
|
"Undefined",
|
||||||
|
"LiPo 2S",
|
||||||
|
"LiPo 3S"};
|
||||||
|
|
||||||
|
const size_t BatteryString_Elements = sizeof(BatteryString) / sizeof(BatteryString[0]);
|
@@ -1,41 +0,0 @@
|
|||||||
#ifndef _COMMON_H_
|
|
||||||
#define _COMMON_H_
|
|
||||||
|
|
||||||
#define Q(x) #x
|
|
||||||
#define QUOTE(x) Q(x)
|
|
||||||
|
|
||||||
// Module connection pins (ESP GPIO-Nums)
|
|
||||||
#define CLK 12
|
|
||||||
#define DIO_FAC_1_7SEG 13
|
|
||||||
#define DIO_FAC_2_7SEG 17
|
|
||||||
#define DIO_FAC_3_7SEG 21
|
|
||||||
|
|
||||||
#define DIO_FAC_1_TRG 36
|
|
||||||
#define FAC_1_TRG_PRESSED LOW
|
|
||||||
#define DIO_FAC_2_TRG 37
|
|
||||||
#define FAC_2_TRG_PRESSED LOW
|
|
||||||
#define DIO_FAC_3_TRG 38
|
|
||||||
#define FAC_3_TRG_PRESSED LOW
|
|
||||||
|
|
||||||
#ifndef HOST_NAME
|
|
||||||
#define HOST_NAME "DE_Timer_%06X" // Use printf-Formatting - Chip-ID (uin32_t) will be added
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef OTA_DELAY
|
|
||||||
#define OTA_DELAY 50 // ticks -> 10ms / tick
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ADMIN_PASSWORD
|
|
||||||
#error "You need to define ADMIN_PASSWORD for OTA-Update"
|
|
||||||
#endif
|
|
||||||
#ifndef WIFI_PASSWORD
|
|
||||||
#error "You must define an WIFI_PASSWORD for OTA-Update"
|
|
||||||
#endif
|
|
||||||
#ifndef WIFI_SSID
|
|
||||||
#error "You must define an WIFI_SSID for OTA-Update"
|
|
||||||
#endif
|
|
||||||
#ifndef WIFI_AP_PASSWORD
|
|
||||||
#error "You must define an WIFI_AP_PASSWORD for Standalone AP-Mode"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,261 +0,0 @@
|
|||||||
#include "config.h"
|
|
||||||
|
|
||||||
I2C_eeprom ee(0x50, EEPROM_SIZE_BYTES);
|
|
||||||
|
|
||||||
configData_t ConfigData;
|
|
||||||
persistenceData_t PersistenceData;
|
|
||||||
const uint16_t eeVersion = 1; // inc
|
|
||||||
boolean eeAvailable = false;
|
|
||||||
|
|
||||||
const uint16_t persistencemarker_Adress = 0; // sizeof 4
|
|
||||||
const uint16_t startofConfig_Adress = 16;
|
|
||||||
const uint16_t startofPersistence_Adress = startofConfig_Adress + sizeof(ConfigData) + (sizeof(ConfigData) % 16);
|
|
||||||
|
|
||||||
boolean checkEEPROMavailable();
|
|
||||||
|
|
||||||
void InitEEPROM()
|
|
||||||
{
|
|
||||||
ee.begin();
|
|
||||||
if (!checkEEPROMavailable())
|
|
||||||
{
|
|
||||||
globals.systemStatus = sysStat_Error;
|
|
||||||
MaintainDTC(DTC_NO_EEPROM_FOUND, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GetConfig_EEPROM();
|
|
||||||
|
|
||||||
if (ConfigData.EEPROM_Version != eeVersion)
|
|
||||||
{
|
|
||||||
FormatConfig_EEPROM();
|
|
||||||
globals.systemStatus = sysStat_Error;
|
|
||||||
MaintainDTC(DTC_EEPROM_VERSION_BAD, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getPersistanceAddress() > ee.getDeviceSize())
|
|
||||||
{
|
|
||||||
FormatPersistence_EEPROM();
|
|
||||||
globals.systemStatus = sysStat_Error;
|
|
||||||
MaintainDTC(DTC_EEPROM_PDS_MARKER_INVALID, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GetPersistence_EEPROM();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EEPROM_Process()
|
|
||||||
{
|
|
||||||
|
|
||||||
switch (globals.requestEEAction)
|
|
||||||
{
|
|
||||||
case EE_CFG_SAVE:
|
|
||||||
StoreConfig_EEPROM();
|
|
||||||
globals.requestEEAction = EE_IDLE;
|
|
||||||
break;
|
|
||||||
case EE_CFG_LOAD:
|
|
||||||
GetConfig_EEPROM();
|
|
||||||
globals.requestEEAction = EE_IDLE;
|
|
||||||
break;
|
|
||||||
case EE_PDS_SAVE:
|
|
||||||
StorePersistence_EEPROM();
|
|
||||||
globals.requestEEAction = EE_IDLE;
|
|
||||||
break;
|
|
||||||
case EE_PDS_LOAD:
|
|
||||||
GetPersistence_EEPROM();
|
|
||||||
globals.requestEEAction = EE_IDLE;
|
|
||||||
break;
|
|
||||||
case EE_IDLE:
|
|
||||||
default:
|
|
||||||
globals.requestEEAction = EE_IDLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void StoreConfig_EEPROM()
|
|
||||||
{
|
|
||||||
ConfigData.checksum = 0;
|
|
||||||
ConfigData.checksum = Checksum_EEPROM((uint8_t *)&ConfigData, sizeof(ConfigData));
|
|
||||||
if (!checkEEPROMavailable())
|
|
||||||
return;
|
|
||||||
|
|
||||||
ee.updateBlock(startofConfig_Adress, (uint8_t *)&ConfigData, sizeof(ConfigData));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetConfig_EEPROM()
|
|
||||||
{
|
|
||||||
if (!checkEEPROMavailable())
|
|
||||||
return;
|
|
||||||
|
|
||||||
ee.readBlock(startofConfig_Adress, (uint8_t *)&ConfigData, sizeof(ConfigData));
|
|
||||||
|
|
||||||
uint32_t checksum = ConfigData.checksum;
|
|
||||||
ConfigData.checksum = 0;
|
|
||||||
|
|
||||||
if (Checksum_EEPROM((uint8_t *)&ConfigData, sizeof(ConfigData)) != checksum)
|
|
||||||
{
|
|
||||||
MaintainDTC(DTC_EEPROM_CFG_BAD, true);
|
|
||||||
FormatConfig_EEPROM();
|
|
||||||
}
|
|
||||||
ConfigData.checksum = checksum;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getPersistanceAddress()
|
|
||||||
{
|
|
||||||
uint32_t eePersistenceMarker;
|
|
||||||
ee.readBlock(persistencemarker_Adress, (uint8_t *)&eePersistenceMarker, sizeof(eePersistenceMarker));
|
|
||||||
return eePersistenceMarker;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updatePersistanceAddress(uint32_t adress)
|
|
||||||
{
|
|
||||||
ee.updateBlock(persistencemarker_Adress, (uint8_t *)&adress, sizeof(adress));
|
|
||||||
}
|
|
||||||
|
|
||||||
void StorePersistence_EEPROM()
|
|
||||||
{
|
|
||||||
if (PersistenceData.writeCycleCounter >= EEPROM_ENDURANCE)
|
|
||||||
MovePersistencePage_EEPROM(false);
|
|
||||||
else
|
|
||||||
PersistenceData.writeCycleCounter++;
|
|
||||||
|
|
||||||
PersistenceData.checksum = 0;
|
|
||||||
PersistenceData.checksum = Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData));
|
|
||||||
|
|
||||||
if (!checkEEPROMavailable())
|
|
||||||
return;
|
|
||||||
|
|
||||||
ee.updateBlock(getPersistanceAddress(), (uint8_t *)&PersistenceData, sizeof(PersistenceData));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetPersistence_EEPROM()
|
|
||||||
{
|
|
||||||
if (!checkEEPROMavailable())
|
|
||||||
return;
|
|
||||||
|
|
||||||
ee.readBlock(getPersistanceAddress(), (uint8_t *)&PersistenceData, sizeof(PersistenceData));
|
|
||||||
|
|
||||||
uint32_t checksum = PersistenceData.checksum;
|
|
||||||
PersistenceData.checksum = 0;
|
|
||||||
|
|
||||||
if (Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) != checksum)
|
|
||||||
{
|
|
||||||
MaintainDTC(DTC_EEPROM_PDS_BAD, true);
|
|
||||||
FormatPersistence_EEPROM();
|
|
||||||
}
|
|
||||||
PersistenceData.checksum = checksum;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FormatConfig_EEPROM()
|
|
||||||
{
|
|
||||||
configData_t defaults;
|
|
||||||
ConfigData = defaults;
|
|
||||||
ConfigData.EEPROM_Version = eeVersion;
|
|
||||||
StoreConfig_EEPROM();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FormatPersistence_EEPROM()
|
|
||||||
{
|
|
||||||
persistenceData_t defaults;
|
|
||||||
PersistenceData = defaults;
|
|
||||||
updatePersistanceAddress(startofPersistence_Adress);
|
|
||||||
StorePersistence_EEPROM();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MovePersistencePage_EEPROM(boolean reset)
|
|
||||||
{
|
|
||||||
if (!checkEEPROMavailable())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (reset)
|
|
||||||
{
|
|
||||||
updatePersistanceAddress(startofPersistence_Adress);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t newPersistenceMarker = getPersistanceAddress() + sizeof(PersistenceData);
|
|
||||||
|
|
||||||
// check if we reached the End of the EEPROM and Startover at the beginning
|
|
||||||
if ((newPersistenceMarker + sizeof(PersistenceData)) > ee.getDeviceSize())
|
|
||||||
{
|
|
||||||
MaintainDTC(DTC_EEPROM_WORNOUT, true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
updatePersistanceAddress(newPersistenceMarker);
|
|
||||||
PersistenceData.writeCycleCounter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t GetEESize()
|
|
||||||
{
|
|
||||||
return ee.getDeviceSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t Checksum_EEPROM(uint8_t const *data, size_t len)
|
|
||||||
{
|
|
||||||
if (data == NULL)
|
|
||||||
return 0;
|
|
||||||
uint32_t crc, mask;
|
|
||||||
crc = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
while (len--)
|
|
||||||
{
|
|
||||||
crc ^= *data++;
|
|
||||||
for (uint8_t k = 0; k < 8; k++)
|
|
||||||
{
|
|
||||||
mask = -(crc & 1);
|
|
||||||
crc = (crc >> 1) ^ (0xEDB88320 & mask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ~crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dumpEEPROM(uint16_t memoryAddress, uint16_t length)
|
|
||||||
{
|
|
||||||
#define BLOCK_TO_LENGTH 16
|
|
||||||
|
|
||||||
if (length > ee.getDeviceSize())
|
|
||||||
length = ee.getDeviceSize();
|
|
||||||
|
|
||||||
if (memoryAddress + length > ee.getDeviceSize())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!checkEEPROMavailable())
|
|
||||||
return;
|
|
||||||
|
|
||||||
char ascii_buf[BLOCK_TO_LENGTH + 1];
|
|
||||||
sprintf(ascii_buf, "%*s", BLOCK_TO_LENGTH, "ASCII");
|
|
||||||
Serial.print(PSTR("\nAddress "));
|
|
||||||
for (int x = 0; x < BLOCK_TO_LENGTH; x++)
|
|
||||||
Serial.printf("%3d", x);
|
|
||||||
|
|
||||||
memoryAddress = memoryAddress / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
|
|
||||||
length = (length + BLOCK_TO_LENGTH - 1) / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
int blockpoint = memoryAddress % BLOCK_TO_LENGTH;
|
|
||||||
if (blockpoint == 0)
|
|
||||||
{
|
|
||||||
ascii_buf[BLOCK_TO_LENGTH] = 0;
|
|
||||||
Serial.printf(" %s", ascii_buf);
|
|
||||||
Serial.printf("\n0x%05X:", memoryAddress);
|
|
||||||
}
|
|
||||||
ascii_buf[blockpoint] = ee.readByte(memoryAddress);
|
|
||||||
Serial.printf(" %02X", ascii_buf[blockpoint]);
|
|
||||||
if (ascii_buf[blockpoint] < 0x20 || ascii_buf[blockpoint] > 0x7E)
|
|
||||||
ascii_buf[blockpoint] = '.';
|
|
||||||
memoryAddress++;
|
|
||||||
}
|
|
||||||
Serial.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean checkEEPROMavailable()
|
|
||||||
{
|
|
||||||
if (!ee.isConnected())
|
|
||||||
{
|
|
||||||
MaintainDTC(DTC_NO_EEPROM_FOUND, true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
@@ -1,69 +0,0 @@
|
|||||||
#ifndef _CONFIG_H_
|
|
||||||
#define _CONFIG_H_
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <Wire.h>
|
|
||||||
#include <I2C_eeprom.h>
|
|
||||||
|
|
||||||
#include "globals.h"
|
|
||||||
#include "dtc.h"
|
|
||||||
|
|
||||||
#define EEPROM_SIZE_BYTES I2C_DEVICESIZE_24LC01
|
|
||||||
#define EEPROM_ENDURANCE 1000000
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
NONE,
|
|
||||||
FACTION_1,
|
|
||||||
FACTION_2,
|
|
||||||
FACTION_3
|
|
||||||
} factions_t;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t writeCycleCounter = 0;
|
|
||||||
uint32_t faction_1_timer = 0;
|
|
||||||
uint32_t faction_2_timer = 0;
|
|
||||||
uint32_t faction_3_timer = 0;
|
|
||||||
factions_t activeFaction = NONE;
|
|
||||||
uint32_t checksum = 0;
|
|
||||||
} persistenceData_t;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
BATTERY_UNDEFINED,
|
|
||||||
BATTERY_LIPO_2S,
|
|
||||||
BATTERY_LIPO_3S
|
|
||||||
} batteryType_t;
|
|
||||||
|
|
||||||
const char BatteryString[][10]{
|
|
||||||
"Undefined",
|
|
||||||
"LiPo 2S",
|
|
||||||
"LiPo 3S"
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint8_t EEPROM_Version = 1;
|
|
||||||
batteryType_t batteryType = BATTERY_UNDEFINED;
|
|
||||||
uint32_t checksum = 0;
|
|
||||||
} configData_t;
|
|
||||||
|
|
||||||
void InitEEPROM();
|
|
||||||
void EEPROM_Process();
|
|
||||||
void StoreConfig_EEPROM();
|
|
||||||
void GetConfig_EEPROM();
|
|
||||||
void StorePersistence_EEPROM();
|
|
||||||
void GetPersistence_EEPROM();
|
|
||||||
void FormatConfig_EEPROM();
|
|
||||||
void FormatPersistence_EEPROM();
|
|
||||||
uint32_t Checksum_EEPROM(uint8_t const *data, size_t len);
|
|
||||||
void dumpEEPROM(uint16_t memoryAddress, uint16_t length);
|
|
||||||
void MovePersistencePage_EEPROM(boolean reset);
|
|
||||||
uint32_t getPersistanceAddress();
|
|
||||||
void updatePersistanceAddress(uint32_t adress);
|
|
||||||
uint32_t GetEESize();
|
|
||||||
|
|
||||||
extern configData_t ConfigData;
|
|
||||||
extern persistenceData_t PersistenceData;
|
|
||||||
#endif // _CONFIG_H_
|
|
494
Software/src/debugger.cpp
Normal file
@@ -0,0 +1,494 @@
|
|||||||
|
/**
|
||||||
|
* @file debugger.cpp
|
||||||
|
* @brief Implementation of debugging functions for monitoring and diagnostics.
|
||||||
|
*
|
||||||
|
* This file contains the implementation of various debugging functions to monitor
|
||||||
|
* and diagnose the system. It includes functions to print system information, WiFi
|
||||||
|
* details, EEPROM status, dump configuration settings, dump persistence data, show
|
||||||
|
* Diagnostic Trouble Codes (DTCs), and more.
|
||||||
|
*
|
||||||
|
* @author Marcel Peterkau
|
||||||
|
* @date 09.04.2024
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "debugger.h"
|
||||||
|
|
||||||
|
DebugStatus_t DebuggerStatus[dbg_cntElements];
|
||||||
|
|
||||||
|
void processCmdDebug(String command);
|
||||||
|
void Debug_formatCFG();
|
||||||
|
void Debug_formatPersistence();
|
||||||
|
void Debug_printSystemInfo();
|
||||||
|
void Debug_printWifiInfo();
|
||||||
|
void Debug_CheckEEPOM(bool autocorrect);
|
||||||
|
void Debug_dumpConfig();
|
||||||
|
void Debug_dumpPersistance();
|
||||||
|
void Debug_ShowDTCs();
|
||||||
|
void Debug_dumpGlobals();
|
||||||
|
void Debug_printHelp();
|
||||||
|
const char *uint32_to_binary_string(uint32_t num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the debugger by setting the initial status for different debug ports.
|
||||||
|
* Serial debug output is turned off.
|
||||||
|
*/
|
||||||
|
void initDebugger()
|
||||||
|
{
|
||||||
|
// Set the initial status of debug ports
|
||||||
|
DebuggerStatus[dbg_Serial] = disabled;
|
||||||
|
DebuggerStatus[dbg_Webui] = disabled;
|
||||||
|
|
||||||
|
// Disable serial debug output
|
||||||
|
Serial.setDebugOutput(false);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Processes incoming debug commands from the Serial interface.
|
||||||
|
* It reads characters from Serial and interprets them as commands.
|
||||||
|
* The recognized commands are processed accordingly.
|
||||||
|
*/
|
||||||
|
void Debug_Process()
|
||||||
|
{
|
||||||
|
// Enumeration for tracking the state of input processing
|
||||||
|
typedef enum InputProcessed_e
|
||||||
|
{
|
||||||
|
IDLE, ///< No command processing is in progress
|
||||||
|
CMD_COMPLETE, ///< Received a complete command
|
||||||
|
CMD_ABORT, ///< Received an abort command (Esc)
|
||||||
|
CMD_OVERFLOW ///< Input buffer overflow occurred
|
||||||
|
} InputProcessed_t;
|
||||||
|
|
||||||
|
static unsigned int inputCnt = 0; ///< Counter for characters in the input buffer
|
||||||
|
static char inputBuffer[32]; ///< Buffer to store the received characters
|
||||||
|
InputProcessed_t InputProcessed = IDLE; ///< State variable for input processing
|
||||||
|
|
||||||
|
// Check if there are characters available in the Serial input buffer
|
||||||
|
if (Serial.available())
|
||||||
|
{
|
||||||
|
char inputChar = Serial.read();
|
||||||
|
|
||||||
|
// Process the received character based on its value
|
||||||
|
switch (inputChar)
|
||||||
|
{
|
||||||
|
case '\n':
|
||||||
|
inputBuffer[inputCnt] = 0; // terminate the String
|
||||||
|
inputCnt = 0;
|
||||||
|
InputProcessed = CMD_COMPLETE;
|
||||||
|
Serial.write(inputChar);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1B: // Esc
|
||||||
|
inputBuffer[0] = 0;
|
||||||
|
inputCnt = 0;
|
||||||
|
InputProcessed = CMD_ABORT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x21 ... 0x7E: // it's a real letter or sign and not some control-chars
|
||||||
|
inputBuffer[inputCnt] = inputChar;
|
||||||
|
inputCnt++;
|
||||||
|
Serial.write(inputChar);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for input buffer overflow
|
||||||
|
if (inputCnt > sizeof(inputBuffer))
|
||||||
|
{
|
||||||
|
inputCnt = 0;
|
||||||
|
inputBuffer[sizeof(inputBuffer) - 1] = 0; // terminate the String
|
||||||
|
InputProcessed = CMD_OVERFLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the command based on the detected state of input processing
|
||||||
|
switch (InputProcessed)
|
||||||
|
{
|
||||||
|
case CMD_ABORT:
|
||||||
|
Debug_pushMessage("Abort\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_COMPLETE:
|
||||||
|
processCmdDebug(String(inputBuffer));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_OVERFLOW:
|
||||||
|
Debug_pushMessage("Input buffer overflow\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InputProcessed != IDLE)
|
||||||
|
Serial.print(">");
|
||||||
|
|
||||||
|
InputProcessed = IDLE;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Sets the status of a specific debug port (Serial or WebUI).
|
||||||
|
* Updates the status in the DebuggerStatus array and provides debug messages.
|
||||||
|
*
|
||||||
|
* @param port The debug port to set the status for (dbg_Serial or dbg_Webui).
|
||||||
|
* @param status The status to set (enabled or disabled).
|
||||||
|
*/
|
||||||
|
void SetDebugportStatus(DebugPorts_t port, DebugStatus_t status)
|
||||||
|
{
|
||||||
|
// Display a debug message based on the provided status
|
||||||
|
if (status == disabled)
|
||||||
|
Debug_pushMessage("Disable DebugPort %s\n", sDebugPorts[port]);
|
||||||
|
|
||||||
|
// Update the status in the DebuggerStatus array
|
||||||
|
DebuggerStatus[port] = status;
|
||||||
|
|
||||||
|
// Display a debug message based on the updated status
|
||||||
|
if (status == enabled)
|
||||||
|
Debug_pushMessage("Enabled DebugPort %s\n", sDebugPorts[port]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pushes a formatted debug message to the enabled debug ports (Serial or WebUI).
|
||||||
|
*
|
||||||
|
* @param format The format string for the debug message.
|
||||||
|
* @param ... Additional arguments for formatting the message.
|
||||||
|
*/
|
||||||
|
void Debug_pushMessage(const char *format, ...)
|
||||||
|
{
|
||||||
|
// Check if either the Serial or WebUI debug port is enabled
|
||||||
|
if ((DebuggerStatus[dbg_Serial] == enabled) || (DebuggerStatus[dbg_Webui] == enabled))
|
||||||
|
{
|
||||||
|
char buff[128]; // Buffer to hold the formatted message
|
||||||
|
va_list arg; // Variable argument list for vsnprintf
|
||||||
|
va_start(arg, format);
|
||||||
|
|
||||||
|
// Format the message and store it in the buffer
|
||||||
|
vsnprintf(buff, sizeof(buff), format, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
// Send the message to the Serial debug port if enabled
|
||||||
|
if (DebuggerStatus[dbg_Serial] == enabled)
|
||||||
|
{
|
||||||
|
Serial.print(buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push the message to the WebUI debug port if enabled
|
||||||
|
if (DebuggerStatus[dbg_Webui] == enabled)
|
||||||
|
{
|
||||||
|
Websocket_PushLiveDebug(String(buff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Processes a debug command and performs corresponding actions.
|
||||||
|
*
|
||||||
|
* @param command The debug command to be processed.
|
||||||
|
*/
|
||||||
|
void processCmdDebug(String command)
|
||||||
|
{
|
||||||
|
// Check the received command and execute corresponding actions
|
||||||
|
if (command == "help")
|
||||||
|
Debug_printHelp();
|
||||||
|
else if (command == "reboot")
|
||||||
|
globals.systemStatus = sysStat_Shutdown;
|
||||||
|
else if (command == "sysinfo")
|
||||||
|
Debug_printSystemInfo();
|
||||||
|
else if (command == "netinfo")
|
||||||
|
Debug_printWifiInfo();
|
||||||
|
else if (command == "formatCFG")
|
||||||
|
Debug_formatCFG();
|
||||||
|
else if (command == "formatPDS")
|
||||||
|
Debug_formatPersistence();
|
||||||
|
else if (command == "checkEE")
|
||||||
|
Debug_CheckEEPOM(false);
|
||||||
|
else if (command == "checkEEfix")
|
||||||
|
Debug_CheckEEPOM(true);
|
||||||
|
else if (command == "dumpEE1k")
|
||||||
|
dumpEEPROM(0, 1024);
|
||||||
|
else if (command == "dumpEE")
|
||||||
|
dumpEEPROM(0, EEPROM_SIZE_BYTES);
|
||||||
|
else if (command == "killEE")
|
||||||
|
writeSequentialToEEPROM(0, 1024);
|
||||||
|
else if (command == "zeroEE")
|
||||||
|
writeZeroToEEPROM(0, 1024);
|
||||||
|
else if (command == "resetPageEE")
|
||||||
|
MovePersistencePage_EEPROM(true);
|
||||||
|
else if (command == "dumpCFG")
|
||||||
|
Debug_dumpConfig();
|
||||||
|
else if (command == "dumpPDS")
|
||||||
|
Debug_dumpPersistance();
|
||||||
|
else if (command == "saveEE")
|
||||||
|
globals.requestEEAction = EE_ALL_SAVE;
|
||||||
|
else if (command == "dumpGlobals")
|
||||||
|
Debug_dumpGlobals();
|
||||||
|
else if (command == "sdbg")
|
||||||
|
SetDebugportStatus(dbg_Serial, enabled);
|
||||||
|
else if (command == "dtc_show")
|
||||||
|
Debug_ShowDTCs();
|
||||||
|
else if (command == "dtc_clear")
|
||||||
|
ClearAllDTC();
|
||||||
|
else if (command == "dtc_crit")
|
||||||
|
MaintainDTC(DTC_FAKE_DTC_CRIT, true, millis());
|
||||||
|
else if (command == "dtc_warn")
|
||||||
|
MaintainDTC(DTC_FAKE_DTC_WARN, true, millis());
|
||||||
|
else if (command == "dtc_info")
|
||||||
|
MaintainDTC(DTC_FAKE_DTC_INFO, true, millis());
|
||||||
|
else if (command == "notify_error")
|
||||||
|
Websocket_PushNotification("Debug Error Notification", error);
|
||||||
|
else if (command == "notify_warning")
|
||||||
|
Websocket_PushNotification("Debug Warning Notification", warning);
|
||||||
|
else if (command == "notify_success")
|
||||||
|
Websocket_PushNotification("Debug Success Notification", success);
|
||||||
|
else if (command == "notify_info")
|
||||||
|
Websocket_PushNotification("Debug Info Notification", info);
|
||||||
|
else
|
||||||
|
Debug_pushMessage("unknown Command\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Formats the Config-EEPROM and resets it to default values.
|
||||||
|
* Prints a debug message after formatting.
|
||||||
|
*/
|
||||||
|
void Debug_formatCFG()
|
||||||
|
{
|
||||||
|
Debug_pushMessage("Formatting Config-EEPROM and resetting to default\n");
|
||||||
|
FormatConfig_EEPROM();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Formats the Persistence-EEPROM and resets it to default values.
|
||||||
|
* Prints a debug message after formatting.
|
||||||
|
*/
|
||||||
|
void Debug_formatPersistence()
|
||||||
|
{
|
||||||
|
Debug_pushMessage("Formatting Persistence-EEPROM and resetting to default\n");
|
||||||
|
FormatPersistence_EEPROM();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prints system information and status to the debug output.
|
||||||
|
*/
|
||||||
|
void Debug_printSystemInfo()
|
||||||
|
{
|
||||||
|
Debug_pushMessage("Hostname: %s\n", globals.DeviceName);
|
||||||
|
|
||||||
|
FlashMode_t ideMode = ESP.getFlashChipMode();
|
||||||
|
Debug_pushMessage("Sdk version: %s\n", ESP.getSdkVersion());
|
||||||
|
Debug_pushMessage("Core Version: %s\n", ESP.getCoreVersion().c_str());
|
||||||
|
Debug_pushMessage("Boot Version: %u\n", ESP.getBootVersion());
|
||||||
|
Debug_pushMessage("Boot Mode: %u\n", ESP.getBootMode());
|
||||||
|
Debug_pushMessage("CPU Frequency: %u MHz\n", ESP.getCpuFreqMHz());
|
||||||
|
Debug_pushMessage("Reset reason: %s\n", ESP.getResetReason().c_str());
|
||||||
|
Debug_pushMessage("Flash Size: %d\n", ESP.getFlashChipRealSize());
|
||||||
|
Debug_pushMessage("Flash Size IDE: %d\n", ESP.getFlashChipSize());
|
||||||
|
Debug_pushMessage("Flash ide mode: %s\n", (ideMode == FM_QIO ? "QIO" : ideMode == FM_QOUT ? "QOUT"
|
||||||
|
: ideMode == FM_DIO ? "DIO"
|
||||||
|
: ideMode == FM_DOUT ? "DOUT"
|
||||||
|
: "UNKNOWN"));
|
||||||
|
Debug_pushMessage("OTA-Pass: %s\n", QUOTE(ADMIN_PASSWORD));
|
||||||
|
Debug_pushMessage("Git-Revision: %s\n", constants.GitHash);
|
||||||
|
Debug_pushMessage("Sw-Version: %d.%02d\n", constants.FW_Version_major, constants.FW_Version_minor);
|
||||||
|
|
||||||
|
Debug_pushMessage("globals.systemStatus: %d\n", globals.systemStatus);
|
||||||
|
Debug_pushMessage("globals.resumeStatus: %d\n", globals.resumeStatus);
|
||||||
|
Debug_pushMessage("globals.systemStatustxt: %s\n", globals.systemStatustxt);
|
||||||
|
Debug_pushMessage("globals.requestEEAction: %d\n", globals.requestEEAction);
|
||||||
|
Debug_pushMessage("globals.DeviceName: %s\n", globals.DeviceName);
|
||||||
|
Debug_pushMessage("globals.FlashVersion: %s\n", globals.FlashVersion);
|
||||||
|
Debug_pushMessage("globals.eePersistanceAdress: %u\n", globals.eePersistanceAdress);
|
||||||
|
Debug_pushMessage("globals.hasDTC: %d\n", globals.hasDTC);
|
||||||
|
Debug_pushMessage("globals.loadvoltage_mV: %d\n", globals.loadvoltage_mV);
|
||||||
|
Debug_pushMessage("globals.battery_level: %d\n", globals.battery_level);
|
||||||
|
Debug_pushMessage("globals.timer_disabled: %d\n", globals.timer_disabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dumps the current configuration parameters to the debug output.
|
||||||
|
*/
|
||||||
|
void Debug_dumpConfig()
|
||||||
|
{
|
||||||
|
Debug_pushMessage("batteryType: %d\n", ConfigData.batteryType);
|
||||||
|
Debug_pushMessage("Faction_1_Name: %s\n", ConfigData.Faction_1_Name);
|
||||||
|
Debug_pushMessage("Faction_1_Name: %s\n", ConfigData.Faction_2_Name);
|
||||||
|
Debug_pushMessage("Faction_1_Name: %s\n", ConfigData.Faction_3_Name);
|
||||||
|
Debug_pushMessage("active_faction_on_reboot: %d\n", ConfigData.active_faction_on_reboot);
|
||||||
|
Debug_pushMessage("wifi_autoconnect: %d\n", ConfigData.wifi_autoconnect);
|
||||||
|
Debug_pushMessage("wifi_ap_password: %s\n", ConfigData.wifi_ap_password);
|
||||||
|
Debug_pushMessage("wifi_ap_ssid: %s\n", ConfigData.wifi_ap_ssid);
|
||||||
|
Debug_pushMessage("wifi_client_ssid: %s\n", ConfigData.wifi_client_ssid);
|
||||||
|
Debug_pushMessage("wifi_client_password: %s\n", ConfigData.wifi_client_password);
|
||||||
|
Debug_pushMessage("EEPROM_Version: %d\n", ConfigData.EEPROM_Version);
|
||||||
|
Debug_pushMessage("checksum: 0x%08X\n", ConfigData.checksum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dumps the global variables and their values to the debug output.
|
||||||
|
*/
|
||||||
|
void Debug_dumpGlobals()
|
||||||
|
{
|
||||||
|
Debug_pushMessage("systemStatus: %d\n", globals.systemStatus);
|
||||||
|
Debug_pushMessage("battery_level: %d\n", globals.battery_level);
|
||||||
|
Debug_pushMessage("loadvoltage_mV: %d\n", globals.loadvoltage_mV);
|
||||||
|
Debug_pushMessage("requestEEAction: %d\n", globals.requestEEAction);
|
||||||
|
Debug_pushMessage("DeviceName: %s\n", globals.DeviceName);
|
||||||
|
Debug_pushMessage("FlashVersion: %s\n", globals.FlashVersion);
|
||||||
|
Debug_pushMessage("eePersistanceAdress: %d\n", globals.eePersistanceAdress);
|
||||||
|
Debug_pushMessage("hasDTC: %d\n", globals.hasDTC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dumps the persistence data variables and their values to the debug output.
|
||||||
|
*/
|
||||||
|
void Debug_dumpPersistance()
|
||||||
|
{
|
||||||
|
Debug_pushMessage("writeCycleCounter: %d\n", PersistenceData.writeCycleCounter);
|
||||||
|
Debug_pushMessage("activeFaction: %d\n", PersistenceData.activeFaction);
|
||||||
|
Debug_pushMessage("faction_1_timer: %d\n", PersistenceData.faction_1_timer);
|
||||||
|
Debug_pushMessage("faction_2_timer: %d\n", PersistenceData.faction_2_timer);
|
||||||
|
Debug_pushMessage("faction_3_timer: %d\n", PersistenceData.faction_3_timer);
|
||||||
|
Debug_pushMessage("checksum: %d\n", PersistenceData.checksum);
|
||||||
|
Debug_pushMessage("PSD Adress: 0x%04X\n", globals.eePersistanceAdress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prints information related to WiFi to the debug output.
|
||||||
|
*/
|
||||||
|
void Debug_printWifiInfo()
|
||||||
|
{
|
||||||
|
Debug_pushMessage("IP Adress: %s\n", WiFi.localIP().toString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks the EEPROM data integrity by calculating and comparing checksums.
|
||||||
|
* Prints the result to the debug output.
|
||||||
|
*/
|
||||||
|
void Debug_CheckEEPOM(bool autocorrect)
|
||||||
|
{
|
||||||
|
// Check PersistenceData EEPROM checksum
|
||||||
|
uint32_t checksum = PersistenceData.checksum;
|
||||||
|
PersistenceData.checksum = 0;
|
||||||
|
|
||||||
|
if (Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) == checksum)
|
||||||
|
{
|
||||||
|
Debug_pushMessage("PersistenceData EEPROM Checksum OK\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug_pushMessage("PersistenceData EEPROM Checksum BAD\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
PersistenceData.checksum = checksum;
|
||||||
|
|
||||||
|
// Check ConfigData EEPROM checksum
|
||||||
|
checksum = ConfigData.checksum;
|
||||||
|
ConfigData.checksum = 0;
|
||||||
|
|
||||||
|
if (Checksum_EEPROM((uint8_t *)&ConfigData, sizeof(ConfigData)) == checksum)
|
||||||
|
{
|
||||||
|
Debug_pushMessage("ConfigData EEPROM Checksum OK\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug_pushMessage("ConfigData EEPROM Checksum BAD\n");
|
||||||
|
}
|
||||||
|
ConfigData.checksum = checksum;
|
||||||
|
|
||||||
|
uint32_t sanitycheck = ConfigSanityCheck(autocorrect);
|
||||||
|
|
||||||
|
if (sanitycheck == 0)
|
||||||
|
{
|
||||||
|
Debug_pushMessage("ConfigData Sanity Check OK\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug_pushMessage("ConfigData Sanity Check BAD: %s\n", uint32_to_binary_string(sanitycheck));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Displays Diagnostic Trouble Codes (DTCs) along with their timestamps,
|
||||||
|
* status, and severity in a formatted manner.
|
||||||
|
*/
|
||||||
|
void Debug_ShowDTCs()
|
||||||
|
{
|
||||||
|
char buff_timestamp[16]; // Format: DD-hh:mm:ss:xxx
|
||||||
|
char buff_active[9];
|
||||||
|
|
||||||
|
// Header for the DTC display
|
||||||
|
Debug_pushMessage("\n timestamp | DTC-Nr. | status | severity\n");
|
||||||
|
|
||||||
|
// Iterate through DTCStorage and display each entry
|
||||||
|
for (uint32_t i = 0; i < MAX_DTC_STORAGE; i++)
|
||||||
|
{
|
||||||
|
if (DTCStorage[i].Number < DTC_LAST_DTC)
|
||||||
|
{
|
||||||
|
// Format timestamp
|
||||||
|
sprintf(buff_timestamp, "%02d-%02d:%02d:%02d:%03d",
|
||||||
|
DTCStorage[i].timestamp / 86400000, // Days
|
||||||
|
DTCStorage[i].timestamp / 360000 % 24, // Hours
|
||||||
|
DTCStorage[i].timestamp / 60000 % 60, // Minutes
|
||||||
|
DTCStorage[i].timestamp / 1000 % 60, // Seconds
|
||||||
|
DTCStorage[i].timestamp % 1000); // Milliseconds
|
||||||
|
|
||||||
|
// Determine DTC status
|
||||||
|
if (DTCStorage[i].active == DTC_ACTIVE)
|
||||||
|
strcpy(buff_active, "active");
|
||||||
|
else if (DTCStorage[i].active == DTC_PREVIOUS)
|
||||||
|
strcpy(buff_active, "previous");
|
||||||
|
else
|
||||||
|
strcpy(buff_active, "none");
|
||||||
|
|
||||||
|
// Display DTC information
|
||||||
|
Debug_pushMessage("%s %7d %8s %8d\n", buff_timestamp, DTCStorage[i].Number, buff_active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Displays the help commands for debugging through Serial or WebUI.
|
||||||
|
* Each command is printed individually in a formatted manner.
|
||||||
|
*/
|
||||||
|
void Debug_printHelp()
|
||||||
|
{
|
||||||
|
char buff[64];
|
||||||
|
|
||||||
|
// Iterate through helpCmd and display each command
|
||||||
|
for (unsigned int i = 0; i < sizeof(helpCmd) / 63; i++)
|
||||||
|
{
|
||||||
|
// Copy a portion of helpCmd to buff for display
|
||||||
|
memcpy_P(buff, (helpCmd + (i * 63)), 63);
|
||||||
|
buff[63] = 0;
|
||||||
|
|
||||||
|
// Display the help command
|
||||||
|
Debug_pushMessage(buff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert a uint32_t value to a binary string with nibbles separated by a space.
|
||||||
|
*
|
||||||
|
* This function takes a uint32_t value and converts it to a binary string
|
||||||
|
* representation. The binary string is stored in a static buffer and returned
|
||||||
|
* as a const char pointer. Each nibble (4 bits) in the binary representation
|
||||||
|
* is separated by a space. The buffer is overwritten on subsequent calls to
|
||||||
|
* this function.
|
||||||
|
*
|
||||||
|
* @param num The uint32_t value to convert.
|
||||||
|
* @return A pointer to a const char string containing the binary representation
|
||||||
|
* of the input number with nibbles separated by a space.
|
||||||
|
*/
|
||||||
|
const char *uint32_to_binary_string(uint32_t num)
|
||||||
|
{
|
||||||
|
static char binary_str[65]; // 32 bits + 31 spaces + null terminator
|
||||||
|
int i, j;
|
||||||
|
for (i = 31, j = 0; i >= 0; i--, j++)
|
||||||
|
{
|
||||||
|
binary_str[j] = ((num >> i) & 1) ? '1' : '0';
|
||||||
|
if (i % 4 == 0 && i != 0)
|
||||||
|
{
|
||||||
|
binary_str[++j] = ' '; // Insert space after every nibble
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binary_str[j] = '\0'; // Null terminator
|
||||||
|
return binary_str;
|
||||||
|
}
|
@@ -1,70 +1,121 @@
|
|||||||
|
/**
|
||||||
|
* @file dtc.cpp
|
||||||
|
* @brief Implementation of functions related to Diagnostic Trouble Codes (DTCs).
|
||||||
|
*
|
||||||
|
* This file contains the implementation of functions that manage the status
|
||||||
|
* and registration of Diagnostic Trouble Codes in the system.
|
||||||
|
*
|
||||||
|
* @author Marcel Peterkau
|
||||||
|
* @date 09.01.2024
|
||||||
|
*/
|
||||||
#include "dtc.h"
|
#include "dtc.h"
|
||||||
|
#include "debugger.h"
|
||||||
|
|
||||||
DTCEntry_s DTCStorage[MAX_DTC_STORAGE];
|
DTCEntry_t DTCStorage[MAX_DTC_STORAGE];
|
||||||
|
|
||||||
void MaintainDTC(DTCNums_t DTC_no, boolean active)
|
// Function implementations...
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Maintains the status of Diagnostic Trouble Codes (DTCs) in the DTCStorage array.
|
||||||
|
* Updates the status of existing DTCs or adds new ones based on their activity.
|
||||||
|
*
|
||||||
|
* @param DTC_no The number of the Diagnostic Trouble Code.
|
||||||
|
* @param active Indicates whether the DTC is active (true) or inactive (false).
|
||||||
|
* @param DebugValue Additional debugging information associated with the DTC.
|
||||||
|
*/
|
||||||
|
void MaintainDTC(DTCNum_t DTC_no, boolean active, uint32_t DebugValue)
|
||||||
{
|
{
|
||||||
|
// Iterate through the existing DTCs in the storage
|
||||||
for (int i = 0; i < MAX_DTC_STORAGE; i++)
|
for (int i = 0; i < MAX_DTC_STORAGE; i++)
|
||||||
{
|
{
|
||||||
|
// Check if the DTC with the specified number exists
|
||||||
if (DTCStorage[i].Number == DTC_no)
|
if (DTCStorage[i].Number == DTC_no)
|
||||||
{
|
{
|
||||||
|
// If the DTC is active and was not active before, update its status
|
||||||
if (active && DTCStorage[i].active != DTC_ACTIVE)
|
if (active && DTCStorage[i].active != DTC_ACTIVE)
|
||||||
{
|
{
|
||||||
Serial.printf("DTC gone active: %d", DTC_no);
|
Debug_pushMessage("DTC gone active: %d, DebugVal: %d\n", DTC_no, DebugValue);
|
||||||
DTCStorage[i].timestamp = millis();
|
DTCStorage[i].timestamp = millis();
|
||||||
DTCStorage[i].active = DTC_ACTIVE;
|
DTCStorage[i].active = DTC_ACTIVE;
|
||||||
|
DTCStorage[i].debugVal = DebugValue;
|
||||||
}
|
}
|
||||||
|
// If the DTC is not active anymore, update its status to previous
|
||||||
if (!active && DTCStorage[i].active == DTC_ACTIVE)
|
if (!active && DTCStorage[i].active == DTC_ACTIVE)
|
||||||
{
|
{
|
||||||
Serial.printf("DTC gone previous: %d", DTC_no);
|
Debug_pushMessage("DTC gone previous: %d\n", DTC_no);
|
||||||
DTCStorage[i].active = DTC_PREVIOUS;
|
DTCStorage[i].active = DTC_PREVIOUS;
|
||||||
}
|
}
|
||||||
return;
|
return; // DTC found and processed, exit the function
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DTC was not found with upper iteration, but is active
|
// DTC was not found in the existing storage, but it is active,
|
||||||
// so we need to look for free space to store DTC
|
// so look for free space to store the new DTC
|
||||||
if (active == true)
|
if (active == true)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_DTC_STORAGE; i++)
|
for (int i = 0; i < MAX_DTC_STORAGE; i++)
|
||||||
{
|
{
|
||||||
|
// Check for an empty slot in the storage
|
||||||
if (DTCStorage[i].Number == DTC_LAST_DTC)
|
if (DTCStorage[i].Number == DTC_LAST_DTC)
|
||||||
{
|
{
|
||||||
Serial.printf("new DTC registered: %d", DTC_no);
|
Debug_pushMessage("new DTC registered: %d, DebugVal: %d\n", DTC_no, DebugValue);
|
||||||
DTCStorage[i].Number = DTC_no;
|
DTCStorage[i].Number = DTC_no;
|
||||||
DTCStorage[i].timestamp = millis();
|
DTCStorage[i].timestamp = millis();
|
||||||
DTCStorage[i].active = DTC_ACTIVE;
|
DTCStorage[i].active = DTC_ACTIVE;
|
||||||
return;
|
DTCStorage[i].debugVal = DebugValue;
|
||||||
|
return; // New DTC registered, exit the function
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearDTC(DTCNums_t DTC_no)
|
/**
|
||||||
|
* @brief Clears a specific Diagnostic Trouble Code (DTC) entry.
|
||||||
|
*
|
||||||
|
* This function clears the information related to a specific DTC entry,
|
||||||
|
* setting its status to inactive and timestamp to zero.
|
||||||
|
*
|
||||||
|
* @param DTC_no The Diagnostic Trouble Code number to be cleared.
|
||||||
|
*/
|
||||||
|
void ClearDTC(DTCNum_t DTC_no)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_DTC_STORAGE; i++)
|
for (int i = 0; i < MAX_DTC_STORAGE; i++)
|
||||||
{
|
{
|
||||||
if (DTCStorage[i].Number == DTC_no)
|
if (DTCStorage[i].Number == DTC_no)
|
||||||
{
|
{
|
||||||
DTCStorage[i].Number = DTC_LAST_DTC;
|
DTCStorage[i].Number = DTC_LAST_DTC;
|
||||||
DTCStorage[i].active = DTC_NONE;
|
DTCStorage[i].active = DTC_INACTIVE;
|
||||||
DTCStorage[i].timestamp = 0;
|
DTCStorage[i].timestamp = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears all Diagnostic Trouble Code (DTC) entries.
|
||||||
|
*
|
||||||
|
* This function clears all DTC entries, setting their status to inactive and
|
||||||
|
* timestamps to zero.
|
||||||
|
*/
|
||||||
void ClearAllDTC()
|
void ClearAllDTC()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_DTC_STORAGE; i++)
|
for (int i = 0; i < MAX_DTC_STORAGE; i++)
|
||||||
{
|
{
|
||||||
DTCStorage[i].Number = DTC_LAST_DTC;
|
DTCStorage[i].Number = DTC_LAST_DTC;
|
||||||
DTCStorage[i].active = DTC_NONE;
|
DTCStorage[i].active = DTC_INACTIVE;
|
||||||
DTCStorage[i].timestamp = 0;
|
DTCStorage[i].timestamp = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DTCNums_t getlastDTC(boolean only_active)
|
/**
|
||||||
|
* @brief Gets the last recorded Diagnostic Trouble Code (DTC) number.
|
||||||
|
*
|
||||||
|
* This function retrieves the DTC number of the last recorded DTC based on the
|
||||||
|
* timestamp. Optionally, it can filter only active DTCs.
|
||||||
|
*
|
||||||
|
* @param only_active If true, considers only active DTCs; otherwise, considers all.
|
||||||
|
* @return The DTC number of the last recorded DTC or DTC_LAST_DTC if none found.
|
||||||
|
*/
|
||||||
|
DTCNum_t getlastDTC(boolean only_active)
|
||||||
{
|
{
|
||||||
int8_t pointer = -1;
|
int8_t pointer = -1;
|
||||||
uint32_t lasttimestamp = 0;
|
uint32_t lasttimestamp = 0;
|
||||||
@@ -82,4 +133,64 @@ DTCNums_t getlastDTC(boolean only_active)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return pointer >= 0 ? DTCStorage[pointer].Number : DTC_LAST_DTC;
|
return pointer >= 0 ? DTCStorage[pointer].Number : DTC_LAST_DTC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the severity level for a specific Diagnostic Trouble Code (DTC).
|
||||||
|
*
|
||||||
|
* This function looks up the severity level associated with the provided DTC code
|
||||||
|
* from the predefined list of DTC definitions.
|
||||||
|
*
|
||||||
|
* @param targetCode The DTC code for which to retrieve the severity.
|
||||||
|
* @return The severity level of the specified DTC or DTC_NONE if not found.
|
||||||
|
*/
|
||||||
|
DTCSeverity_t getSeverityForDTC(DTCNum_t targetCode)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < DTC_LAST_DTC; i++)
|
||||||
|
{
|
||||||
|
if (dtc_definitions[i].code == targetCode)
|
||||||
|
{
|
||||||
|
return dtc_definitions[i].severity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DTC_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Processes Diagnostic Trouble Codes (DTCs) and updates system status accordingly.
|
||||||
|
*
|
||||||
|
* This function checks for the presence of active DTCs and adjusts the system status
|
||||||
|
* based on the severity of the most critical DTC. If a critical DTC is detected,
|
||||||
|
* the system status is set to sysStat_Error, potentially triggering a system shutdown.
|
||||||
|
*
|
||||||
|
* @note The function also preserves the original system status when transitioning to an error state
|
||||||
|
* and restores it when all DTCs are cleared.
|
||||||
|
*/
|
||||||
|
void DTC_Process()
|
||||||
|
{
|
||||||
|
static tSystem_Status preserverSysStatusError;
|
||||||
|
DTCNum_t lastDTC = getlastDTC(true);
|
||||||
|
|
||||||
|
if (lastDTC < DTC_LAST_DTC)
|
||||||
|
{
|
||||||
|
globals.hasDTC = true;
|
||||||
|
|
||||||
|
if (getSeverityForDTC(lastDTC) == DTC_CRITICAL && globals.systemStatus != sysStat_Shutdown)
|
||||||
|
{
|
||||||
|
if (globals.systemStatus != sysStat_Error)
|
||||||
|
{
|
||||||
|
preserverSysStatusError = globals.systemStatus;
|
||||||
|
}
|
||||||
|
globals.systemStatus = sysStat_Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
globals.hasDTC = false;
|
||||||
|
|
||||||
|
if (globals.systemStatus == sysStat_Error)
|
||||||
|
{
|
||||||
|
globals.systemStatus = preserverSysStatusError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1,39 +0,0 @@
|
|||||||
#ifndef _DTC_H_
|
|
||||||
#define _DTC_H_
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
|
|
||||||
#define MAX_DTC_STORAGE 6
|
|
||||||
|
|
||||||
typedef enum DTCNums_e
|
|
||||||
{
|
|
||||||
DTC_NO_EEPROM_FOUND,
|
|
||||||
DTC_EEPROM_CFG_BAD,
|
|
||||||
DTC_EEPROM_PDS_BAD,
|
|
||||||
DTC_EEPROM_VERSION_BAD,
|
|
||||||
DTC_EEPROM_WORNOUT, // this will happen if the EEPROM-cells are all overwritten 1 million times!
|
|
||||||
DTC_EEPROM_PDS_MARKER_INVALID, // This happens if the Marker of the PersistanceData was pointing to an EE-Adress bigger than the used EEPROM-IC
|
|
||||||
DTC_LAST_DTC
|
|
||||||
} DTCNums_t;
|
|
||||||
|
|
||||||
typedef enum DTCActive_e
|
|
||||||
{
|
|
||||||
DTC_ACTIVE,
|
|
||||||
DTC_PREVIOUS,
|
|
||||||
DTC_NONE
|
|
||||||
} DTCActive_t;
|
|
||||||
|
|
||||||
typedef struct DTCEntry_s
|
|
||||||
{
|
|
||||||
DTCNums_t Number;
|
|
||||||
uint32_t timestamp;
|
|
||||||
DTCActive_t active;
|
|
||||||
} DTCEntry_t;
|
|
||||||
|
|
||||||
void MaintainDTC(DTCNums_t DTC_no, boolean active);
|
|
||||||
void ClearDTC(DTCNums_t DTC_no);
|
|
||||||
void ClearAllDTC();
|
|
||||||
DTCNums_t getlastDTC(boolean only_active);
|
|
||||||
|
|
||||||
extern DTCEntry_s DTCStorage[MAX_DTC_STORAGE];
|
|
||||||
#endif
|
|
18
Software/src/dtc_defs.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# No. | DTC-Constant | Severity | Title | Description
|
||||||
|
#-----|------------------------------|---------------|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
1; DTC_BAT_CRITICAL; DTC_CRITICAL; Akku leer; Akku ist komplett leer. Den Akku aufladen!
|
||||||
|
2; DTC_BAT_LOW; DTC_WARN; Akku niedrig; Akku ist unter der Warnschwelle. Den Akku demnächst aufladen
|
||||||
|
3; DTC_NO_EEPROM_FOUND; DTC_CRITICAL; kein EEPROM erkannt; Es wurde kein EEPROM gefunden. Dies lässt einen Hardware-Defekt vermuten.
|
||||||
|
4; DTC_EEPROM_CFG_BAD; DTC_CRITICAL; EEPROM CFG Checksumme; Die Checksumme der Config-Partition des EEPROM ist ungültig. Setzen sie den EEPROM-Bereich 'CFG' im Menu 'Wartung' zurück
|
||||||
|
5; DTC_EEPROM_PDS_BAD; DTC_CRITICAL; EEPROM PDS Checksumme; Die Checksumme der Betriebsdaten-Partition des EEPROM ist ungültig. Setzen sie den EEPROM-Bereich 'PDS' im Menu 'Wartung' zurück
|
||||||
|
6; DTC_EEPROM_PDSADRESS_BAD; DTC_CRITICAL; EEPROM PDS Adresse; Die Adresse der Betriebsdaten-Partition im EEPROM ist ungültig. Setzen sie den EEPROM-Bereich 'PDS' im Menu 'Wartung' zurück
|
||||||
|
7; DTC_EEPROM_VERSION_BAD; DTC_CRITICAL; EEPROM Version falsch; Die Layout-Version des EEPROM stimmt nicht mit der Firmware-Version überein. Setzen sie den EEPROM-Bereich 'CFG' im Menu 'Wartung' zurück
|
||||||
|
8; DTC_FLASHFS_ERROR; DTC_CRITICAL; Flashspeicher Fehler; Der Flashspeicher konnte nicht initialisiert werden. Aktualisieren sie Flash & Firmware
|
||||||
|
9; DTC_FLASHFS_VERSION_ERROR; DTC_CRITICAL; Flashversion falsch; Die Version des Flashspeicher stimmt nicht mit der Firmware-Version überein. Aktualisieren sie den Flash mit der passenden Update-Datei
|
||||||
|
10; DTC_NO_BATMNON_FOUND; DTC_CRITICAL; Keine Akkuüberwachung; Es wurde keine Akkuüberwachung über I2C gefunden, Prüfen sie die Hardware!
|
||||||
|
11; DTC_NO_LORA_FOUND; DTC_CRITICAL; LoRa-Transceiver Error; Es konnte keine Verbindung zum LoRa-Transceiver hergestellt werden. Prüfen Sie die Hardware auf Defekte
|
||||||
|
12; DTC_EEPROM_CFG_SANITY; DTC_WARN; Config-Validierung; Ein oder mehrer Einstellungswerte sind ausserhalb plausibler Werte. Prüfen Sie Ihre Einstellungen
|
||||||
|
13; DTC_EEPROM_MIGRATE_FAILED; DTC_CRITICAL; EEPROM-Migration; Es wurde ein altes EEPROm Image erkannt, konnte aber nicht migriert werden. EEPROM manuell zurück setzen und neue Einstellunge speichern.
|
||||||
|
14; DTC_FAKE_DTC_INFO; DTC_INFO; Dummy-DTC Info; Ein Dummy-DTC der Schwere "Info" für Debugging-Zwecke
|
||||||
|
15; DTC_FAKE_DTC_WARN; DTC_WARN; Dummy-DTC Warnung; Ein Dummy-DTC der Schwere "Warnung" für Debugging-Zwecke
|
||||||
|
16; DTC_FAKE_DTC_CRIT; DTC_CRITICAL; Dummy-DTC Kritisch; Ein Dummy-DTC der Schwere "Kritisch" für Debugging-Zwecke
|
514
Software/src/eeprom.cpp
Normal file
@@ -0,0 +1,514 @@
|
|||||||
|
/**
|
||||||
|
* @file config.cpp
|
||||||
|
* @brief Implementation of EEPROM and configuration-related functions.
|
||||||
|
*
|
||||||
|
* This file contains functions for managing EEPROM storage and handling configuration data.
|
||||||
|
* It includes the definitions of configuration structures, EEPROM access, and utility functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "eeprom.h"
|
||||||
|
#include "debugger.h"
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
// Instance of I2C_eeprom for EEPROM access
|
||||||
|
I2C_eeprom ee(I2C_EE_ADDRESS, EEPROM_SIZE_BYTES);
|
||||||
|
|
||||||
|
// Configuration and persistence data structures
|
||||||
|
configData_t ConfigData;
|
||||||
|
persistenceData_t PersistenceData;
|
||||||
|
|
||||||
|
// EEPROM version identifier
|
||||||
|
const uint16_t eeVersion = EEPROM_STRUCTURE_REVISION;
|
||||||
|
|
||||||
|
// Flag indicating whether EEPROM is available
|
||||||
|
boolean eeAvailable = false;
|
||||||
|
|
||||||
|
// Offsets within EEPROM for ConfigData and PersistenceData
|
||||||
|
const uint16_t startofConfigData = 16;
|
||||||
|
const uint16_t startofPersistence = 16 + sizeof(ConfigData) + (sizeof(ConfigData) % 16);
|
||||||
|
|
||||||
|
// Function prototype to check EEPROM availability
|
||||||
|
boolean checkEEPROMavailable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes EEPROM and checks its availability.
|
||||||
|
*
|
||||||
|
* This function initializes the EEPROM using the I2C_eeprom instance and checks if it's available.
|
||||||
|
*/
|
||||||
|
void InitEEPROM()
|
||||||
|
{
|
||||||
|
ConfigData = ConfigData_defaults;
|
||||||
|
PersistenceData = {0};
|
||||||
|
ee.begin();
|
||||||
|
checkEEPROMavailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Processes EEPROM actions based on the request from the global state.
|
||||||
|
*
|
||||||
|
* This function processes EEPROM actions based on the request from the global state.
|
||||||
|
* It performs actions such as saving, loading, and formatting EEPROM data for both configuration and persistence.
|
||||||
|
*/
|
||||||
|
void EEPROM_Process()
|
||||||
|
{
|
||||||
|
switch (globals.requestEEAction)
|
||||||
|
{
|
||||||
|
case EE_CFG_SAVE:
|
||||||
|
StoreConfig_EEPROM();
|
||||||
|
globals.requestEEAction = EE_IDLE;
|
||||||
|
Debug_pushMessage("Stored EEPROM CFG\n");
|
||||||
|
break;
|
||||||
|
case EE_CFG_LOAD:
|
||||||
|
GetConfig_EEPROM();
|
||||||
|
globals.requestEEAction = EE_IDLE;
|
||||||
|
Debug_pushMessage("Loaded EEPROM CFG\n");
|
||||||
|
break;
|
||||||
|
case EE_CFG_FORMAT:
|
||||||
|
FormatConfig_EEPROM();
|
||||||
|
globals.requestEEAction = EE_IDLE;
|
||||||
|
GetConfig_EEPROM();
|
||||||
|
Debug_pushMessage("Formatted EEPROM CFG\n");
|
||||||
|
break;
|
||||||
|
case EE_PDS_SAVE:
|
||||||
|
StorePersistence_EEPROM();
|
||||||
|
globals.requestEEAction = EE_IDLE;
|
||||||
|
Debug_pushMessage("Stored EEPROM PDS\n");
|
||||||
|
break;
|
||||||
|
case EE_PDS_LOAD:
|
||||||
|
GetPersistence_EEPROM();
|
||||||
|
globals.requestEEAction = EE_IDLE;
|
||||||
|
Debug_pushMessage("Loaded EEPROM PDS\n");
|
||||||
|
break;
|
||||||
|
case EE_PDS_FORMAT:
|
||||||
|
FormatPersistence_EEPROM();
|
||||||
|
globals.requestEEAction = EE_IDLE;
|
||||||
|
GetPersistence_EEPROM();
|
||||||
|
Debug_pushMessage("Formatted EEPROM PDS\n");
|
||||||
|
break;
|
||||||
|
case EE_FORMAT_ALL:
|
||||||
|
FormatConfig_EEPROM();
|
||||||
|
FormatPersistence_EEPROM();
|
||||||
|
GetConfig_EEPROM();
|
||||||
|
GetPersistence_EEPROM();
|
||||||
|
globals.requestEEAction = EE_IDLE;
|
||||||
|
Debug_pushMessage("Formatted EEPROM ALL\n");
|
||||||
|
break;
|
||||||
|
case EE_ALL_SAVE:
|
||||||
|
StorePersistence_EEPROM();
|
||||||
|
StoreConfig_EEPROM();
|
||||||
|
globals.requestEEAction = EE_IDLE;
|
||||||
|
Debug_pushMessage("Stored EEPROM ALL\n");
|
||||||
|
break;
|
||||||
|
case EE_IDLE:
|
||||||
|
default:
|
||||||
|
globals.requestEEAction = EE_IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stores the configuration data in EEPROM.
|
||||||
|
*
|
||||||
|
* This function calculates the checksum for the configuration data, updates it, and stores it in EEPROM.
|
||||||
|
* It also performs a sanity check on the configuration and raises a diagnostic trouble code (DTC) if needed.
|
||||||
|
*/
|
||||||
|
void StoreConfig_EEPROM()
|
||||||
|
{
|
||||||
|
// Berechnung der Prüfsumme
|
||||||
|
ConfigData.checksum = 0;
|
||||||
|
ConfigData.checksum = Checksum_EEPROM((uint8_t *)&ConfigData, sizeof(ConfigData));
|
||||||
|
|
||||||
|
// Überprüfung, ob der EEPROM verfügbar ist
|
||||||
|
if (!checkEEPROMavailable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Byteweise in den EEPROM schreiben
|
||||||
|
uint8_t *dataPtr = (uint8_t *)&ConfigData;
|
||||||
|
for (uint16_t i = 0; i < sizeof(ConfigData); i++)
|
||||||
|
{
|
||||||
|
ee.writeByte(startofConfigData + i, dataPtr[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity Check der Konfiguration
|
||||||
|
uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false);
|
||||||
|
if (ConfigSanityCheckResult > 0)
|
||||||
|
{
|
||||||
|
MaintainDTC(DTC_EEPROM_CFG_SANITY, true, ConfigSanityCheckResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the configuration data from EEPROM.
|
||||||
|
*
|
||||||
|
* This function reads the configuration data from EEPROM, performs a checksum validation,
|
||||||
|
* and conducts a sanity check on the configuration. It raises a diagnostic trouble code (DTC) if needed.
|
||||||
|
*/
|
||||||
|
void GetConfig_EEPROM()
|
||||||
|
{
|
||||||
|
if (!checkEEPROMavailable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ee.readBlock(startofConfigData, (uint8_t *)&ConfigData, sizeof(ConfigData));
|
||||||
|
|
||||||
|
uint32_t checksum = ConfigData.checksum;
|
||||||
|
ConfigData.checksum = 0;
|
||||||
|
|
||||||
|
MaintainDTC(DTC_EEPROM_CFG_BAD, (Checksum_EEPROM((uint8_t *)&ConfigData, sizeof(ConfigData)) != checksum));
|
||||||
|
|
||||||
|
ConfigData.checksum = checksum;
|
||||||
|
|
||||||
|
uint32_t ConfigSanityCheckResult = ConfigSanityCheck(false);
|
||||||
|
|
||||||
|
MaintainDTC(DTC_EEPROM_CFG_SANITY, (ConfigSanityCheckResult > 0), ConfigSanityCheckResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stores the persistence data in EEPROM.
|
||||||
|
*
|
||||||
|
* This function increments the write cycle counter, performs a checksum calculation on the persistence data,
|
||||||
|
* and stores it in EEPROM. It also handles EEPROM page movement when needed.
|
||||||
|
*/
|
||||||
|
void StorePersistence_EEPROM()
|
||||||
|
{
|
||||||
|
if (PersistenceData.writeCycleCounter >= 0xFFF0)
|
||||||
|
MovePersistencePage_EEPROM(false);
|
||||||
|
else
|
||||||
|
PersistenceData.writeCycleCounter++;
|
||||||
|
|
||||||
|
PersistenceData.checksum = 0;
|
||||||
|
PersistenceData.checksum = Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData));
|
||||||
|
|
||||||
|
if (!checkEEPROMavailable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Byteweise in den EEPROM schreiben
|
||||||
|
uint8_t *dataPtr = (uint8_t *)&PersistenceData;
|
||||||
|
for (uint16_t i = 0; i < sizeof(PersistenceData); i++)
|
||||||
|
{
|
||||||
|
ee.writeByte(globals.eePersistanceAdress + i, dataPtr[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Retrieves the persistence data from EEPROM.
|
||||||
|
*
|
||||||
|
* This function reads the EEPROM to get the start address of the persistence data.
|
||||||
|
* If the start address is out of range, it resets and stores defaults. Otherwise,
|
||||||
|
* it reads from EEPROM and checks if the data is correct.
|
||||||
|
*/
|
||||||
|
void GetPersistence_EEPROM()
|
||||||
|
{
|
||||||
|
if (!checkEEPROMavailable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ee.readBlock(0, (uint8_t *)&globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress));
|
||||||
|
// if we got the StartAdress of Persistance and it's out of Range - we Reset it and store defaults
|
||||||
|
// otherwise we Read from eeprom and check if everything is correct
|
||||||
|
if (globals.eePersistanceAdress < startofPersistence || globals.eePersistanceAdress > ee.getDeviceSize())
|
||||||
|
{
|
||||||
|
MovePersistencePage_EEPROM(true);
|
||||||
|
FormatPersistence_EEPROM();
|
||||||
|
MaintainDTC(DTC_EEPROM_PDSADRESS_BAD, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ee.readBlock(globals.eePersistanceAdress, (uint8_t *)&PersistenceData, sizeof(PersistenceData));
|
||||||
|
|
||||||
|
uint32_t checksum = PersistenceData.checksum;
|
||||||
|
PersistenceData.checksum = 0;
|
||||||
|
|
||||||
|
MaintainDTC(DTC_EEPROM_PDS_BAD, (Checksum_EEPROM((uint8_t *)&PersistenceData, sizeof(PersistenceData)) != checksum));
|
||||||
|
|
||||||
|
PersistenceData.checksum = checksum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Formats the configuration partition in EEPROM.
|
||||||
|
*
|
||||||
|
* This function resets the configuration data to defaults and stores it in EEPROM.
|
||||||
|
*/
|
||||||
|
void FormatConfig_EEPROM()
|
||||||
|
{
|
||||||
|
Debug_pushMessage("Formatting Config-Partition\n");
|
||||||
|
ConfigData = ConfigData_defaults;
|
||||||
|
ConfigData.EEPROM_Version = eeVersion;
|
||||||
|
StoreConfig_EEPROM();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Formats the persistence partition in EEPROM.
|
||||||
|
*
|
||||||
|
* This function resets the persistence data to defaults and stores it in EEPROM.
|
||||||
|
*/
|
||||||
|
void FormatPersistence_EEPROM()
|
||||||
|
{
|
||||||
|
Debug_pushMessage("Formatting Persistance-Partition\n");
|
||||||
|
PersistenceData = {0};
|
||||||
|
// memset(&PersistenceData, 0, sizeof(PersistenceData));
|
||||||
|
StorePersistence_EEPROM();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Moves the persistence page in EEPROM.
|
||||||
|
*
|
||||||
|
* This function adjusts the persistence page address and resets the write cycle counter.
|
||||||
|
*
|
||||||
|
* @param reset If true, the function resets the persistence page address to the start of the partition.
|
||||||
|
*/
|
||||||
|
void MovePersistencePage_EEPROM(boolean reset)
|
||||||
|
{
|
||||||
|
if (!checkEEPROMavailable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
globals.eePersistanceAdress += sizeof(PersistenceData);
|
||||||
|
PersistenceData.writeCycleCounter = 0;
|
||||||
|
|
||||||
|
// Check if we reached the end of the EEPROM and start over at the beginning
|
||||||
|
if ((globals.eePersistanceAdress + sizeof(PersistenceData)) > ee.getDeviceSize() || reset)
|
||||||
|
{
|
||||||
|
globals.eePersistanceAdress = startofPersistence;
|
||||||
|
}
|
||||||
|
|
||||||
|
ee.updateBlock(0, (uint8_t *)&globals.eePersistanceAdress, sizeof(globals.eePersistanceAdress));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate CRC-32 checksum for a block of data.
|
||||||
|
*
|
||||||
|
* This function implements the CRC-32 algorithm.
|
||||||
|
*
|
||||||
|
* @param data Pointer to the data block.
|
||||||
|
* @param len Length of the data block in bytes.
|
||||||
|
* @return CRC-32 checksum.
|
||||||
|
*/
|
||||||
|
uint32_t Checksum_EEPROM(uint8_t const *data, size_t len)
|
||||||
|
{
|
||||||
|
if (data == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uint32_t crc = 0xFFFFFFFF;
|
||||||
|
uint32_t mask;
|
||||||
|
|
||||||
|
while (len--)
|
||||||
|
{
|
||||||
|
crc ^= *data++;
|
||||||
|
|
||||||
|
for (uint8_t k = 0; k < 8; k++)
|
||||||
|
{
|
||||||
|
mask = -(crc & 1);
|
||||||
|
crc = (crc >> 1) ^ (0xEDB88320 & mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ~crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dump a portion of EEPROM contents for debugging.
|
||||||
|
*
|
||||||
|
* This function prints the contents of a specified portion of EEPROM in a formatted way.
|
||||||
|
*
|
||||||
|
* @param memoryAddress Starting address in EEPROM.
|
||||||
|
* @param length Number of bytes to dump.
|
||||||
|
*/
|
||||||
|
void dumpEEPROM(uint16_t memoryAddress, uint16_t length)
|
||||||
|
{
|
||||||
|
#define BLOCK_TO_LENGTH 16
|
||||||
|
|
||||||
|
if (!checkEEPROMavailable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
char ascii_buf[BLOCK_TO_LENGTH + 1] = {0};
|
||||||
|
sprintf(ascii_buf, "%*s", BLOCK_TO_LENGTH, "ASCII");
|
||||||
|
|
||||||
|
// Print column headers
|
||||||
|
Debug_pushMessage(PSTR("\nAddress "));
|
||||||
|
for (int x = 0; x < BLOCK_TO_LENGTH; x++)
|
||||||
|
Debug_pushMessage("%3d", x);
|
||||||
|
|
||||||
|
// Align address and length to BLOCK_TO_LENGTH boundaries
|
||||||
|
memoryAddress = memoryAddress / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
|
||||||
|
length = (length + BLOCK_TO_LENGTH - 1) / BLOCK_TO_LENGTH * BLOCK_TO_LENGTH;
|
||||||
|
|
||||||
|
// Iterate through the specified portion of EEPROM
|
||||||
|
for (unsigned int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
int blockpoint = memoryAddress % BLOCK_TO_LENGTH;
|
||||||
|
|
||||||
|
// Print ASCII representation header for each block
|
||||||
|
if (blockpoint == 0)
|
||||||
|
{
|
||||||
|
if (i > 0) // Ensure we don't print an empty ASCII buffer on the first iteration
|
||||||
|
{
|
||||||
|
ascii_buf[BLOCK_TO_LENGTH] = 0;
|
||||||
|
Debug_pushMessage(" %s", ascii_buf);
|
||||||
|
}
|
||||||
|
Debug_pushMessage("\n0x%05X:", memoryAddress);
|
||||||
|
memset(ascii_buf, ' ', BLOCK_TO_LENGTH); // Clear the ASCII buffer with spaces
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read and print each byte
|
||||||
|
uint8_t byte = ee.readByte(memoryAddress);
|
||||||
|
ascii_buf[blockpoint] = (byte >= 0x20 && byte <= 0x7E) ? byte : '.';
|
||||||
|
Debug_pushMessage(" %02X", byte);
|
||||||
|
|
||||||
|
memoryAddress++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print remaining ASCII buffer
|
||||||
|
ascii_buf[BLOCK_TO_LENGTH] = 0;
|
||||||
|
Debug_pushMessage(" %s\n", ascii_buf); // Final ASCII line
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if EEPROM is available and connected.
|
||||||
|
*
|
||||||
|
* This function checks if the EEPROM is available and connected. If not, it triggers
|
||||||
|
* a diagnostic trouble code (DTC) indicating the absence of EEPROM.
|
||||||
|
*
|
||||||
|
* @return true if EEPROM is available, false otherwise.
|
||||||
|
*/
|
||||||
|
boolean checkEEPROMavailable()
|
||||||
|
{
|
||||||
|
// Check if EEPROM is connected
|
||||||
|
if (!ee.isConnected())
|
||||||
|
{
|
||||||
|
// Trigger DTC for no EEPROM found
|
||||||
|
MaintainDTC(DTC_NO_EEPROM_FOUND, true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear DTC for no EEPROM found since it's available now
|
||||||
|
MaintainDTC(DTC_NO_EEPROM_FOUND, false);
|
||||||
|
|
||||||
|
// EEPROM is available
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Perform sanity check on configuration settings.
|
||||||
|
*
|
||||||
|
* This function checks the validity of various configuration settings and returns a bitmask
|
||||||
|
* indicating which settings need to be reset. If autocorrect is enabled, it resets the settings
|
||||||
|
* to their default values.
|
||||||
|
*
|
||||||
|
* @param autocorrect If true, automatically correct invalid settings by resetting to defaults.
|
||||||
|
* @return A bitmask indicating which settings need to be reset.
|
||||||
|
*/
|
||||||
|
uint32_t ConfigSanityCheck(bool autocorrect)
|
||||||
|
{
|
||||||
|
uint32_t setting_reset_bits = 0;
|
||||||
|
|
||||||
|
if (!validateWiFiString(ConfigData.wifi_ap_ssid, sizeof(ConfigData.wifi_ap_ssid)))
|
||||||
|
{
|
||||||
|
SET_BIT(setting_reset_bits, 1);
|
||||||
|
if (autocorrect)
|
||||||
|
strncpy(ConfigData.wifi_ap_ssid, ConfigData_defaults.wifi_ap_ssid, sizeof(ConfigData.wifi_ap_ssid));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validateWiFiString(ConfigData.wifi_ap_password, sizeof(ConfigData.wifi_ap_password)))
|
||||||
|
{
|
||||||
|
SET_BIT(setting_reset_bits, 2);
|
||||||
|
if (autocorrect)
|
||||||
|
strncpy(ConfigData.wifi_ap_password, ConfigData_defaults.wifi_ap_password, sizeof(ConfigData.wifi_ap_password));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validateWiFiString(ConfigData.wifi_client_ssid, sizeof(ConfigData.wifi_client_ssid)))
|
||||||
|
{
|
||||||
|
SET_BIT(setting_reset_bits, 3);
|
||||||
|
if (autocorrect)
|
||||||
|
strncpy(ConfigData.wifi_client_ssid, ConfigData_defaults.wifi_client_ssid, sizeof(ConfigData.wifi_client_ssid));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validateWiFiString(ConfigData.wifi_client_password, sizeof(ConfigData.wifi_client_password)))
|
||||||
|
{
|
||||||
|
SET_BIT(setting_reset_bits, 4);
|
||||||
|
if (autocorrect)
|
||||||
|
strncpy(ConfigData.wifi_client_password, ConfigData_defaults.wifi_client_password, sizeof(ConfigData.wifi_client_password));
|
||||||
|
}
|
||||||
|
// Return the bitmask indicating which settings need to be reset
|
||||||
|
return setting_reset_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Validates whether a given string contains only characters allowed in WiFi SSIDs and passwords.
|
||||||
|
*
|
||||||
|
* This function checks each character in the provided string to ensure
|
||||||
|
* that it contains only characters allowed in WiFi SSIDs and passwords.
|
||||||
|
* It considers characters from 'A' to 'Z', 'a' to 'z', '0' to '9', as well as
|
||||||
|
* the following special characters: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
|
||||||
|
*
|
||||||
|
* @param string Pointer to the string to be validated.
|
||||||
|
* @param size Size of the string including the null-terminator.
|
||||||
|
* @return true if the string contains only allowed characters or is NULL,
|
||||||
|
* false otherwise.
|
||||||
|
*/
|
||||||
|
bool validateWiFiString(char *string, size_t size)
|
||||||
|
{
|
||||||
|
if (string == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
char c = string[i];
|
||||||
|
if (c == '\0')
|
||||||
|
{
|
||||||
|
// Reached the end of the string, all characters were valid WiFi characters.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
|
||||||
|
(c >= '0' && c <= '9') || c == '!' || c == '"' || c == '#' ||
|
||||||
|
c == '$' || c == '%' || c == '&' || c == '\'' || c == '(' ||
|
||||||
|
c == ')' || c == '*' || c == '+' || c == ',' || c == '-' ||
|
||||||
|
c == '.' || c == '/' || c == ':' || c == ';' || c == '<' ||
|
||||||
|
c == '=' || c == '>' || c == '?' || c == '@' || c == '[' ||
|
||||||
|
c == '\\' || c == ']' || c == '^' || c == '_' || c == '`' ||
|
||||||
|
c == '{' || c == '|' || c == '}' || c == '~'))
|
||||||
|
{
|
||||||
|
// Found a character that is not a valid WiFi character.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the loop completes without finding a null terminator, the string is invalid.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write sequential numbers to a portion of EEPROM.
|
||||||
|
*
|
||||||
|
* This function writes sequential numbers starting from 0 to a specified portion of EEPROM.
|
||||||
|
* If the number reaches 255, it wraps around and starts again from 1.
|
||||||
|
*
|
||||||
|
* @param memoryAddress Starting address in EEPROM.
|
||||||
|
* @param length Number of bytes to write.
|
||||||
|
*/
|
||||||
|
void writeSequentialToEEPROM(uint16_t memoryAddress, uint16_t length)
|
||||||
|
{
|
||||||
|
if (!checkEEPROMavailable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t value = 0;
|
||||||
|
for (uint16_t i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
ee.writeByte(memoryAddress + i, value);
|
||||||
|
value = (value == 255) ? 1 : value + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write 0 to a portion of EEPROM.
|
||||||
|
*
|
||||||
|
* This function writes 0 to a specified portion of EEPROM.
|
||||||
|
*
|
||||||
|
* @param memoryAddress Starting address in EEPROM.
|
||||||
|
* @param length Number of bytes to write.
|
||||||
|
*/
|
||||||
|
void writeZeroToEEPROM(uint16_t memoryAddress, uint16_t length)
|
||||||
|
{
|
||||||
|
if (!checkEEPROMavailable())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
ee.writeByte(memoryAddress + i, 0);
|
||||||
|
}
|
||||||
|
}
|
10
Software/src/globals.cpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
Globals_t globals;
|
||||||
|
|
||||||
|
void initGlobals()
|
||||||
|
{
|
||||||
|
globals.systemStatus = sysStat_Startup;
|
||||||
|
globals.requestEEAction = EE_IDLE;
|
||||||
|
globals.systemStatustxt[0] = 0;
|
||||||
|
}
|
@@ -1,36 +0,0 @@
|
|||||||
#ifndef _GLOBALS_H_
|
|
||||||
#define _GLOBALS_H_
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
|
|
||||||
typedef enum eSystem_Status
|
|
||||||
{
|
|
||||||
sysStat_Startup,
|
|
||||||
sysStat_Normal,
|
|
||||||
sysStat_Error,
|
|
||||||
sysStat_Shutdown
|
|
||||||
} tSystem_Status;
|
|
||||||
|
|
||||||
typedef enum eEERequest
|
|
||||||
{
|
|
||||||
EE_IDLE,
|
|
||||||
EE_CFG_SAVE,
|
|
||||||
EE_CFG_LOAD,
|
|
||||||
EE_PDS_SAVE,
|
|
||||||
EE_PDS_LOAD
|
|
||||||
} tEERequest;
|
|
||||||
|
|
||||||
typedef struct Globals_s
|
|
||||||
{
|
|
||||||
char DeviceName[33];
|
|
||||||
char DeviceName_ID[43];
|
|
||||||
tSystem_Status systemStatus = sysStat_Startup;
|
|
||||||
tSystem_Status resumeStatus = sysStat_Startup;
|
|
||||||
eEERequest requestEEAction = EE_IDLE;
|
|
||||||
float loadvoltage = 0;
|
|
||||||
int battery_level = 0;
|
|
||||||
} Globals_t;
|
|
||||||
|
|
||||||
extern Globals_t globals;
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,20 +1,322 @@
|
|||||||
#include "lora_net.h"
|
#include "lora_net.h"
|
||||||
|
|
||||||
uint8_t LoRa_Init()
|
#ifdef FEATURE_ENABLE_LORA
|
||||||
|
LoRa_E220 e220ttl(GPIO_LORA_TX, GPIO_LORA_RX, GPIO_LORA_AUX, 3, 4); // Arduino RX <-- e220 TX, Arduino TX --> e220 RX AUX M0 M1
|
||||||
|
void printParameters(struct Configuration configuration);
|
||||||
|
void printModuleInformation(struct ModuleInformation moduleInformation);
|
||||||
|
#elif defined(FEATURE_ENABLE_UARTLORA)
|
||||||
|
SoftwareSerial SerialLoRa(GPIO_LORA_RX, GPIO_LORA_TX); // RX, TX
|
||||||
|
void Parse_LoRa_UartCommand(char input[], int size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool InitLoRa(void (*MPinHelper)(int, int))
|
||||||
{
|
{
|
||||||
uint8_t success = false;
|
bool returnval = false;
|
||||||
// SPI LoRa pins
|
|
||||||
SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_SS);
|
|
||||||
// setup LoRa transceiver module
|
|
||||||
LoRa.setPins(LORA_SS, LORA_RST, LORA_DIO0);
|
|
||||||
|
|
||||||
if (!LoRa.begin(LORA_BAND))
|
#ifdef FEATURE_ENABLE_LORA
|
||||||
{
|
|
||||||
Serial.println("Starting LoRa failed!");
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
Serial.println("LoRa Initializing OK!");
|
|
||||||
success = true;
|
|
||||||
|
|
||||||
return success;
|
e220ttl.setMPins = MPinHelper;
|
||||||
|
returnval = e220ttl.begin();
|
||||||
|
|
||||||
|
if (returnval == true)
|
||||||
|
{
|
||||||
|
ResponseStructContainer c;
|
||||||
|
c = e220ttl.getConfiguration();
|
||||||
|
// It's important get configuration pointer before all other operation
|
||||||
|
Configuration configuration = *(Configuration *)c.data;
|
||||||
|
Serial.println(c.status.getResponseDescription());
|
||||||
|
Serial.println(c.status.code);
|
||||||
|
|
||||||
|
ResponseStructContainer cMi;
|
||||||
|
cMi = e220ttl.getModuleInformation();
|
||||||
|
// It's important get information pointer before all other operation
|
||||||
|
// ModuleInformation mi = *(ModuleInformation *)cMi.data;
|
||||||
|
|
||||||
|
Serial.println(cMi.status.getResponseDescription());
|
||||||
|
Serial.println(cMi.status.code);
|
||||||
|
|
||||||
|
// ----------------------- DEFAULT TRANSPARENT WITH RSSI -----------------------
|
||||||
|
configuration.ADDL = 0x02;
|
||||||
|
configuration.ADDH = 0x00;
|
||||||
|
|
||||||
|
configuration.CHAN = 23;
|
||||||
|
|
||||||
|
configuration.SPED.uartBaudRate = UART_BPS_9600;
|
||||||
|
configuration.SPED.airDataRate = AIR_DATA_RATE_010_24;
|
||||||
|
configuration.SPED.uartParity = MODE_00_8N1;
|
||||||
|
|
||||||
|
configuration.OPTION.subPacketSetting = SPS_200_00;
|
||||||
|
configuration.OPTION.RSSIAmbientNoise = RSSI_AMBIENT_NOISE_ENABLED;
|
||||||
|
configuration.OPTION.transmissionPower = POWER_22;
|
||||||
|
|
||||||
|
configuration.TRANSMISSION_MODE.enableRSSI = RSSI_ENABLED;
|
||||||
|
configuration.TRANSMISSION_MODE.fixedTransmission = FT_FIXED_TRANSMISSION;
|
||||||
|
configuration.TRANSMISSION_MODE.enableLBT = LBT_ENABLED;
|
||||||
|
configuration.TRANSMISSION_MODE.WORPeriod = WOR_2000_011;
|
||||||
|
|
||||||
|
// Set configuration changed and set to not hold the configuration
|
||||||
|
ResponseStatus rs = e220ttl.setConfiguration(configuration, WRITE_CFG_PWR_DWN_LOSE);
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
Serial.println(rs.code);
|
||||||
|
c.close();
|
||||||
|
|
||||||
|
printParameters(configuration);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MaintainDTC(DTC_NO_LORA_FOUND, DTC_WARN, true);
|
||||||
|
}
|
||||||
|
#elif defined(FEATURE_ENABLE_UARTLORA)
|
||||||
|
SerialLoRa.begin(9600);
|
||||||
|
returnval = true;
|
||||||
|
#endif
|
||||||
|
return returnval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoRa_Process()
|
||||||
|
{
|
||||||
|
#ifdef FEATURE_ENABLE_LORA
|
||||||
|
if (e220ttl.available() > 1)
|
||||||
|
{
|
||||||
|
ResponseContainer rc = e220ttl.receiveMessageRSSI();
|
||||||
|
// Is something goes wrong print error
|
||||||
|
if (rc.status.code != 1)
|
||||||
|
{
|
||||||
|
Serial.println(rc.status.getResponseDescription());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Print the data received
|
||||||
|
Serial.println(rc.status.getResponseDescription());
|
||||||
|
Serial.println(rc.data);
|
||||||
|
Serial.print("RSSI: ");
|
||||||
|
Serial.println(rc.rssi, DEC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif defined(FEATURE_ENABLE_UARTLORA)
|
||||||
|
|
||||||
|
static char packageInput[32];
|
||||||
|
static bool packageRecieved = false;
|
||||||
|
static unsigned int bufferPtr = 0;
|
||||||
|
int recievedSize = 0;
|
||||||
|
|
||||||
|
while (SerialLoRa.available() && packageRecieved == false)
|
||||||
|
{
|
||||||
|
if (bufferPtr < sizeof(packageInput) - 1)
|
||||||
|
{
|
||||||
|
packageInput[bufferPtr] = SerialLoRa.read();
|
||||||
|
packageInput[bufferPtr + 1] = 0; // always terminate String
|
||||||
|
|
||||||
|
if (packageInput[bufferPtr] == '\n')
|
||||||
|
{
|
||||||
|
packageRecieved = true;
|
||||||
|
recievedSize = bufferPtr;
|
||||||
|
bufferPtr = 0;
|
||||||
|
Debug_pushMessage("Got LoRa UART: %s\n", packageInput);
|
||||||
|
}
|
||||||
|
else if ((packageInput[bufferPtr] >= 0x30) || (packageInput[bufferPtr] <= 0x5A)) // only accept Numbers, UpperCase-Letters and some special chars
|
||||||
|
{
|
||||||
|
bufferPtr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packageRecieved) {
|
||||||
|
Parse_LoRa_UartCommand(packageInput, recievedSize);
|
||||||
|
packageRecieved = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendStatus_LoRa()
|
||||||
|
{
|
||||||
|
#ifdef FEATURE_ENABLE_LORA
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
MessageType_t type = "STATUS";
|
||||||
|
MessageStatus_t status;
|
||||||
|
} __attribute__((packed)) sendStatus;
|
||||||
|
|
||||||
|
sendStatus.status.nodeid = 0x0002;
|
||||||
|
sendStatus.status.millis = millis();
|
||||||
|
sendStatus.status.faction_active = 1;
|
||||||
|
sendStatus.status.faction_1_timer = 0xBBBBBBBB;
|
||||||
|
sendStatus.status.faction_2_timer = 0xCCCCCCCC;
|
||||||
|
sendStatus.status.faction_3_timer = 0xDDDDDDDD;
|
||||||
|
|
||||||
|
ResponseStatus rs = e220ttl.sendFixedMessage(0xFF, 0xFF, 23, (byte *)&sendStatus, sizeof(sendStatus));
|
||||||
|
Serial.println(rs.getResponseDescription());
|
||||||
|
|
||||||
|
#elif defined(FEATURE_ENABLE_UARTLORA)
|
||||||
|
|
||||||
|
SerialLoRa.print(PersistenceData.faction_1_timer);
|
||||||
|
SerialLoRa.write(";");
|
||||||
|
SerialLoRa.print(PersistenceData.faction_2_timer);
|
||||||
|
SerialLoRa.write(";");
|
||||||
|
SerialLoRa.print(PersistenceData.faction_3_timer);
|
||||||
|
SerialLoRa.write(";");
|
||||||
|
SerialLoRa.print(PersistenceData.activeFaction);
|
||||||
|
SerialLoRa.write(";");
|
||||||
|
SerialLoRa.print(globals.battery_level);
|
||||||
|
SerialLoRa.write('\n');
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FEATURE_ENABLE_LORA
|
||||||
|
|
||||||
|
void printParameters(struct Configuration configuration)
|
||||||
|
{
|
||||||
|
Serial.println("----------------------------------------");
|
||||||
|
|
||||||
|
Serial.print(F("HEAD : "));
|
||||||
|
Serial.print(configuration.COMMAND, HEX);
|
||||||
|
Serial.print(" ");
|
||||||
|
Serial.print(configuration.STARTING_ADDRESS, HEX);
|
||||||
|
Serial.print(" ");
|
||||||
|
Serial.println(configuration.LENGHT, HEX);
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("AddH : "));
|
||||||
|
Serial.println(configuration.ADDH, HEX);
|
||||||
|
Serial.print(F("AddL : "));
|
||||||
|
Serial.println(configuration.ADDL, HEX);
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("Chan : "));
|
||||||
|
Serial.print(configuration.CHAN, DEC);
|
||||||
|
Serial.print(" -> ");
|
||||||
|
Serial.println(configuration.getChannelDescription());
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("SpeedParityBit : "));
|
||||||
|
Serial.print(configuration.SPED.uartParity, BIN);
|
||||||
|
Serial.print(" -> ");
|
||||||
|
Serial.println(configuration.SPED.getUARTParityDescription());
|
||||||
|
Serial.print(F("SpeedUARTDatte : "));
|
||||||
|
Serial.print(configuration.SPED.uartBaudRate, BIN);
|
||||||
|
Serial.print(" -> ");
|
||||||
|
Serial.println(configuration.SPED.getUARTBaudRateDescription());
|
||||||
|
Serial.print(F("SpeedAirDataRate : "));
|
||||||
|
Serial.print(configuration.SPED.airDataRate, BIN);
|
||||||
|
Serial.print(" -> ");
|
||||||
|
Serial.println(configuration.SPED.getAirDataRateDescription());
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("OptionSubPacketSett: "));
|
||||||
|
Serial.print(configuration.OPTION.subPacketSetting, BIN);
|
||||||
|
Serial.print(" -> ");
|
||||||
|
Serial.println(configuration.OPTION.getSubPacketSetting());
|
||||||
|
Serial.print(F("OptionTranPower : "));
|
||||||
|
Serial.print(configuration.OPTION.transmissionPower, BIN);
|
||||||
|
Serial.print(" -> ");
|
||||||
|
Serial.println(configuration.OPTION.getTransmissionPowerDescription());
|
||||||
|
Serial.print(F("OptionRSSIAmbientNo: "));
|
||||||
|
Serial.print(configuration.OPTION.RSSIAmbientNoise, BIN);
|
||||||
|
Serial.print(" -> ");
|
||||||
|
Serial.println(configuration.OPTION.getRSSIAmbientNoiseEnable());
|
||||||
|
Serial.println(F(" "));
|
||||||
|
Serial.print(F("TransModeWORPeriod : "));
|
||||||
|
Serial.print(configuration.TRANSMISSION_MODE.WORPeriod, BIN);
|
||||||
|
Serial.print(" -> ");
|
||||||
|
Serial.println(configuration.TRANSMISSION_MODE.getWORPeriodByParamsDescription());
|
||||||
|
Serial.print(F("TransModeEnableLBT : "));
|
||||||
|
Serial.print(configuration.TRANSMISSION_MODE.enableLBT, BIN);
|
||||||
|
Serial.print(" -> ");
|
||||||
|
Serial.println(configuration.TRANSMISSION_MODE.getLBTEnableByteDescription());
|
||||||
|
Serial.print(F("TransModeEnableRSSI: "));
|
||||||
|
Serial.print(configuration.TRANSMISSION_MODE.enableRSSI, BIN);
|
||||||
|
Serial.print(" -> ");
|
||||||
|
Serial.println(configuration.TRANSMISSION_MODE.getRSSIEnableByteDescription());
|
||||||
|
Serial.print(F("TransModeFixedTrans: "));
|
||||||
|
Serial.print(configuration.TRANSMISSION_MODE.fixedTransmission, BIN);
|
||||||
|
Serial.print(" -> ");
|
||||||
|
Serial.println(configuration.TRANSMISSION_MODE.getFixedTransmissionDescription());
|
||||||
|
|
||||||
|
Serial.println("----------------------------------------");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FEATURE_ENABLE_UARTLORA
|
||||||
|
void Parse_LoRa_UartCommand(char input[], int size)
|
||||||
|
{
|
||||||
|
|
||||||
|
Debug_pushMessage("Start parsing, size: %d", size);
|
||||||
|
char delimiter[] = ";";
|
||||||
|
char *ptr;
|
||||||
|
char command[8];
|
||||||
|
char value[8];
|
||||||
|
|
||||||
|
ptr = strtok(input, delimiter);
|
||||||
|
|
||||||
|
ptr = strtok(input, delimiter);
|
||||||
|
|
||||||
|
while (ptr != NULL)
|
||||||
|
{
|
||||||
|
strncpy(command, ptr, sizeof(command) - 1); // Platz für Nullterminator lassen
|
||||||
|
command[sizeof(command) - 1] = '\0'; // Nullterminator setzen
|
||||||
|
|
||||||
|
ptr = strtok(NULL, delimiter);
|
||||||
|
|
||||||
|
if (ptr != NULL)
|
||||||
|
{
|
||||||
|
strncpy(value, ptr, sizeof(value) - 1); // Platz für Nullterminator lassen
|
||||||
|
value[sizeof(value) - 1] = '\0'; // Nullterminator setzen
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Wenn ptr NULL ist, setze value auf leeren String
|
||||||
|
value[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hier kannst du den Wert und das Kommando verarbeiten
|
||||||
|
Debug_pushMessage("Command: %s, Value: %s", command, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug_pushMessage("Parsed LoRa UART Command: %s Value: %s\n", command, value);
|
||||||
|
|
||||||
|
if (!strcmp(command, "ENABLE"))
|
||||||
|
{
|
||||||
|
globals.timer_disabled = false;
|
||||||
|
Debug_pushMessage("Enabled by LoRa");
|
||||||
|
}
|
||||||
|
else if (!strcmp(command, "DISABLE"))
|
||||||
|
{
|
||||||
|
globals.timer_disabled = true;
|
||||||
|
Debug_pushMessage("Disabled by LoRa");
|
||||||
|
}
|
||||||
|
else if (!strcmp(command, "RESET"))
|
||||||
|
{
|
||||||
|
PersistenceData.activeFaction = NONE;
|
||||||
|
PersistenceData.faction_1_timer = 0;
|
||||||
|
PersistenceData.faction_2_timer = 0;
|
||||||
|
PersistenceData.faction_3_timer = 0;
|
||||||
|
Debug_pushMessage("Reset by LoRa");
|
||||||
|
}
|
||||||
|
else if (!strcmp(command, "TMRSTP"))
|
||||||
|
{
|
||||||
|
PersistenceData.activeFaction = NONE;
|
||||||
|
}
|
||||||
|
else if (!strcmp(command, "TMR1"))
|
||||||
|
{
|
||||||
|
PersistenceData.faction_1_timer = atol(value);
|
||||||
|
}
|
||||||
|
else if (!strcmp(command, "TMR2"))
|
||||||
|
{
|
||||||
|
PersistenceData.faction_2_timer = atol(value);
|
||||||
|
}
|
||||||
|
else if (!strcmp(command, "TMR3"))
|
||||||
|
{
|
||||||
|
PersistenceData.faction_3_timer = atol(value);
|
||||||
|
}
|
||||||
|
else if (!strcmp(command, "EFAC1"))
|
||||||
|
{
|
||||||
|
PersistenceData.activeFaction = FACTION_1;
|
||||||
|
}
|
||||||
|
else if (!strcmp(command, "EFAC2"))
|
||||||
|
{
|
||||||
|
PersistenceData.activeFaction = FACTION_2;
|
||||||
|
}
|
||||||
|
else if (!strcmp(command, "EFAC3"))
|
||||||
|
{
|
||||||
|
PersistenceData.activeFaction = FACTION_3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
@@ -1,23 +0,0 @@
|
|||||||
#ifndef _LORA_NET_H_
|
|
||||||
#define _LORA_NET_H_
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <SPI.h>
|
|
||||||
#include <LoRa.h>
|
|
||||||
|
|
||||||
// define the pins used by the LoRa transceiver module
|
|
||||||
#define LORA_SCK 5
|
|
||||||
#define LORA_MISO 19
|
|
||||||
#define LORA_MOSI 27
|
|
||||||
#define LORA_SS 18
|
|
||||||
#define LORA_RST 14
|
|
||||||
#define LORA_DIO0 26
|
|
||||||
|
|
||||||
// 433E6 for Asia
|
|
||||||
// 866E6 for Europe
|
|
||||||
// 915E6 for North America
|
|
||||||
#define LORA_BAND 8681E5
|
|
||||||
|
|
||||||
uint8_t LoRa_Init();
|
|
||||||
|
|
||||||
#endif
|
|
@@ -1,42 +0,0 @@
|
|||||||
#include "oled_display.h"
|
|
||||||
|
|
||||||
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);
|
|
||||||
|
|
||||||
void OLED_Init()
|
|
||||||
{
|
|
||||||
|
|
||||||
// reset OLED display via software
|
|
||||||
pinMode(OLED_RST, OUTPUT);
|
|
||||||
digitalWrite(OLED_RST, LOW);
|
|
||||||
delay(20);
|
|
||||||
digitalWrite(OLED_RST, HIGH);
|
|
||||||
|
|
||||||
// initialize OLED
|
|
||||||
Wire.begin(OLED_SDA, OLED_SCL);
|
|
||||||
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false))
|
|
||||||
{ // Address 0x3C for 128x32
|
|
||||||
Serial.println(F("SSD1306 allocation failed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
display.clearDisplay();
|
|
||||||
display.setTextColor(WHITE);
|
|
||||||
display.setTextSize(1);
|
|
||||||
display.setCursor(0, 0);
|
|
||||||
display.print("DISPLAY INIT");
|
|
||||||
display.display();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OLED_Process()
|
|
||||||
{
|
|
||||||
|
|
||||||
display.clearDisplay();
|
|
||||||
display.setCursor(0, 0);
|
|
||||||
display.printf("LiPo: %d%%\n", globals.battery_level);
|
|
||||||
display.print(PersistenceData.activeFaction == FACTION_1 ? "> " : " ");
|
|
||||||
display.printf("%-5s: %02d:%02d:%02d\n", FACTION_1_NAME, PersistenceData.faction_1_timer / 3600, (PersistenceData.faction_1_timer / 60) % 60, PersistenceData.faction_1_timer % 60);
|
|
||||||
display.print(PersistenceData.activeFaction == FACTION_2 ? "> " : " ");
|
|
||||||
display.printf("%-5s: %02d:%02d:%02d\n", FACTION_2_NAME, PersistenceData.faction_2_timer / 3600, (PersistenceData.faction_2_timer / 60) % 60, PersistenceData.faction_2_timer % 60);
|
|
||||||
display.print(PersistenceData.activeFaction == FACTION_3 ? "> " : " ");
|
|
||||||
display.printf("%-5s: %02d:%02d:%02d\n", FACTION_3_NAME, PersistenceData.faction_3_timer / 3600, (PersistenceData.faction_3_timer / 60) % 60, PersistenceData.faction_3_timer % 60);
|
|
||||||
display.display();
|
|
||||||
}
|
|
@@ -1,20 +0,0 @@
|
|||||||
#ifndef _OLED_DISPLAY_H_
|
|
||||||
#define _OLED_DISPLAY_H_
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <Wire.h>
|
|
||||||
#include <Adafruit_GFX.h>
|
|
||||||
#include <Adafruit_SSD1306.h>
|
|
||||||
#include "globals.h"
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#define OLED_SDA 4
|
|
||||||
#define OLED_SCL 15
|
|
||||||
#define OLED_RST 16
|
|
||||||
#define SCREEN_WIDTH 128 // OLED display width, in pixels
|
|
||||||
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
|
|
||||||
|
|
||||||
void OLED_Init();
|
|
||||||
void OLED_Process();
|
|
||||||
|
|
||||||
#endif
|
|
43
Software/src/struct2json.cpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* @file struct2json.cpp
|
||||||
|
*
|
||||||
|
* @brief Implementation file for converting structs to JSON objects.
|
||||||
|
*
|
||||||
|
* @note This file is auto-generated by a script on 2024-05-30 22:54:25.
|
||||||
|
*
|
||||||
|
* @author Marcel Peterkau
|
||||||
|
* @date 30.05.2024
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "struct2json.h"
|
||||||
|
|
||||||
|
void generateJsonObject_ConfigData(JsonObject data)
|
||||||
|
{
|
||||||
|
data["EEPROM_Version"] = ConfigData.EEPROM_Version;
|
||||||
|
data["batteryType"] = ConfigData.batteryType;
|
||||||
|
data["active_faction_on_reboot"] = ConfigData.active_faction_on_reboot;
|
||||||
|
data["Faction_1_Name"] = ConfigData.Faction_1_Name;
|
||||||
|
data["Faction_2_Name"] = ConfigData.Faction_2_Name;
|
||||||
|
data["Faction_3_Name"] = ConfigData.Faction_3_Name;
|
||||||
|
data["wifi_ap_ssid"] = ConfigData.wifi_ap_ssid;
|
||||||
|
data["wifi_ap_password"] = ConfigData.wifi_ap_password;
|
||||||
|
data["wifi_client_ssid"] = ConfigData.wifi_client_ssid;
|
||||||
|
data["wifi_client_password"] = ConfigData.wifi_client_password;
|
||||||
|
data["wifi_autoconnect"] = ConfigData.wifi_autoconnect;
|
||||||
|
data["checksum"] = ConfigData.checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateJsonObject_PersistenceData(JsonObject data)
|
||||||
|
{
|
||||||
|
data["writeCycleCounter"] = PersistenceData.writeCycleCounter;
|
||||||
|
data["faction_1_timer"] = PersistenceData.faction_1_timer;
|
||||||
|
data["faction_2_timer"] = PersistenceData.faction_2_timer;
|
||||||
|
data["faction_3_timer"] = PersistenceData.faction_3_timer;
|
||||||
|
data["activeFaction"] = PersistenceData.activeFaction;
|
||||||
|
data["checksum"] = PersistenceData.checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// CODEGENERATOR_CHECKSUM: 735cd4daf9a46bd773bdf5e6cd5a58d61b0d877196399bc2784a0d0ea7af717d
|
@@ -1,209 +1,804 @@
|
|||||||
|
/**
|
||||||
|
* @file webui.cpp
|
||||||
|
*
|
||||||
|
* @brief Implementation file for web-based user interface (WebUI) functions in the DE-Timer application.
|
||||||
|
*
|
||||||
|
* This file contains the implementation of functions related to the initialization and processing of the
|
||||||
|
* web-based user interface (WebUI). It includes the setup of LittleFS, handling of firmware version checks,
|
||||||
|
* initialization of mDNS, setup of web server routes, and handling of various HTTP events.
|
||||||
|
*
|
||||||
|
* @author Marcel Peterkau
|
||||||
|
* @date 09.01.2024
|
||||||
|
*/
|
||||||
|
|
||||||
#include "webui.h"
|
#include "webui.h"
|
||||||
|
|
||||||
AsyncWebServer webServer(80);
|
AsyncWebServer webServer(80);
|
||||||
|
|
||||||
typedef enum
|
const char *PARAM_MESSAGE = "message";
|
||||||
{
|
|
||||||
RESPMSG_HIDE,
|
batteryType_t batterytypePreselect; /**< Preselect Memory for change Batterytype */
|
||||||
RESPMSG_SUCCESS,
|
|
||||||
RESPMSG_INFO,
|
|
||||||
RESPMSG_WARNING,
|
|
||||||
RESPMSG_DANGER
|
|
||||||
} statusResponseMessage_Type_t;
|
|
||||||
char StatusResponseMessage[64];
|
|
||||||
statusResponseMessage_Type_t StatusResponseMessage_Type = RESPMSG_INFO;
|
|
||||||
|
|
||||||
String processor(const String &var);
|
String processor(const String &var);
|
||||||
void WebserverPOST_Callback(AsyncWebServerRequest *request);
|
|
||||||
void WebserverNotFound_Callback(AsyncWebServerRequest *request);
|
void WebserverNotFound_Callback(AsyncWebServerRequest *request);
|
||||||
void Webserver_Callback(AsyncWebServerRequest *request);
|
void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final);
|
||||||
void WebserverCommands_Callback(String input);
|
void WebserverEERestore_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final);
|
||||||
|
void WebServerEEJSON_Callback(AsyncWebServerRequest *request);
|
||||||
|
void GetFlashVersion(char *buff, size_t buff_size);
|
||||||
|
|
||||||
|
AsyncWebSocket webSocket("/ws");
|
||||||
|
|
||||||
|
void WebsocketEvent_Callback(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len);
|
||||||
|
void Websocket_HandleMessage(void *arg, uint8_t *data, size_t len);
|
||||||
|
void Websocket_RefreshClientData_DTCs(uint32_t client_id);
|
||||||
|
void Websocket_RefreshClientData_Status(uint32_t client_id, bool send_mapping = false);
|
||||||
|
void Websocket_RefreshClientData_Static(uint32_t client_id, bool send_mapping = false);
|
||||||
|
void Websocket_HandleButtons(uint8_t *data);
|
||||||
|
void Websocket_HandleSettings(uint8_t *data);
|
||||||
|
void parseWebsocketString(char *data, char *identifierBuffer, size_t identifierBufferSize, char *valueBuffer, size_t valueBufferSize);
|
||||||
|
int findIndexByString(const char *searchString, const char *const *array, int arraySize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the web-based user interface (WebUI) for the DE-Timer application.
|
||||||
|
*
|
||||||
|
* This function sets up the necessary components for the WebUI, including mounting LittleFS,
|
||||||
|
* performing flash version checks, initializing mDNS, and configuring the web server with
|
||||||
|
* routes and event handlers. If any errors occur during setup, appropriate diagnostic messages
|
||||||
|
* are pushed to the debugging system, and potential error conditions are recorded as Diagnostic
|
||||||
|
* Trouble Codes (DTCs).
|
||||||
|
*
|
||||||
|
* @note This function should be called during the initialization phase of the application.
|
||||||
|
*/
|
||||||
void initWebUI()
|
void initWebUI()
|
||||||
{
|
{
|
||||||
|
// Attempt to mount LittleFS
|
||||||
if (!LittleFS.begin())
|
if (!LittleFS.begin())
|
||||||
{
|
{
|
||||||
Serial.println("An Error has occurred while mounting LittleFS");
|
Debug_pushMessage("An Error has occurred while mounting LittleFS\n");
|
||||||
|
MaintainDTC(DTC_FLASHFS_ERROR, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Retrieve the flash version
|
||||||
|
GetFlashVersion(globals.FlashVersion, sizeof(globals.FlashVersion));
|
||||||
|
|
||||||
|
// Compare the flash version with the required version
|
||||||
|
char buffer[6];
|
||||||
|
snprintf(buffer, sizeof(buffer), "%d.%02d", constants.Required_Flash_Version_major, constants.Required_Flash_Version_minor);
|
||||||
|
if (strcmp(globals.FlashVersion, buffer))
|
||||||
|
{
|
||||||
|
MaintainDTC(DTC_FLASHFS_VERSION_ERROR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize mDNS and add service
|
||||||
|
MDNS.begin(globals.DeviceName);
|
||||||
|
MDNS.addService("http", "tcp", 80);
|
||||||
|
|
||||||
|
// Set up WebSocket event handler and attach to web server
|
||||||
|
webSocket.onEvent(WebsocketEvent_Callback);
|
||||||
|
webServer.addHandler(&webSocket);
|
||||||
|
|
||||||
|
// Serve static files and define routes
|
||||||
webServer.serveStatic("/static/", LittleFS, "/static/").setCacheControl("max-age=360000");
|
webServer.serveStatic("/static/", LittleFS, "/static/").setCacheControl("max-age=360000");
|
||||||
|
webServer.serveStatic("/index.htm", LittleFS, "/index.htm").setCacheControl("max-age=360000");
|
||||||
webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
|
webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
|
||||||
{ request->redirect("/index.htm"); });
|
{ request->redirect("/index.htm"); });
|
||||||
webServer.onNotFound(WebserverNotFound_Callback);
|
webServer.onNotFound(WebserverNotFound_Callback);
|
||||||
webServer.on("/index.htm", HTTP_GET, Webserver_Callback);
|
webServer.on("/eejson", HTTP_GET, WebServerEEJSON_Callback);
|
||||||
webServer.on("/index.htm", HTTP_POST, WebserverPOST_Callback);
|
webServer.on(
|
||||||
|
"/doUpdate", HTTP_POST, [](AsyncWebServerRequest *request) {}, WebserverFirmwareUpdate_Callback);
|
||||||
|
webServer.on(
|
||||||
|
"/eeRestore", HTTP_POST, [](AsyncWebServerRequest *request) {}, WebserverEERestore_Callback);
|
||||||
|
|
||||||
|
// Start the web server
|
||||||
webServer.begin();
|
webServer.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
String processor(const String &var)
|
/**
|
||||||
|
* @brief Processes the web server functionality for the DE-Timer application.
|
||||||
|
*
|
||||||
|
* This function performs periodic processing tasks for the web server, including cleaning up
|
||||||
|
* WebSocket clients and refreshing client data when WebSocket connections are active. It ensures
|
||||||
|
* that WebSocket client data related to Diagnostic Trouble Codes (DTCs) and system status is
|
||||||
|
* updated at regular intervals.
|
||||||
|
*
|
||||||
|
* @note This function should be called in the main loop of the application.
|
||||||
|
*/
|
||||||
|
void Webserver_Process()
|
||||||
{
|
{
|
||||||
if (var == "SHOW_DTC_TABLE")
|
static uint32_t previousMillis = 0;
|
||||||
return globals.systemStatus == sysStat_Error ? "" : "hidden";
|
|
||||||
|
|
||||||
if (var == "SHOW_RESP_MESSAGE")
|
webSocket.cleanupClients();
|
||||||
return StatusResponseMessage_Type != RESPMSG_HIDE ? "" : "hidden";
|
|
||||||
|
|
||||||
if (var == "RESP_MESSAGE_TYPE")
|
if ((webSocket.count() > 0) && (millis() - previousMillis >= 10000))
|
||||||
{
|
{
|
||||||
switch (StatusResponseMessage_Type)
|
Websocket_RefreshClientData_DTCs(0);
|
||||||
{
|
Websocket_RefreshClientData_Status(0);
|
||||||
case RESPMSG_SUCCESS:
|
previousMillis = millis();
|
||||||
return "success";
|
|
||||||
case RESPMSG_INFO:
|
|
||||||
return "info";
|
|
||||||
case RESPMSG_WARNING:
|
|
||||||
return "warning";
|
|
||||||
case RESPMSG_DANGER:
|
|
||||||
return "danger";
|
|
||||||
default:
|
|
||||||
return "info";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (var == "RESP_MESSAGE")
|
|
||||||
return String(StatusResponseMessage);
|
|
||||||
|
|
||||||
if (var == "BAT_REMAIN_CAPACITY")
|
|
||||||
return String(globals.battery_level);
|
|
||||||
|
|
||||||
if (var == "DEVICE_NAME")
|
|
||||||
return String(globals.DeviceName);
|
|
||||||
|
|
||||||
if (var == "BAT_VOLTAGE")
|
|
||||||
return String(globals.loadvoltage);
|
|
||||||
|
|
||||||
if (var == "DTC_TABLE")
|
|
||||||
{
|
|
||||||
String temp;
|
|
||||||
char buff_timestamp[16]; // Format: DD-hh:mm:ss:xxx
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < MAX_DTC_STORAGE; i++)
|
|
||||||
{
|
|
||||||
if (DTCStorage[i].Number > 0)
|
|
||||||
{
|
|
||||||
sprintf(buff_timestamp, "%02d-%02d:%02d:%02d:%03d",
|
|
||||||
DTCStorage[i].timestamp / 86400000, // Days
|
|
||||||
DTCStorage[i].timestamp / 360000 % 24, // Hours
|
|
||||||
DTCStorage[i].timestamp / 60000 % 60, // Minutes
|
|
||||||
DTCStorage[i].timestamp / 1000 % 60, // Seconds
|
|
||||||
DTCStorage[i].timestamp % 1000); // milliseconds
|
|
||||||
|
|
||||||
temp = "<tr><td>" + String(buff_timestamp);
|
|
||||||
temp = temp + "</td><td>" + String(DTCStorage[i].Number) + "</td><td>";
|
|
||||||
|
|
||||||
if (DTCStorage[i].active == DTC_ACTIVE)
|
|
||||||
temp = temp + "active";
|
|
||||||
else if (DTCStorage[i].active == DTC_PREVIOUS)
|
|
||||||
temp = temp + "previous";
|
|
||||||
else
|
|
||||||
temp = temp + "none";
|
|
||||||
|
|
||||||
temp = temp + "</td></tr>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (var == "PLACEHOLDER")
|
|
||||||
return "placeholder";
|
|
||||||
|
|
||||||
if (var == "POINTS_FAC_1")
|
|
||||||
{
|
|
||||||
char buff[12];
|
|
||||||
snprintf(buff, 12, "%3d:%02d:%02d", PersistenceData.faction_1_timer / 3600, (PersistenceData.faction_1_timer / 60) % 60, PersistenceData.faction_1_timer % 60);
|
|
||||||
return String(buff);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (var == "POINTS_FAC_2")
|
|
||||||
{
|
|
||||||
char buff[12];
|
|
||||||
snprintf(buff, 12, "%3d:%02d:%02d", PersistenceData.faction_2_timer / 3600, (PersistenceData.faction_2_timer / 60) % 60, PersistenceData.faction_2_timer % 60);
|
|
||||||
return String(buff);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (var == "POINTS_FAC_3")
|
|
||||||
{
|
|
||||||
char buff[12];
|
|
||||||
snprintf(buff, 12, "%3d:%02d:%02d", PersistenceData.faction_3_timer / 3600, (PersistenceData.faction_3_timer / 60) % 60, PersistenceData.faction_3_timer % 60);
|
|
||||||
return String(buff);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (var == "STATUS_FAC_1")
|
|
||||||
return PersistenceData.activeFaction == FACTION_1 ? "ACTIVE" : "INACTIVE";
|
|
||||||
|
|
||||||
if (var == "STATUS_FAC_2")
|
|
||||||
return PersistenceData.activeFaction == FACTION_2 ? "ACTIVE" : "INACTIVE";
|
|
||||||
|
|
||||||
if (var == "STATUS_FAC_3")
|
|
||||||
return PersistenceData.activeFaction == FACTION_3 ? "ACTIVE" : "INACTIVE";
|
|
||||||
|
|
||||||
if (var == "NAME_FAC_1")
|
|
||||||
return FACTION_1_NAME;
|
|
||||||
|
|
||||||
if (var == "NAME_FAC_2")
|
|
||||||
return FACTION_2_NAME;
|
|
||||||
|
|
||||||
if (var == "NAME_FAC_3")
|
|
||||||
return FACTION_3_NAME;
|
|
||||||
|
|
||||||
if (var == "TITLE")
|
|
||||||
return DEVICE_NAME;
|
|
||||||
|
|
||||||
if (var == "BATTERY_LEVEL")
|
|
||||||
{
|
|
||||||
return String(globals.battery_level);
|
|
||||||
}
|
|
||||||
if (var == "BATTERY_TYPE")
|
|
||||||
{
|
|
||||||
return String(BatteryString[ConfigData.batteryType]);
|
|
||||||
}
|
|
||||||
if (var == "BATTERY_VOLTAGE")
|
|
||||||
{
|
|
||||||
return String(globals.loadvoltage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return String();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Webserver_Callback(AsyncWebServerRequest *request)
|
/**
|
||||||
|
* @brief Shuts down the web server functionality for the DE-Timer application.
|
||||||
|
*
|
||||||
|
* This function closes all WebSocket connections and terminates the web server. It is intended
|
||||||
|
* to be called when the application is being shut down or when there is a need to deactivate the
|
||||||
|
* web server.
|
||||||
|
*
|
||||||
|
* @details This function ensures a graceful shutdown of the web server by closing all active
|
||||||
|
* WebSocket connections and ending the web server instance.
|
||||||
|
*
|
||||||
|
* @note This function should be called before shutting down the application to properly
|
||||||
|
* deactivate the web server.
|
||||||
|
*/
|
||||||
|
void Webserver_Shutdown()
|
||||||
{
|
{
|
||||||
request->send(LittleFS, "/index.htm", "text/html", false, processor);
|
if (webSocket.count() > 0)
|
||||||
StatusResponseMessage_Type = RESPMSG_HIDE;
|
webSocket.closeAll();
|
||||||
}
|
webServer.end();
|
||||||
|
|
||||||
void WebserverPOST_Callback(AsyncWebServerRequest *request)
|
|
||||||
{
|
|
||||||
int paramsNr = request->params();
|
|
||||||
for (int i = 0; i < paramsNr; i++)
|
|
||||||
{
|
|
||||||
AsyncWebParameter *p = request->getParam(i);
|
|
||||||
if (p->name() == "commandInput")
|
|
||||||
WebserverCommands_Callback(p->value());
|
|
||||||
}
|
|
||||||
request->send(LittleFS, "/index.htm", "text/html", false, processor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function for handling HTTP 404 (Not Found) errors on the web server.
|
||||||
|
*
|
||||||
|
* This function is invoked when an HTTP request results in a 404 error (Not Found). It sends
|
||||||
|
* a simple "Not found" text response with an HTTP status code of 404.
|
||||||
|
*
|
||||||
|
* @param request Pointer to the AsyncWebServerRequest object representing the HTTP request.
|
||||||
|
*/
|
||||||
void WebserverNotFound_Callback(AsyncWebServerRequest *request)
|
void WebserverNotFound_Callback(AsyncWebServerRequest *request)
|
||||||
{
|
{
|
||||||
request->send(404, "text/html", "Not found");
|
request->send(404, "text/html", "Not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebserverCommands_Callback(String input)
|
/**
|
||||||
|
* @brief Reads the flash version information from a file in LittleFS.
|
||||||
|
*
|
||||||
|
* This function reads the flash version information stored in a file named "version" in the
|
||||||
|
* LittleFS filesystem. It opens the file, reads the content until a carriage return ('\r') is
|
||||||
|
* encountered, and stores the result in the provided buffer. The buffer is null-terminated.
|
||||||
|
*
|
||||||
|
* @param buff Pointer to the buffer where the flash version information will be stored.
|
||||||
|
* @param buff_size Size of the buffer.
|
||||||
|
*/
|
||||||
|
void GetFlashVersion(char *buff, size_t buff_size)
|
||||||
{
|
{
|
||||||
String command = input.substring(0, input.indexOf(' '));
|
File this_file = LittleFS.open("version", "r");
|
||||||
command.toUpperCase();
|
if (!this_file)
|
||||||
StatusResponseMessage_Type = RESPMSG_HIDE;
|
{ // failed to open the file, retrn empty result
|
||||||
|
buff[0] = '\0';
|
||||||
if (command == "RESET")
|
return;
|
||||||
|
}
|
||||||
|
if (this_file.available())
|
||||||
{
|
{
|
||||||
strcpy(StatusResponseMessage, "Counter Reset done");
|
int bytes_read;
|
||||||
StatusResponseMessage_Type = RESPMSG_SUCCESS;
|
bytes_read = this_file.readBytesUntil('\r', buff, buff_size - 1);
|
||||||
|
buff[bytes_read] = '\0';
|
||||||
|
}
|
||||||
|
this_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function for handling firmware updates via the web server.
|
||||||
|
*
|
||||||
|
* This function is invoked during the firmware update process when a new firmware file
|
||||||
|
* is received. It handles the update process using the ESPAsyncHTTPUpdate library. The update
|
||||||
|
* process involves checking the firmware type, initializing the update, writing data, and finalizing
|
||||||
|
* the update. If the update is successful, it triggers a system shutdown.
|
||||||
|
*
|
||||||
|
* @param request Pointer to the AsyncWebServerRequest object.
|
||||||
|
* @param filename The name of the file being updated.
|
||||||
|
* @param index The index of the file being updated.
|
||||||
|
* @param data Pointer to the data buffer.
|
||||||
|
* @param len The length of the data buffer.
|
||||||
|
* @param final Boolean indicating if this is the final chunk of data.
|
||||||
|
*/
|
||||||
|
void WebserverFirmwareUpdate_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!index)
|
||||||
|
{
|
||||||
|
Debug_pushMessage("Update\n");
|
||||||
|
size_t content_len = request->contentLength();
|
||||||
|
int cmd = (filename.indexOf(".fs") > -1) ? U_FS : U_FLASH;
|
||||||
|
Update.runAsync(true);
|
||||||
|
if (!Update.begin(content_len, cmd))
|
||||||
|
{
|
||||||
|
Update.printError(Serial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Update.write(data, len) != len)
|
||||||
|
{
|
||||||
|
Update.printError(Serial);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug_pushMessage("Progress: %d%%\n", (Update.progress() * 100) / Update.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (final)
|
||||||
|
{
|
||||||
|
AsyncWebServerResponse *response = request->beginResponse(302, "text/plain", "Please wait while the device reboots");
|
||||||
|
response->addHeader("Refresh", "20");
|
||||||
|
response->addHeader("Location", "/");
|
||||||
|
request->send(response);
|
||||||
|
if (!Update.end(true))
|
||||||
|
{
|
||||||
|
Update.printError(Serial);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug_pushMessage("Update complete\n");
|
||||||
|
globals.systemStatus = sysStat_Shutdown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function for handling EEPROM restore via the web server.
|
||||||
|
*
|
||||||
|
* This function is invoked during the EEPROM restore process when a new EEPROM file
|
||||||
|
* is received. It handles the restore process by reading the data from the received file,
|
||||||
|
* deserializing the JSON data, and updating the configuration and persistence data accordingly.
|
||||||
|
* If the restore is successful, it triggers a system shutdown.
|
||||||
|
*
|
||||||
|
* @param request Pointer to the AsyncWebServerRequest object.
|
||||||
|
* @param filename The name of the file being restored.
|
||||||
|
* @param index The index of the file being restored.
|
||||||
|
* @param data Pointer to the data buffer.
|
||||||
|
* @param len The length of the data buffer.
|
||||||
|
* @param final Boolean indicating if this is the final chunk of data.
|
||||||
|
*/
|
||||||
|
void WebserverEERestore_Callback(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final)
|
||||||
|
{
|
||||||
|
bool ee_done = false;
|
||||||
|
static bool validext = false;
|
||||||
|
static char *buffer = NULL;
|
||||||
|
static uint32_t read_ptr = 0;
|
||||||
|
DeserializationError error;
|
||||||
|
|
||||||
|
if (!index)
|
||||||
|
{
|
||||||
|
validext = (filename.indexOf(".ee.json") > -1);
|
||||||
|
if (validext)
|
||||||
|
{
|
||||||
|
buffer = (char *)malloc(1536);
|
||||||
|
read_ptr = 0;
|
||||||
|
if (buffer == NULL)
|
||||||
|
Debug_pushMessage("malloc() failed for EEPROM-Restore\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer != NULL)
|
||||||
|
{
|
||||||
|
memcpy(buffer + read_ptr, data, len);
|
||||||
|
read_ptr = read_ptr + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (final)
|
||||||
|
{
|
||||||
|
if (buffer != NULL)
|
||||||
|
{
|
||||||
|
Serial.print(buffer);
|
||||||
|
JsonDocument json;
|
||||||
|
error = deserializeJson(json, buffer);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
Debug_pushMessage("deserializeJson() failed: %s\n", error.f_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
ConfigData.batteryType = (batteryType_t)json["config"]["batteryType"].as<int>();
|
||||||
|
ConfigData.active_faction_on_reboot = json["config"]["active_faction_on_reboot"].as<bool>();
|
||||||
|
strncpy(ConfigData.Faction_1_Name, json["config"]["Faction_1_Name"].as<const char *>(), sizeof(ConfigData.Faction_1_Name));
|
||||||
|
strncpy(ConfigData.Faction_2_Name, json["config"]["Faction_2_Name"].as<const char *>(), sizeof(ConfigData.Faction_2_Name));
|
||||||
|
strncpy(ConfigData.Faction_3_Name, json["config"]["Faction_3_Name"].as<const char *>(), sizeof(ConfigData.Faction_3_Name));
|
||||||
|
strncpy(ConfigData.wifi_ap_ssid, json["config"]["wifi_ap_ssid"].as<const char *>(), sizeof(ConfigData.wifi_ap_ssid));
|
||||||
|
strncpy(ConfigData.wifi_ap_password, json["config"]["wifi_ap_password"].as<const char *>(), sizeof(ConfigData.wifi_ap_password));
|
||||||
|
strncpy(ConfigData.wifi_client_ssid, json["config"]["wifi_client_ssid"].as<const char *>(), sizeof(ConfigData.wifi_client_ssid));
|
||||||
|
strncpy(ConfigData.wifi_client_password, json["config"]["wifi_client_password"].as<const char *>(), sizeof(ConfigData.wifi_client_password));
|
||||||
|
|
||||||
|
PersistenceData.writeCycleCounter = json["persis"]["writeCycleCounter"].as<uint16_t>();
|
||||||
|
PersistenceData.activeFaction = (Factions_t)json["persis"]["activeFaction"].as<int>();
|
||||||
|
PersistenceData.faction_1_timer = json["persis"]["faction_1_timer"].as<uint32_t>();
|
||||||
|
PersistenceData.faction_2_timer = json["persis"]["faction_2_timer"].as<uint32_t>();
|
||||||
|
PersistenceData.faction_3_timer = json["persis"]["faction_3_timer"].as<uint32_t>();
|
||||||
|
PersistenceData.checksum = json["persis"]["checksum"].as<uint32_t>();
|
||||||
|
|
||||||
|
ee_done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
AsyncWebServerResponse *response = request->beginResponse(302, "text/plain", "Please wait while the device reboots");
|
||||||
|
response->addHeader("Refresh", "20");
|
||||||
|
response->addHeader("Location", "/");
|
||||||
|
request->send(response);
|
||||||
|
|
||||||
|
if (ee_done)
|
||||||
|
{
|
||||||
|
Debug_pushMessage("Update complete\n");
|
||||||
|
globals.systemStatus = sysStat_Shutdown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function for handling EEPROM JSON request via the web server.
|
||||||
|
*
|
||||||
|
* This function is invoked when a request for EEPROM JSON data is received. It constructs a JSON
|
||||||
|
* response containing information about the firmware, configuration, and persistence data.
|
||||||
|
*
|
||||||
|
* @param request Pointer to the AsyncWebServerRequest object.
|
||||||
|
*/
|
||||||
|
void WebServerEEJSON_Callback(AsyncWebServerRequest *request)
|
||||||
|
{
|
||||||
|
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||||
|
JsonDocument json;
|
||||||
|
JsonObject info = json["info"].to<JsonObject>();
|
||||||
|
|
||||||
|
char buffer[16];
|
||||||
|
|
||||||
|
info["DeviceName"] = globals.DeviceName;
|
||||||
|
sprintf(buffer, "%d.%02d", constants.Required_Flash_Version_major, constants.Required_Flash_Version_minor);
|
||||||
|
info["FW-Version"] = buffer;
|
||||||
|
info["FS-Version"] = globals.FlashVersion;
|
||||||
|
snprintf_P(buffer, sizeof(buffer), "%s", constants.GitHash);
|
||||||
|
info["Git-Hash"] = buffer;
|
||||||
|
|
||||||
|
JsonObject config = json["config"].to<JsonObject>();
|
||||||
|
generateJsonObject_ConfigData(config);
|
||||||
|
JsonObject persis = json["persis"].to<JsonObject>();
|
||||||
|
generateJsonObject_PersistenceData(persis);
|
||||||
|
|
||||||
|
JsonObject eepart = json["eepart"].to<JsonObject>();
|
||||||
|
sprintf(buffer, "0x%04X", globals.eePersistanceAdress);
|
||||||
|
eepart["PersistanceAddress"] = buffer;
|
||||||
|
|
||||||
|
serializeJsonPretty(json, *response);
|
||||||
|
|
||||||
|
response->addHeader("Content-disposition", "attachment; filename=backup.ee.json");
|
||||||
|
|
||||||
|
request->send(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function for handling WebSocket events.
|
||||||
|
*
|
||||||
|
* This function is invoked when events occur in the WebSocket communication, such as client connection,
|
||||||
|
* disconnection, reception of data, and others. It dispatches the events to the appropriate handlers.
|
||||||
|
*
|
||||||
|
* @param server Pointer to the AsyncWebSocket object.
|
||||||
|
* @param client Pointer to the AsyncWebSocketClient object representing the WebSocket client.
|
||||||
|
* @param type Type of WebSocket event.
|
||||||
|
* @param arg Event-specific argument.
|
||||||
|
* @param data Pointer to the received data (if applicable).
|
||||||
|
* @param len Length of the received data.
|
||||||
|
*/
|
||||||
|
void WebsocketEvent_Callback(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case WS_EVT_CONNECT:
|
||||||
|
Debug_pushMessage("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
|
||||||
|
Websocket_RefreshClientData_Status(client->id(), true);
|
||||||
|
Websocket_RefreshClientData_Static(client->id(), true);
|
||||||
|
Websocket_RefreshClientData_DTCs(client->id());
|
||||||
|
break;
|
||||||
|
case WS_EVT_DISCONNECT:
|
||||||
|
Debug_pushMessage("WebSocket client #%u disconnected\n", client->id());
|
||||||
|
break;
|
||||||
|
case WS_EVT_DATA:
|
||||||
|
Websocket_HandleMessage(arg, data, len);
|
||||||
|
break;
|
||||||
|
case WS_EVT_PONG:
|
||||||
|
case WS_EVT_ERROR:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handles WebSocket messages received from clients.
|
||||||
|
*
|
||||||
|
* This function processes WebSocket messages, such as starting or stopping debugging,
|
||||||
|
* and provides appropriate responses.
|
||||||
|
*
|
||||||
|
* @param arg Pointer to the WebSocket frame information.
|
||||||
|
* @param data Pointer to the received data.
|
||||||
|
* @param len Length of the received data.
|
||||||
|
*/
|
||||||
|
void Websocket_HandleMessage(void *arg, uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
AwsFrameInfo *info = (AwsFrameInfo *)arg;
|
||||||
|
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT)
|
||||||
|
{
|
||||||
|
data[len] = 0;
|
||||||
|
Debug_pushMessage("Websocket-Message (len: %d): %s\n", len, (char *)data);
|
||||||
|
|
||||||
|
if (strncmp((char *)data, "btn-", strlen("btn-")) == 0)
|
||||||
|
{
|
||||||
|
Websocket_HandleButtons(data + strlen("btn-"));
|
||||||
|
}
|
||||||
|
else if (strncmp((char *)data, "set-", strlen("set-")) == 0)
|
||||||
|
{
|
||||||
|
Websocket_HandleSettings(data + strlen("set-"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug_pushMessage("Got unknown Websocket-Message '%s' from client\n", (char *)data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle button commands received via WebSocket.
|
||||||
|
*
|
||||||
|
* This function parses a WebSocket string representing button commands, extracts
|
||||||
|
* the identifier and value components, and performs corresponding actions based on
|
||||||
|
* the received commands.
|
||||||
|
*
|
||||||
|
* @param data The WebSocket data containing button commands.
|
||||||
|
*/
|
||||||
|
void Websocket_HandleButtons(uint8_t *data)
|
||||||
|
{
|
||||||
|
char identifier[32];
|
||||||
|
char value[32];
|
||||||
|
|
||||||
|
parseWebsocketString((char *)data, identifier, sizeof(identifier), value, sizeof(value));
|
||||||
|
if (strcmp(identifier, "reset-timer") == 0)
|
||||||
|
{
|
||||||
|
PersistenceData.activeFaction = NONE;
|
||||||
PersistenceData.faction_1_timer = 0;
|
PersistenceData.faction_1_timer = 0;
|
||||||
PersistenceData.faction_2_timer = 0;
|
PersistenceData.faction_2_timer = 0;
|
||||||
PersistenceData.faction_3_timer = 0;
|
PersistenceData.faction_3_timer = 0;
|
||||||
PersistenceData.activeFaction = NONE;
|
|
||||||
}
|
}
|
||||||
|
else if (strcmp(identifier, "debugstart") == 0)
|
||||||
|
{
|
||||||
|
SetDebugportStatus(dbg_Webui, enabled);
|
||||||
|
}
|
||||||
|
else if (strcmp(identifier, "debugstop") == 0)
|
||||||
|
{
|
||||||
|
SetDebugportStatus(dbg_Webui, disabled);
|
||||||
|
}
|
||||||
|
else if (strcmp(identifier, "settingssave") == 0)
|
||||||
|
{
|
||||||
|
ConfigData.batteryType = batterytypePreselect;
|
||||||
|
globals.requestEEAction = EE_CFG_SAVE;
|
||||||
|
}
|
||||||
|
else if (strcmp(identifier, "reboot") == 0)
|
||||||
|
{
|
||||||
|
globals.systemStatus = sysStat_Shutdown;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug_pushMessage("Got unknown Button-id '%s' from ws-client\n", identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle settings commands received via WebSocket.
|
||||||
|
*
|
||||||
|
* This function parses a WebSocket string representing settings commands, extracts
|
||||||
|
* the identifier and value components, and updates the system settings accordingly.
|
||||||
|
*
|
||||||
|
* @param data The WebSocket data containing settings commands.
|
||||||
|
*/
|
||||||
|
void Websocket_HandleSettings(uint8_t *data)
|
||||||
|
{
|
||||||
|
char identifier[32];
|
||||||
|
char value[63];
|
||||||
|
|
||||||
|
parseWebsocketString((char *)data, identifier, sizeof(identifier), value, sizeof(value));
|
||||||
|
|
||||||
|
if (strcmp(identifier, "active_faction_on_reboot") == 0)
|
||||||
|
{
|
||||||
|
ConfigData.active_faction_on_reboot = value[0] == '1' ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (strcmp(identifier, "name_faction1") == 0)
|
||||||
|
{
|
||||||
|
strncpy(ConfigData.Faction_1_Name, value, sizeof(ConfigData.Faction_1_Name));
|
||||||
|
}
|
||||||
|
else if (strcmp(identifier, "name_faction2") == 0)
|
||||||
|
{
|
||||||
|
strncpy(ConfigData.Faction_2_Name, value, sizeof(ConfigData.Faction_2_Name));
|
||||||
|
}
|
||||||
|
else if (strcmp(identifier, "name_faction3") == 0)
|
||||||
|
{
|
||||||
|
strncpy(ConfigData.Faction_3_Name, value, sizeof(ConfigData.Faction_3_Name));
|
||||||
|
}
|
||||||
|
else if (strcmp(identifier, "batterytype") == 0)
|
||||||
|
{
|
||||||
|
strncpy(ConfigData.wifi_client_ssid, value, sizeof(ConfigData.wifi_client_ssid));
|
||||||
|
}
|
||||||
|
else if (strcmp(identifier, "batterytype") == 0)
|
||||||
|
{
|
||||||
|
int index = findIndexByString(value, BatteryString, BatteryString_Elements);
|
||||||
|
batterytypePreselect = (batteryType_t)index;
|
||||||
|
}
|
||||||
|
else if (strcmp(identifier, "wifi-ssid") == 0)
|
||||||
|
{
|
||||||
|
strncpy(ConfigData.wifi_client_ssid, value, sizeof(ConfigData.wifi_client_ssid));
|
||||||
|
}
|
||||||
|
else if (strcmp(identifier, "wifi-password") == 0)
|
||||||
|
{
|
||||||
|
strncpy(ConfigData.wifi_client_password, value, sizeof(ConfigData.wifi_client_password));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug_pushMessage("Got unknown Settings-id and value '%s' from ws-client\n", identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pushes live debug messages to all WebSocket clients.
|
||||||
|
*
|
||||||
|
* This function sends a live debug message to all connected WebSocket clients.
|
||||||
|
*
|
||||||
|
* @param Message The debug message to be sent.
|
||||||
|
*/
|
||||||
|
void Websocket_PushLiveDebug(String Message)
|
||||||
|
{
|
||||||
|
webSocket.textAll("DEBUG:" + Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Refreshes client data related to Diagnostic Trouble Codes (DTCs) on WebSocket clients.
|
||||||
|
*
|
||||||
|
* This function constructs a DTC-related string and sends it to a specific WebSocket client or
|
||||||
|
* broadcasts it to all connected WebSocket clients.
|
||||||
|
*
|
||||||
|
* @param client_id The ID of the WebSocket client to which the data should be sent. If 0, the data
|
||||||
|
* will be broadcasted to all connected clients.
|
||||||
|
*/
|
||||||
|
void Websocket_RefreshClientData_DTCs(uint32_t client_id)
|
||||||
|
{
|
||||||
|
String temp = "DTC:";
|
||||||
|
|
||||||
|
// Build DTC-String
|
||||||
|
if (globals.hasDTC != true)
|
||||||
|
{
|
||||||
|
temp.concat(String(DTC_NO_DTC) + ";");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < MAX_DTC_STORAGE; i++)
|
||||||
|
{
|
||||||
|
if (DTCStorage[i].Number < DTC_LAST_DTC)
|
||||||
|
{
|
||||||
|
temp.concat(String(DTCStorage[i].timestamp) + ",");
|
||||||
|
temp.concat(String(DTCStorage[i].Number) + ",");
|
||||||
|
temp.concat(String(getSeverityForDTC(DTCStorage[i].Number)) + ",");
|
||||||
|
temp.concat(String(DTCStorage[i].active) + ",");
|
||||||
|
temp.concat(String(DTCStorage[i].debugVal) + ";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (client_id > 0)
|
||||||
|
{
|
||||||
|
webSocket.text(client_id, temp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
webSocket.textAll(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Refreshes client data related to system status and relevant parameters on WebSocket clients.
|
||||||
|
*
|
||||||
|
* This function constructs a status-related string and sends it to a specific WebSocket client or
|
||||||
|
* broadcasts it to all connected WebSocket clients. It also sends a mapping of the status parameters.
|
||||||
|
*
|
||||||
|
* @param client_id The ID of the WebSocket client to which the data should be sent. If 0, the data
|
||||||
|
* will be broadcasted to all connected clients.
|
||||||
|
* @param send_mapping Flag indicating whether to send the parameter mapping to the client(s).
|
||||||
|
*/
|
||||||
|
void Websocket_RefreshClientData_Status(uint32_t client_id, bool send_mapping)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (send_mapping)
|
||||||
|
{
|
||||||
|
const char mapping[] = "MAPPING_STATUS:"
|
||||||
|
"batterylevel;"
|
||||||
|
"systemstatus;"
|
||||||
|
"activefaction;"
|
||||||
|
"time_faction1;"
|
||||||
|
"time_faction2;"
|
||||||
|
"time_faction3;";
|
||||||
|
|
||||||
|
if (client_id > 0)
|
||||||
|
webSocket.text(client_id, mapping);
|
||||||
|
else
|
||||||
|
webSocket.textAll(mapping);
|
||||||
|
|
||||||
|
Debug_pushMessage("send MAPPING_STATUS WS-Client Data\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
String temp = "STATUS:";
|
||||||
|
|
||||||
|
temp.concat(String(globals.battery_level) + ";");
|
||||||
|
temp.concat(String(globals.systemStatustxt) + ";");
|
||||||
|
temp.concat(String(PersistenceData.activeFaction) + ";");
|
||||||
|
temp.concat(String(PersistenceData.faction_1_timer) + ";");
|
||||||
|
temp.concat(String(PersistenceData.faction_2_timer) + ";");
|
||||||
|
temp.concat(String(PersistenceData.faction_3_timer) + ";");
|
||||||
|
|
||||||
|
if (client_id > 0)
|
||||||
|
{
|
||||||
|
webSocket.text(client_id, temp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
webSocket.textAll(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Refreshes client data related to static configuration parameters on WebSocket clients.
|
||||||
|
*
|
||||||
|
* This function constructs a static configuration-related string and sends it to a specific WebSocket client or
|
||||||
|
* broadcasts it to all connected WebSocket clients. It also sends a mapping of the static configuration parameters.
|
||||||
|
*
|
||||||
|
* @param client_id The ID of the WebSocket client to which the data should be sent. If 0, the data
|
||||||
|
* will be broadcasted to all connected clients.
|
||||||
|
* @param send_mapping Flag indicating whether to send the parameter mapping to the client(s).
|
||||||
|
*/
|
||||||
|
void Websocket_RefreshClientData_Static(uint32_t client_id, bool send_mapping)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (send_mapping)
|
||||||
|
{
|
||||||
|
const char mapping[] = "MAPPING_STATIC:"
|
||||||
|
"active_faction_on_reboot;"
|
||||||
|
"batteryType;"
|
||||||
|
"name_faction1;"
|
||||||
|
"name_faction2;"
|
||||||
|
"name_faction3;"
|
||||||
|
"wifi-ssid;"
|
||||||
|
"wifi-pass;";
|
||||||
|
|
||||||
|
if (client_id > 0)
|
||||||
|
webSocket.text(client_id, mapping);
|
||||||
|
else
|
||||||
|
webSocket.textAll(mapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
String temp = "STATIC:";
|
||||||
|
|
||||||
|
temp.concat(String(ConfigData.active_faction_on_reboot) + ";");
|
||||||
|
temp.concat(String(ConfigData.batteryType) + ";");
|
||||||
|
temp.concat(String(ConfigData.Faction_1_Name) + ";");
|
||||||
|
temp.concat(String(ConfigData.Faction_2_Name) + ";");
|
||||||
|
temp.concat(String(ConfigData.Faction_3_Name) + ";");
|
||||||
|
temp.concat(String(ConfigData.wifi_client_ssid) + ";");
|
||||||
|
temp.concat(String(ConfigData.wifi_client_password) + ";");
|
||||||
|
|
||||||
|
if (client_id > 0)
|
||||||
|
{
|
||||||
|
webSocket.text(client_id, temp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
webSocket.textAll(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parse a WebSocket string into identifier and value components.
|
||||||
|
*
|
||||||
|
* This function takes a WebSocket string, separates it into identifier and value
|
||||||
|
* components using the ":" delimiter, and stores them in the specified buffers.
|
||||||
|
* If no ":" is found, the entire string is considered as the value, and the
|
||||||
|
* identifier buffer is set to an empty string.
|
||||||
|
*
|
||||||
|
* @param data The WebSocket string to parse.
|
||||||
|
* @param identifierBuffer The buffer to store the identifier component.
|
||||||
|
* @param identifierBufferSize The size of the identifier buffer.
|
||||||
|
* @param valueBuffer The buffer to store the value component.
|
||||||
|
* @param valueBufferSize The size of the value buffer.
|
||||||
|
*/
|
||||||
|
void parseWebsocketString(char *data, char *identifierBuffer, size_t identifierBufferSize,
|
||||||
|
char *valueBuffer, size_t valueBufferSize)
|
||||||
|
{
|
||||||
|
// Zerlegen des Strings anhand des Trennzeichens ":"
|
||||||
|
char *token = strtok(data, ":");
|
||||||
|
|
||||||
|
// Falls der erste Teil des Strings vorhanden ist
|
||||||
|
if (token != NULL)
|
||||||
|
{
|
||||||
|
// Kopieren des ersten Teils in den Buffer für Identifier
|
||||||
|
strncpy(identifierBuffer, token, identifierBufferSize - 1);
|
||||||
|
identifierBuffer[identifierBufferSize - 1] = '\0'; // Null-Terminierung sicherstellen
|
||||||
|
|
||||||
|
// Weitere Aufrufe von strtok, um den nächsten Teil zu erhalten
|
||||||
|
token = strtok(NULL, ":");
|
||||||
|
|
||||||
|
// Falls der zweite Teil des Strings vorhanden ist
|
||||||
|
if (token != NULL)
|
||||||
|
{
|
||||||
|
// Kopieren des zweiten Teils in den Buffer für Value
|
||||||
|
strncpy(valueBuffer, token, valueBufferSize - 1);
|
||||||
|
valueBuffer[valueBufferSize - 1] = '\0'; // Null-Terminierung sicherstellen
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Kein zweiter Teil vorhanden, setzen Sie den Buffer für Value auf leer
|
||||||
|
valueBuffer[0] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Der erste Teil des Strings fehlt, setzen Sie den Buffer für Identifier auf leer
|
||||||
|
identifierBuffer[0] = '\0';
|
||||||
|
|
||||||
|
// Der gesamte String wird als Value betrachtet
|
||||||
|
strncpy(valueBuffer, data, valueBufferSize - 1);
|
||||||
|
valueBuffer[valueBufferSize - 1] = '\0'; // Null-Terminierung sicherstellen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find the index of a string in an array.
|
||||||
|
*
|
||||||
|
* This function searches for the given string in the provided array and returns
|
||||||
|
* the index of the first occurrence. If the string is not found, it returns -1.
|
||||||
|
*
|
||||||
|
* @param searchString The string to search for in the array.
|
||||||
|
* @param array The array of strings to search within.
|
||||||
|
* @param arraySize The size of the array.
|
||||||
|
*
|
||||||
|
* @return The index of the first occurrence of the string in the array,
|
||||||
|
* or -1 if the string is not found.
|
||||||
|
*/
|
||||||
|
int findIndexByString(const char *searchString, const char *const *array, int arraySize)
|
||||||
|
{
|
||||||
|
// Durchlaufe das Array und vergleiche jeden String
|
||||||
|
for (int i = 0; i < arraySize; ++i)
|
||||||
|
{
|
||||||
|
if (strcmp(array[i], searchString) == 0)
|
||||||
|
{
|
||||||
|
// String gefunden, gib den Index zurück
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// String nicht gefunden, gib -1 zurück
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pushes a notification to all WebSocket clients.
|
||||||
|
*
|
||||||
|
* This function sends a live debug message to all connected WebSocket clients.
|
||||||
|
*
|
||||||
|
* @param Message The debug message to be sent.
|
||||||
|
* @param type The type of notification (info, success, warning, error).
|
||||||
|
* - Use NotificationType_t::info for informational messages.
|
||||||
|
* - Use NotificationType_t::success for successful operation messages.
|
||||||
|
* - Use NotificationType_t::warning for warning messages.
|
||||||
|
* - Use NotificationType_t::error for error messages.
|
||||||
|
*/
|
||||||
|
void Websocket_PushNotification(String Message, NotificationType_t type)
|
||||||
|
{
|
||||||
|
String typeString = "";
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case info:
|
||||||
|
typeString = "info";
|
||||||
|
break;
|
||||||
|
case success:
|
||||||
|
typeString = "success";
|
||||||
|
break;
|
||||||
|
case warning:
|
||||||
|
typeString = "warning";
|
||||||
|
break;
|
||||||
|
case error:
|
||||||
|
typeString = "danger";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
webSocket.textAll("NOTIFY:" + typeString + ";" + Message);
|
||||||
|
Debug_pushMessage("Sending Notification to WebUI: %s\n", typeString);
|
||||||
}
|
}
|
@@ -1,15 +0,0 @@
|
|||||||
#ifndef _WEBUI_H_
|
|
||||||
#define _WEBUI_H_
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <FS.h>
|
|
||||||
#include <LittleFS.h>
|
|
||||||
#include <AsyncTCP.h>
|
|
||||||
#include <ESPAsyncWebServer.h>
|
|
||||||
#include "config.h"
|
|
||||||
#include "globals.h"
|
|
||||||
#include "dtc.h"
|
|
||||||
|
|
||||||
void initWebUI();
|
|
||||||
|
|
||||||
#endif
|
|