Compare commits

..

379 Commits

Author SHA1 Message Date
richonguzman
3c27e52df7 readme update for T3S3 2024-10-29 10:13:23 -03:00
richonguzman
3d5f3a4914 add Lilygo T3S3 2024-10-29 09:57:26 -03:00
richonguzman
db6292ce59 added but reboots 2024-10-28 09:33:27 -03:00
richonguzman
7995d23779 cleaned 2024-10-25 15:56:03 -03:00
richonguzman
7f150bc4a0 minor letter fix 2024-10-25 15:22:24 -03:00
richonguzman
ff5650f0c5 readme and build update 2024-10-25 12:50:15 -03:00
richonguzman
a91f0f3f3c WIRE update 2024-10-25 11:50:57 -03:00
richonguzman
c9577b6c21 more display testing 2024-10-25 11:08:00 -03:00
richonguzman
10cb7c6e45 added LightGateway 2024-10-25 10:42:15 -03:00
richonguzman
99052e594a typo fix 2024-10-23 12:09:24 -03:00
richonguzman
a05917c494 update 2024-10-22 22:14:29 -03:00
richonguzman
e2e935797f images update for V2.1 2024-10-21 12:26:40 -03:00
richonguzman
5ceff0064f small update to avoid sending gps = 0 2024-10-21 11:16:31 -03:00
richonguzman
8beb7c0465 readme update 2024-10-21 09:09:47 -03:00
richonguzman
112e38312d codingRate4 = 4 does not exists 2024-10-21 09:08:53 -03:00
richonguzman
5a1c6e7ed9 testing GPS 2024-10-21 08:28:35 -03:00
richonguzman
0defd5b289 added HWT with GPS 2024-10-14 17:48:14 -03:00
richonguzman
cdac54c34e cleaning code 2024-10-14 17:44:01 -03:00
richonguzman
71e98487f6 readme and index update 2024-10-14 17:23:42 -03:00
richonguzman
510b5bdc59 index reads better 2024-10-14 17:15:56 -03:00
richonguzman
00db358cc3 GPS for iGate 2024-10-14 17:04:28 -03:00
richonguzman
c0641986aa RxPacket freeze fix 2024-10-14 12:49:01 -03:00
richonguzman
55378bb9f3 readme Update for NTP update 2024-10-14 11:56:48 -03:00
richonguzman
79cf50a630 NTP time added 2024-10-14 11:44:22 -03:00
richonguzman
03ccd2b12e r up 2024-10-11 07:16:44 -03:00
richonguzman
d5ffd26c3c double validation for DigiEcoMode start stop 2024-10-10 18:45:12 -03:00
richonguzman
2f0f991785 readme2 2024-10-09 11:46:45 -03:00
richonguzman
975b140c73 readme1 2024-10-09 11:45:01 -03:00
richonguzman
f2abe34af1 readme Update Digi Eco Mode 2024-10-08 12:25:09 -03:00
richonguzman
a786d83b9e Queries for DigiEcoMode 2024-10-08 12:19:22 -03:00
richonguzman
bf0a0d6e4c EcoMode Digi 2024-10-08 11:04:36 -03:00
richonguzman
d08e5b1b27 ready for testing LowPowerDigi 2024-10-08 01:22:10 -03:00
richonguzman
f387e03b53 testing LowPowerDigi 2024-10-08 01:03:58 -03:00
richonguzman
16215f9e56 minor update for Internal Battery Sleep 2024-10-07 11:10:19 -03:00
richonguzman
ce01d0aa4d minor white spaces kill 2024-10-07 09:39:31 -03:00
richonguzman
b0a05f89f6 readme update 2024-10-06 23:35:51 -03:00
richonguzman
58d8736969 test for Killed Wifi Active 2024-10-06 23:23:22 -03:00
richonguzman
df9060d906 testing not active 2024-10-06 23:02:10 -03:00
richonguzman
2bd6844d89 WiFiAP Active switch added 2024-10-06 22:59:58 -03:00
richonguzman
0a79b6459b added initial corrections to WiFiAP 2024-10-06 22:30:44 -03:00
richonguzman
d5eb32a38b cross digi rules added 2024-10-06 11:37:25 -03:00
richonguzman
d6c5741fde cross digi added 2024-10-06 11:36:37 -03:00
richonguzman
1063a82294 se viene thirdParty 2024-10-05 20:25:29 -03:00
richonguzman
6913b6b89f ahora a probar thirdParty 2024-10-05 20:23:58 -03:00
richonguzman
42c990f5cf !thirdParty con o sin path 2024-10-05 20:21:36 -03:00
richonguzman
a17900e4d0 bme into wxsensor 2024-10-05 08:48:08 -03:00
richonguzman
3fd819bd4e not encoded telemetry as default 2024-09-25 11:23:38 -03:00
richonguzman
640166a50b update for wiki 2024-09-23 17:41:05 -03:00
richonguzman
a9bcae62e2 readme update 2024-09-23 15:15:22 -03:00
richonguzman
3e0368383a better writting 2024-09-23 15:11:35 -03:00
richonguzman
8b790ef656 updated libraries for SDK3 2024-09-23 14:31:45 -03:00
richonguzman
c110b41b99 build update for new boards 2024-09-23 12:42:03 -03:00
richonguzman
be7fe23cd5 Added LLCC68 1W board 2024-09-23 12:37:35 -03:00
richonguzman
202d03c61f shortening reduced Wx report 2024-09-23 12:15:58 -03:00
richonguzman
ddb45544db readme UPdate 2024-09-22 22:35:51 -03:00
richonguzman
c9ea51c6da update Version 2024-09-22 22:34:00 -03:00
richonguzman
72fd2b45ec added mods to include Telemetry 2024-09-22 22:31:33 -03:00
richonguzman
0e46c64880 primera mejora Telemetria 2024-09-22 13:34:13 -03:00
richonguzman
dd12330e85 killing some delays 2024-09-17 14:25:00 -03:00
richonguzman
2edb183cad minor update on Heltec WS 2024-09-11 16:14:40 -03:00
richonguzman
775677d5e8 trying heltec wireless stick oled fix 2024-09-11 15:49:58 -03:00
richonguzman
a60a6d6e4b update WIRE 2024-09-10 14:26:10 -03:00
richonguzman
14abe14703 updated structs of last Stations and 25seg buffer 2024-09-10 14:06:10 -03:00
richonguzman
345fb1e937 up 2024-09-02 09:40:17 -04:00
richonguzman
916eb038e5 updated WiFi.setHostName() 2024-09-02 09:12:18 -04:00
richonguzman
40fc177828 small fix on wire begin 2024-08-30 15:46:50 -04:00
richonguzman
5dc6e99972 low external voltage RF Tx fix 2024-08-28 17:11:50 -04:00
richonguzman
db5710ec6a test 2024-08-28 12:21:54 -04:00
richonguzman
65acb54dbe wrong external sleep voltage definition fix 2024-08-28 11:45:16 -04:00
richonguzman
6088c61e73 versionUpdate + utils beacon message update 2024-08-26 10:33:49 -04:00
Ricardo Guzman (Richonguzman)
a8c972c5e1 Merge pull request #157 from S57PNX/main
Correct logic of serial notifications for APRS-IS and RF beacons
2024-08-26 10:32:01 -04:00
S57PNX
bd3a9f91d6 Merge branch 'richonguzman:main' into main 2024-08-26 10:25:17 +02:00
richonguzman
643a18f40c Wemos S2 Mini DIY LoRa added 2024-08-23 18:05:27 -04:00
richonguzman
46e5bdd21e added led 2024-08-23 18:00:25 -04:00
richonguzman
ea426f4126 board update 2024-08-22 16:27:41 -04:00
richonguzman
5cbdd318a2 test for WEMOS S2 Mini DIY LORA 2024-08-22 15:00:56 -04:00
richonguzman
735988ee1c adding WEMOS S2 MINI 2024-08-22 14:24:30 -04:00
richonguzman
d5b666f458 HELTEC WS update 2024-08-22 13:25:46 -04:00
richonguzman
702f4abcbb update for gps beacon with timestamp 2024-08-21 19:11:05 -04:00
richonguzman
d0070e4381 updated config 2024-08-20 19:01:04 -04:00
richonguzman
f4744eab6a Heltec Wireless Paper base 2024-08-19 11:37:55 -04:00
richonguzman
bd672857f4 testing for external battery block 2024-08-19 10:41:46 -04:00
richonguzman
9cc26ccdae wireless paper battery reading fix 2024-08-18 21:06:57 -04:00
richonguzman
8863838210 updated battery readings 2024-08-17 13:16:44 -04:00
richonguzman
f11b6de57a fix for normal display 2024-08-16 16:00:58 -04:00
richonguzman
55d6bc325f version update 2024-08-16 15:52:55 -04:00
richonguzman
ee687e6959 first test 2024-08-16 15:52:20 -04:00
S57PNX
d1732a6bba Correct logic of serial notifications for APRS-IS
and RF beacons
2024-08-15 20:54:26 +02:00
richonguzman
4fb4712a33 backupDigimode avoided in only rx mode 2024-08-14 13:37:52 -04:00
richonguzman
39276b0d32 update to display h and cpp 2024-08-14 12:32:34 -04:00
richonguzman
22203a7c24 just code cleaning 2024-08-14 12:07:17 -04:00
richonguzman
d8d832fde9 configuration test without fails 2024-08-14 11:50:39 -04:00
richonguzman
61db6c3132 backUpDigiMode and BME for HWSL v3 fix 2024-08-13 17:56:27 -04:00
richonguzman
9521a357b1 readmeUpdate 2024-08-13 14:49:30 -04:00
richonguzman
ee95931f00 web user and password 2024-08-13 14:48:08 -04:00
richonguzman
60aa2b05ac more boards update 2024-08-13 12:46:20 -04:00
richonguzman
bc5183a192 Ht-ct62 updates 2024-08-13 12:36:37 -04:00
richonguzman
1019306c7c wide2-n fix 2024-08-12 13:49:58 -04:00
richonguzman
fbe00903ad version Date on footer added 2024-08-12 11:01:35 -04:00
richonguzman
291a6bc80e added mesh - diy board v1-2 2024-08-12 10:35:45 -04:00
richonguzman
3b550c7f81 mode3 fix WIDE2-2 2024-08-06 10:57:00 -04:00
richonguzman
4659f8b2ff mode3start 2024-08-06 10:11:50 -04:00
richonguzman
62d157d7f0 state add at boot 2024-08-06 09:12:01 -04:00
richonguzman
b0e116ee1d Readme Update Digis 2024-08-05 17:42:59 -04:00
richonguzman
00b12c2bf5 version update 2024-08-05 15:43:42 -04:00
richonguzman
85b21565db index fix 2024-08-05 15:43:02 -04:00
richonguzman
b9e2c0e8f0 digimode 3 improvement 2024-08-05 15:42:33 -04:00
richonguzman
b763b4af78 RNAAAA add + WIDE2 description in index 2024-08-05 15:20:58 -04:00
richonguzman
5553e7ae5c added mode 3 for digirepeater 2024-08-05 14:37:16 -04:00
richonguzman
1afd039c3f digi mode 3 added 2024-08-03 21:55:32 -04:00
richonguzman
1888084f31 WSL v3 wire1 add 2024-08-02 16:15:10 -04:00
richonguzman
dc92b822c8 fixed missing wire begin 2024-08-02 15:28:31 -04:00
richonguzman
3c305259e0 update to recover from wifi AP 2024-08-02 13:08:54 -04:00
richonguzman
497d648c17 ready for testing 2024-07-18 14:41:09 -04:00
richonguzman
d267f6699c HWSL_V3_Display add 2024-07-17 16:20:20 -04:00
richonguzman
16ce6bc6d2 a7670 voltage calibration fix 2024-07-17 10:47:42 -04:00
richonguzman
008b6250ea Non Ham mods only for Rx 2024-07-10 15:13:57 -04:00
richonguzman
ddb83d1368 voltageCalibrationCorrection 2024-07-10 09:49:13 -04:00
richonguzman
26e2dec2b2 font size update 2024-07-09 10:41:26 -04:00
richonguzman
174507377b fix for other boards 2024-07-09 08:39:59 -04:00
richonguzman
864ed44a5d favicon and battery adc calibration 2024-07-08 23:29:04 -04:00
richonguzman
5d69cfbe1c 1 2024-07-08 23:06:03 -04:00
richonguzman
e57d356fd1 new ADC calibration test 2024-07-08 23:02:45 -04:00
richonguzman
8381f0916c variable name change 2024-07-05 13:12:21 -04:00
richonguzman
beca09293a queryUppercase fix 2024-07-05 11:58:18 -04:00
richonguzman
dcca18eeac readme Update 2024-07-01 18:30:11 -04:00
richonguzman
2494acea55 espacio en blanco 2024-06-30 10:36:15 -04:00
richonguzman
0c50ce8de4 tyeofpacket update 2024-06-30 09:24:21 -04:00
richonguzman
2f07d35861 readmeupdate7 2024-06-28 16:20:07 -04:00
richonguzman
91240c5be6 readmeupdate6 2024-06-28 16:19:18 -04:00
richonguzman
b4308a95d5 readmeupdate5 2024-06-28 16:18:41 -04:00
richonguzman
6c301795d6 readmeupdate4 2024-06-28 16:18:13 -04:00
richonguzman
5f0c6f4986 readmeupdate3 2024-06-28 16:15:56 -04:00
richonguzman
7c989e6e9e readmeupdate2 2024-06-28 16:15:22 -04:00
richonguzman
2bcda6d3a4 readme update 2024-06-28 16:14:42 -04:00
richonguzman
848492dc36 updated QueryAnswer for 3rdPartyPacket 2024-06-28 16:05:04 -04:00
richonguzman
413bef67fb readme update 2024-06-27 16:25:58 -04:00
richonguzman
3fa4c9371a new battery web config 2024-06-27 16:02:20 -04:00
richonguzman
e846c38f97 externalBatdivider 2024-06-27 15:39:53 -04:00
richonguzman
b8446e3f1d bat and sh gone 2024-06-27 13:19:51 -04:00
richonguzman
c3984bc8da casi listo para prueba 2024-06-26 23:42:24 -04:00
richonguzman
601b72da9f funciona 2024-06-26 18:13:02 -04:00
richonguzman
5d9493314d casi 2024-06-26 17:56:11 -04:00
richonguzman
86cf12d6c1 carga datos base 2024-06-26 17:10:07 -04:00
richonguzman
e5e2c6a980 readmeUpdate 2024-06-26 13:26:17 -04:00
richonguzman
3b9d49c5f9 personalNote implementation 2024-06-26 13:24:36 -04:00
richonguzman
ab9443140b personalNote1 2024-06-26 13:05:45 -04:00
richonguzman
ad1129c588 callsign validation process fix 2024-06-25 16:36:49 -04:00
richonguzman
8bb0b0446c more 3rd party filtering 2024-06-24 13:25:30 -04:00
richonguzman
6b1d319901 fix firstColon on last position 2024-06-24 11:36:40 -04:00
richonguzman
1ceaf159ba colonIndex fix3 2024-06-24 11:18:42 -04:00
richonguzman
f1de8d2df0 colonIndex upload fix 2024-06-24 11:16:52 -04:00
richonguzman
b9b4f46c66 typeOfPacket fix3 2024-06-24 11:02:38 -04:00
richonguzman
22b2c679d2 typeofPacket initial fix 2024-06-24 10:54:21 -04:00
richonguzman
7baa98bf7e first 3rdparty correction 2024-06-24 10:32:58 -04:00
richonguzman
35e79709e3 HeltecWSL V3 battery reading fix 2024-06-21 15:33:56 -04:00
richonguzman
f4bae74c26 build fix 2024-06-21 11:38:54 -04:00
richonguzman
04e721ac5a build correction 2024-06-21 11:15:52 -04:00
richonguzman
1922d7453b readmeUpdate 3rd Party 2024-06-21 11:11:40 -04:00
richonguzman
f1bd751585 readmeUpdate3rdParty 2024-06-21 11:02:34 -04:00
richonguzman
c346bc0f39 version and readme update 2024-06-21 10:58:54 -04:00
richonguzman
bbc1996918 update const String 2024-06-21 02:13:34 -04:00
richonguzman
505bb3d5a4 version update 2024-06-20 21:14:30 -04:00
richonguzman
b97457146a many updates const String and 3rd party 2024-06-20 21:12:54 -04:00
richonguzman
64b51fea72 first test with new 3rdParty 2024-06-20 14:06:14 -04:00
richonguzman
d82cf9235d starting with builing Tx packet 2024-06-18 23:42:09 -04:00
richonguzman
d83bb19bc8 A7670 code cleanup 2024-06-18 19:55:33 -04:00
richonguzman
0feb0045d0 build update 2024-06-18 19:36:17 -04:00
richonguzman
4999c89820 all boards with 915 versions added 2024-06-18 19:30:34 -04:00
richonguzman
f5048edf84 all sx1276 added 2024-06-18 18:43:25 -04:00
richonguzman
691f60925a only digi with packetbuffer25seg 2024-06-18 16:45:01 -04:00
richonguzman
4bf4e781df not callsign filtering from aprs-is feed 2024-06-18 15:29:00 -04:00
richonguzman
0c09f5a934 callsign filter changed 2024-06-18 15:15:27 -04:00
richonguzman
494be4a393 readmeupdate5 2024-06-17 21:41:29 -04:00
richonguzman
16e79d291c readmeupdate4 2024-06-17 21:40:54 -04:00
richonguzman
c9a52d5b61 readmeupdate3 2024-06-17 21:40:30 -04:00
richonguzman
7d813524e3 readme update2 2024-06-17 21:39:26 -04:00
richonguzman
2d7d02f2df update readme 2024-06-17 21:37:53 -04:00
richonguzman
562b0a46ea update of Configuration images 2024-06-17 20:32:39 -04:00
richonguzman
69c074a834 readmeMods 2024-06-16 20:55:54 -04:00
richonguzman
bf04507ed0 new webflasher image 2024-06-16 20:53:36 -04:00
richonguzman
e653d39004 build updated for missing letter in sx1268 tbeam 2024-06-15 09:50:30 -04:00
richonguzman
68edade5b4 readyForNewRelease1.0.3 2024-06-15 09:01:33 -04:00
richonguzman
685d629ef6 callsign test corrected 2024-06-14 23:25:47 -04:00
richonguzman
b7f6d84ac8 build test 2024-06-14 15:15:43 -04:00
richonguzman
dda4b06714 update 2024-06-14 11:01:32 -04:00
richonguzman
6095b4ff72 Si7021 fix for HELTEC V3 2024-06-13 13:36:18 -04:00
richonguzman
f77d7078b6 updateVersion 2024-06-12 09:34:13 -04:00
richonguzman
1dc1a291cd not funny 2024-06-12 09:23:01 -04:00
richonguzman
4396078d76 readmeUpdate 2024-06-10 17:02:27 -04:00
richonguzman
9924fb9a38 test 2024-06-10 14:13:28 -04:00
richonguzman
72a6c48553 testing ESP32C31WLORA 2024-06-10 14:09:30 -04:00
richonguzman
217e5b07e1 ESP32C3 1W DIY TEST 2024-06-10 14:00:15 -04:00
richonguzman
ce7ed2519f version update 2024-06-10 13:17:01 -04:00
richonguzman
72f0c80a29 betterCallsign Validation process 2024-06-10 11:33:26 -04:00
richonguzman
62db4c18da testing SI7021 2024-06-09 22:25:15 -04:00
richonguzman
7e91317730 update 2024-06-08 15:59:16 -04:00
richonguzman
49cffe7d0c avoid 3 bytes again 2024-06-08 15:50:55 -04:00
richonguzman
7537c1ee50 readmeUpdate 2024-06-08 15:28:16 -04:00
richonguzman
b2a8def481 update for NOCALL-10 2024-06-08 15:26:49 -04:00
richonguzman
b3441ece02 WIDE fix when not present 2024-06-08 14:39:15 -04:00
richonguzman
6ee86f7557 const corrections 2024-06-08 14:12:20 -04:00
richonguzman
0f5330141f testing state 2024-06-08 13:57:58 -04:00
richonguzman
d04b009a49 test1 2024-06-08 12:52:47 -04:00
richonguzman
397a94cc47 callsignValidationTest 2024-06-07 17:29:55 -04:00
richonguzman
a8e1a48d62 version update 2024-06-07 00:16:03 -04:00
richonguzman
d75be8f007 code cleaning 2024-06-07 00:10:04 -04:00
richonguzman
c89ca7316f more const cleaning 2024-06-05 23:49:16 -04:00
richonguzman
18de124c04 switch and display cleaning 2024-06-05 23:20:34 -04:00
richonguzman
01cee5d51e libraries update 2024-06-04 13:33:34 -04:00
richonguzman
005f114a97 more - less code 2024-06-03 00:02:43 -04:00
richonguzman
e133d50cd9 syslog Fix 2024-05-31 15:09:28 -04:00
richonguzman
d3ebe43ebb readme update 2024-05-31 07:58:40 -04:00
richonguzman
c67f5b60e5 minor code cleaning 2024-05-30 20:04:46 -04:00
richonguzman
d2923cc0b6 SignalReport Query Added 2024-05-30 19:58:33 -04:00
richonguzman
a87cc0be58 testing lowerMemory Ussssage 2024-05-30 16:27:07 -04:00
richonguzman
e63d54d9f0 signalReport available 2024-05-30 15:38:30 -04:00
richonguzman
f6793c01c4 syslog call and code update 2024-05-30 15:12:34 -04:00
richonguzman
12bcc76452 deepSleepReboot update 2024-05-29 15:46:07 -04:00
richonguzman
4cf3a333c9 deepSleep update 2024-05-29 15:43:23 -04:00
richonguzman
c5217842ff Battery Monitor for T-Beams 2024-05-27 11:46:14 -04:00
richonguzman
e9bb0391f2 update for minSleepVoltage recovery 2024-05-26 21:51:22 -04:00
richonguzman
edd2ff65b9 update3 2024-05-25 14:08:57 -04:00
richonguzman
dcc0340c90 buildUpdate2.3 2024-05-25 14:00:27 -04:00
richonguzman
4aa8f1aba8 buildUpdate2.2 2024-05-25 13:58:52 -04:00
richonguzman
7c7b8507eb buildUpdate2.1 2024-05-25 13:57:45 -04:00
richonguzman
3d1ae2fa70 buildUpdate2 2024-05-25 13:57:26 -04:00
richonguzman
095cc7edae buildUpdate1 2024-05-25 12:57:39 -04:00
richonguzman
c1d1069785 update6-12 2024-05-24 18:36:43 -04:00
richonguzman
bc29afa94e update6-11 2024-05-24 18:19:24 -04:00
richonguzman
eeba0df050 update6-10 2024-05-24 18:12:39 -04:00
richonguzman
8f40563ae5 update6-5 2024-05-24 17:39:05 -04:00
richonguzman
8bcf95548c update6-4 2024-05-24 17:34:40 -04:00
richonguzman
6809d96b59 update6-3 2024-05-24 17:30:04 -04:00
richonguzman
09bf14f8d1 update6-2 2024-05-24 17:13:57 -04:00
richonguzman
666c57738b update6-1 2024-05-24 17:02:07 -04:00
richonguzman
e4d41380bf update6 2024-05-24 16:48:55 -04:00
richonguzman
afdde6ad2d update4 2024-05-24 16:15:04 -04:00
richonguzman
f7ce94c494 update3 2024-05-24 16:07:02 -04:00
richonguzman
ce69b0c950 update2 2024-05-24 15:55:21 -04:00
richonguzman
6e381fe7fc update 2024-05-24 15:45:17 -04:00
richonguzman
dcc549c5ba update build comming 2024-05-24 15:18:21 -04:00
richonguzman
618be275af battery monitor update 2024-05-24 14:42:39 -04:00
richonguzman
2c71e3ed65 update for HT-CT62 2024-05-24 14:27:39 -04:00
richonguzman
3589f54d02 full update for BatteryHealthMonitor 2024-05-24 14:24:40 -04:00
richonguzman
c6687529da comienzo dormir ext 2024-05-24 13:05:28 -04:00
richonguzman
3c2c49aa01 updated 2024-05-24 11:59:06 -04:00
richonguzman
9044b93090 ordenando 2024-05-24 11:48:12 -04:00
richonguzman
076f3bfcb5 funciona 2024-05-24 11:08:08 -04:00
richonguzman
c6888adca8 battery5-1 2024-05-24 10:43:06 -04:00
richonguzman
b06b91d258 starting 2024-05-24 10:00:21 -04:00
richonguzman
bbdcf8ce0d new names ok 2024-05-23 22:52:17 -04:00
richonguzman
992641578d battery 5 andando 2024-05-23 20:39:21 -04:00
richonguzman
f70d836285 reorden index 2024-05-23 20:29:35 -04:00
richonguzman
d50b0767c4 battery basico funciona 2024-05-23 20:22:12 -04:00
richonguzman
fc8d3fd9fb justo antes de fallar 2024-05-23 20:13:05 -04:00
richonguzman
345a6c2c21 a 2024-05-23 19:27:10 -04:00
richonguzman
5986125661 wifiInterval not used 2024-05-23 18:29:08 -04:00
richonguzman
6090b83d34 web edit 2024-05-22 19:24:28 -04:00
richonguzman
7cc1a759cc readme update 2024-05-22 19:20:27 -04:00
richonguzman
51f9e0f0cc Reboot Mode Added 2024-05-22 19:19:25 -04:00
richonguzman
960df01d61 readme update again 2024-05-22 16:45:21 -04:00
richonguzman
60a8fe01a3 readme update 2024-05-22 16:43:49 -04:00
richonguzman
46d8b12896 Testing backupDigiMode return2 2024-05-22 16:41:20 -04:00
richonguzman
5296b19ef2 first test backupDigiMode 2024-05-22 16:19:45 -04:00
richonguzman
35fbd7a5dc testing backupDigiMode 2024-05-22 15:41:25 -04:00
richonguzman
adf4c1fcb8 testing Mode5 return1 2024-05-22 15:29:00 -04:00
richonguzman
0921d01340 starting mods 2024-05-22 11:41:08 -04:00
richonguzman
0c81df7cc5 lora power mod 2024-05-22 10:54:20 -04:00
richonguzman
789b3732f3 fix battery calculations 2024-05-22 08:36:54 -04:00
richonguzman
8be573e2b6 new buildPacketToTx 2024-05-21 00:00:23 -04:00
richonguzman
7022046f21 new order in WebUi 2024-05-20 23:33:59 -04:00
richonguzman
d19284df12 Objects received 2024-05-20 23:03:57 -04:00
richonguzman
05a5c096c3 ready to test Objects to Rf 2024-05-20 21:54:55 -04:00
richonguzman
7add09d346 tx objects 2024-05-20 17:57:58 -04:00
richonguzman
9e87c50966 welcomeMessage update 2024-05-20 11:18:01 -04:00
richonguzman
9a33df49e3 testing for heltec v2_1 2024-05-20 07:49:52 -04:00
richonguzman
916cbade8c testing new Syslog Comments info 2024-05-19 23:34:29 -04:00
richonguzman
2496c12763 WemosD1 update 2024-05-18 11:51:28 -04:00
richonguzman
166773b81d Wemos D1 added 2024-05-18 11:48:50 -04:00
richonguzman
b8d000356a boards_pinout change 2024-05-18 11:27:14 -04:00
richonguzman
49d3801e83 updateNewStuff 2024-05-17 15:14:58 -04:00
richonguzman
9dead41e79 version update 2024-05-17 15:11:59 -04:00
richonguzman
f3eaa28c76 lora code update 2024-05-17 09:01:15 -04:00
richonguzman
1bdfa3a117 adding Heltec WSL v3 2024-05-17 00:12:46 -04:00
richonguzman
8af1f4cea3 another Radiolib Test 2024-05-16 23:22:27 -04:00
richonguzman
d3e45c57e0 test1 2024-05-16 17:52:25 -04:00
richonguzman
8024925950 HELTEC WSL V3 added 2024-05-16 15:43:13 -04:00
richonguzman
8e6346aa97 build mods 2024-05-16 14:35:53 -04:00
richonguzman
cfca59cf20 const String 2 2024-05-15 17:47:29 -04:00
richonguzman
2430f92193 tnc + station const String 2024-05-15 16:41:07 -04:00
richonguzman
3cef4676a7 A7670 const String 2024-05-15 16:30:00 -04:00
richonguzman
87a1830970 adding decimal to BME Pressure measurement 2024-05-15 12:12:05 -04:00
richonguzman
b8fb7cfba0 readme update 2024-05-14 11:44:28 -04:00
richonguzman
3b81460798 HELTEC_V3 BME680 fix 2024-05-14 11:43:29 -04:00
richonguzman
630ec062c1 HT_CT_62 beaconPacket fix 2024-05-14 09:23:22 -04:00
richonguzman
dc39eec941 testing heltecv3 0.3 2024-05-14 09:14:25 -04:00
richonguzman
bdf3fe7cbc test HELTECv3 0.2 2024-05-14 09:08:24 -04:00
richonguzman
3de3aac026 testing HeltecV3 0.1 2024-05-14 08:59:47 -04:00
richonguzman
3a148fa55d testing heltecv3 2024-05-14 08:47:57 -04:00
richonguzman
c7e79eba43 bme680 fix for heltec v3 2024-05-14 02:01:24 -04:00
richonguzman
8429bb4730 25SegBuffer fix 2024-05-14 01:14:02 -04:00
richonguzman
c940cb99d9 testing actions 2024-05-14 00:36:32 -04:00
richonguzman
0be60b76b0 mayor code cleaning 2024-05-13 23:30:15 -04:00
richonguzman
794cc0640f buffer implemented 2024-05-13 21:47:52 -04:00
richonguzman
c5dcfd86b2 buffer 0.1 2024-05-13 21:24:44 -04:00
richonguzman
4d4598e09e buffer added to digimode 2024-05-13 21:00:42 -04:00
richonguzman
2e4ee4792e 1 2024-05-13 20:29:08 -04:00
richonguzman
bee09386e1 less lora state validations 2024-05-13 18:12:51 -04:00
richonguzman
0a15813ef2 WebUpdate for auto BME detect 2024-05-13 17:17:07 -04:00
richonguzman
6ecb733bea saving works kinda 2024-05-13 16:08:27 -04:00
richonguzman
1345ddd608 index1.1 2024-05-13 14:48:07 -04:00
richonguzman
5c0fba60b5 index mod1 2024-05-13 14:40:30 -04:00
richonguzman
67c2a61f09 first test mod WebUI 2024-05-13 14:13:00 -04:00
richonguzman
f1e712a363 bme autodetect 2024-05-13 14:00:07 -04:00
richonguzman
7753618756 test startup delay 1 2024-05-13 08:50:34 -04:00
richonguzman
61168d9217 Startup delay test added 2024-05-13 08:45:19 -04:00
richonguzman
d9af677f69 tft rotation fix 2024-05-12 22:57:45 -04:00
richonguzman
cc976a4a4a small code refactor 2024-05-12 22:02:12 -04:00
Ricardo Guzman (Richonguzman)
e6402409fc bme comment fix 2024-05-12 11:42:28 -04:00
richonguzman
12860410fd code cleaning1 2024-05-11 12:59:25 -04:00
richonguzman
886b661a62 CodeCleaning 2024-05-11 12:59:07 -04:00
richonguzman
53461f289c batteryReading for Heltec WT 2024-05-11 12:38:05 -04:00
richonguzman
54496a9f86 readme update 2024-05-11 12:29:10 -04:00
richonguzman
5e0294fb14 typeOfPacket fix 2024-05-11 12:27:13 -04:00
richonguzman
d7c1c70f10 TFT fix and ??? in beacon Rx 2024-05-11 12:19:19 -04:00
richonguzman
ad507cb4c9 Heltec WT added1 2024-05-11 12:02:08 -04:00
richonguzman
c54843622c setRxBoostedGainMode 2024-05-10 23:18:27 -04:00
richonguzman
2d820bbcc4 callsign always as uppercase 2024-05-10 16:36:28 -04:00
richonguzman
691f967aaf git Ignore update 2024-05-10 10:20:04 -04:00
richonguzman
3b85a3a5bf small battery measurement update 2024-05-09 13:49:09 -04:00
richonguzman
983467e059 BME warning fix 2024-05-08 15:05:43 -04:00
richonguzman
2b6066f62e versionUpdate 2024-05-05 08:17:18 -04:00
richonguzman
b81d986c58 blackSpacekiller 2024-05-05 08:16:58 -04:00
richonguzman
71c5e608b6 better heared station function 2024-05-05 08:16:15 -04:00
richonguzman
db24293b91 better definitions 2024-05-02 15:31:31 -04:00
richonguzman
611ea87264 better battery code 2024-05-02 13:41:21 -04:00
richonguzman
04a7f89891 code cleaning in power_utils 2024-05-02 12:57:18 -04:00
richonguzman
d744f0a0f0 heltec v3 battery test 2024-05-01 08:06:31 -04:00
richonguzman
a14c570db0 heltecV3 battery readings fix 2024-04-30 17:18:02 -04:00
richonguzman
708742f43d update display toggle 2024-04-29 09:19:25 -04:00
richonguzman
e182dd163e code cleaning 2024-04-28 09:30:56 -04:00
richonguzman
b2b388da99 syslog update 2024-04-28 09:06:45 -04:00
richonguzman
c6929e161a readme update1.1 2024-04-26 20:56:44 -04:00
richonguzman
26e4984225 readme update1 2024-04-26 20:55:54 -04:00
richonguzman
fe41189418 black space again 2024-04-23 22:40:03 -04:00
richonguzman
9742e25100 sx1276 && 915 added 2024-04-23 22:25:20 -04:00
richonguzman
e2c3edd0f1 delete old images 2024-04-23 17:13:03 -04:00
richonguzman
ffc3bd7624 batteryPin measurement A7670 2024-04-23 16:37:49 -04:00
richonguzman
7743cbe221 battery pin update 2024-04-23 16:36:08 -04:00
richonguzman
da0178bc56 battery and led pin add 2024-04-23 16:28:19 -04:00
richonguzman
5f145751c0 ESP32 & A7670 & LoRa added 2024-04-23 14:10:04 -04:00
richonguzman
cda72194db Add ESP32 & Modem A7670 2024-04-23 13:57:21 -04:00
richonguzman
47e6623881 first test of Modem 2024-04-23 12:30:57 -04:00
richonguzman
7e4fdff0a3 digi packet process fix 2024-04-23 10:53:53 -04:00
richonguzman
eb472b1506 first library cleaning in platformio 2024-04-23 10:29:46 -04:00
richonguzman
f2a6bbf0a9 start addA7670 2024-04-23 09:16:39 -04:00
richonguzman
3df25d71e2 readme update 2024-04-22 13:38:03 -04:00
richonguzman
1b5a89b31b Merge branch 'main' of https://github.com/richonguzman/LoRa_APRS_iGate 2024-04-22 13:33:21 -04:00
richonguzman
bd8c8e2eb1 readme change and version update 2024-04-22 13:31:02 -04:00
richonguzman
2b0cc514f0 WEMOS LOLIN32 added for testing 2024-04-22 13:25:52 -04:00
richonguzman
deb4ea6974 heltec v3 battery 2024-04-20 14:02:11 -04:00
richonguzman
5333a68d04 ht-ce62 fix 2024-04-20 13:17:25 -04:00
richonguzman
7ab5ffa81d more cleaning 2024-04-20 12:38:45 -04:00
richonguzman
3964354844 QTH images add for wiki 2024-04-20 12:18:19 -04:00
Ricardo Guzman (Richonguzman)
1eee529f9f qth image add 2024-04-20 12:15:15 -04:00
richonguzman
38b81ffbd7 version update 2024-04-20 11:09:11 -04:00
richonguzman
7dfbaf45ef readme update 5 2024-04-20 11:08:50 -04:00
richonguzman
13adc2d2d0 upload images 2024-04-20 11:00:04 -04:00
Ricardo Guzman (Richonguzman)
ce088035ff adding pinpoint and aprsis32 2024-04-20 10:57:47 -04:00
richonguzman
4eb46d59f6 readme update 4 2024-04-20 10:55:09 -04:00
richonguzman
2cbb6c1a1a readme update3 2024-04-20 10:52:26 -04:00
Ricardo Guzman (Richonguzman)
507a365b88 new webflasher image 2024-04-20 10:50:47 -04:00
richonguzman
5f04468285 readme update2 2024-04-20 10:43:38 -04:00
richonguzman
fc2a35a058 readme update 2024-04-20 10:41:48 -04:00
richonguzman
7987ceb262 final mods to test outputbuffer 2024-04-20 10:06:22 -04:00
richonguzman
8f1629abbc lastRxTime added to process buffer 2024-04-20 09:37:22 -04:00
richonguzman
b4f2daca42 outputBuffer Created-all LoRa send to Buffer 2024-04-20 09:27:20 -04:00
richonguzman
ce058ed424 HELTEC V3 battery input fix 2024-04-19 11:06:26 -04:00
98 changed files with 5202 additions and 2744 deletions

View File

@@ -11,17 +11,72 @@ jobs:
fail-fast: false
matrix:
target:
- "ttgo-lora32-v21"
- "heltec-lora32-v2"
- "heltec_wifi_lora_32_V3"
- "ESP32_DIY_LoRa"
- "ESP32_DIY_1W_LoRa"
- "ttgo-t-beam-v1_2"
- "ttgo-t-beam-v1"
- "ttgo-t-beam-v1_SX1268"
- "ttgo-t-beam-v1_2_SX1262"
- "heltec_wireless_stick"
- "heltec_ht-ct62"
- name: ttgo-lora32-v21
chip: esp32
- name: ttgo-lora32-v21_915
chip: esp32
- name: ttgo_lora32_t3s3_v1_2
chip: esp32s3
- name: heltec-lora32-v2
chip: esp32
- name: heltec_wifi_lora_32_V3
chip: esp32s3
- name: heltec_wireless_stick
chip: esp32s3
- name: heltec_wireless_stick_lite_v3
chip: esp32s3
- name: heltec_wireless_stick_lite_v3_display
chip: esp32s3
- name: ESP32_DIY_LoRa
chip: esp32
- name: ESP32_DIY_LoRa_915
chip: esp32
- name: ESP32_DIY_1W_LoRa
chip: esp32
- name: ESP32_DIY_1W_LoRa_915
chip: esp32
- name: ESP32_DIY_1W_LoRa_LLCC68
chip: esp32
- name: ESP32_DIY_1W_LoRa_Mesh_V1_2
chip: esp32
- name: ttgo-t-beam-v1_2
chip: esp32
- name: ttgo-t-beam-v1_2_915
chip: esp32
- name: ttgo-t-beam-v1
chip: esp32
- name: ttgo-t-beam-v1_915
chip: esp32
- name: ttgo-t-beam-v1_SX1268
chip: esp32
- name: ttgo-t-beam-v1_2_SX1262
chip: esp32
- name: ESP32_DIY_LoRa_A7670
chip: esp32
- name: ESP32_DIY_LoRa_A7670_915
chip: esp32
- name: heltec_wireless_tracker
chip: esp32s3
- name: heltec_ht-ct62
chip: esp32c3
- name: heltec_wireless_paper
chip: esp32s3
- name: OE5HWN_MeshCom
chip: esp32
- name: WEMOS-LOLIN32-OLED-DIY
chip: esp32
- name: WEMOS-D1-R32-RA02
chip: esp32
- name: WEMOS_S2_MINI_DIY_LoRa
chip: esp32s2
- name: esp32c3_DIY_1W_LoRa
chip: esp32c3
- name: esp32c3_DIY_1W_LoRa_915
chip: esp32c3
- name: ESP32_C3_OctopusLab_LoRa
chip: esp32c3
- name: QRPLabs_LightGateway_1_0
chip: esp32s3
steps:
- uses: actions/checkout@v3
@@ -33,25 +88,70 @@ jobs:
run: pip install --upgrade platformio
- name: Build target
run: pio run -e ${{ matrix.target }}
run: |
pio run -e ${{ matrix.target.name }}
- name: Build FS
run: pio run --target buildfs -e ${{ matrix.target }}
run: |
pio run --target buildfs -e ${{ matrix.target.name }}
- name: Move Files
run: |
mkdir -p installer/firmware
cp .pio/build/${{ matrix.target }}/firmware.bin installer/ota_update.bin
cp .pio/build/${{ matrix.target }}/firmware.bin installer/firmware/
cp .pio/build/${{ matrix.target }}/bootloader.bin installer/firmware/
cp .pio/build/${{ matrix.target }}/partitions.bin installer/firmware/
cp .pio/build/${{ matrix.target }}/spiffs.bin installer/firmware/
cp .pio/build/${{ matrix.target.name }}/firmware.bin installer/ota_update.bin
cp .pio/build/${{ matrix.target.name }}/firmware.bin installer/firmware/
cp .pio/build/${{ matrix.target.name }}/bootloader.bin installer/firmware/
cp .pio/build/${{ matrix.target.name }}/partitions.bin installer/firmware/
cp .pio/build/${{ matrix.target.name }}/spiffs.bin installer/firmware/
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin installer/firmware/
- name: Merge for web flashing
run: |
python installer/bin/esptool/esptool.py --chip esp32 merge_bin -o installer/web_upgrade.bin --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 installer/firmware/bootloader.bin 0x8000 installer/firmware/partitions.bin 0xe000 installer/firmware/boot_app0.bin 0x10000 installer/firmware/firmware.bin
python installer/bin/esptool/esptool.py --chip esp32 merge_bin -o installer/web_factory.bin --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 installer/firmware/bootloader.bin 0x8000 installer/firmware/partitions.bin 0xe000 installer/firmware/boot_app0.bin 0x10000 installer/firmware/firmware.bin 2686976 installer/firmware/spiffs.bin
if [ "${{ matrix.target.chip }}" == "esp32" ]; then
python installer/bin/esptool/esptool.py --chip esp32 merge_bin \
-o installer/web_factory.bin \
--flash_mode dio \
--flash_freq 40m \
--flash_size 4MB \
0x1000 installer/firmware/bootloader.bin \
0x8000 installer/firmware/partitions.bin \
0xe000 installer/firmware/boot_app0.bin \
0x10000 installer/firmware/firmware.bin \
0x3D0000 installer/firmware/spiffs.bin
elif [ "${{ matrix.target.chip }}" == "esp32s2" ]; then
python installer/bin/esptool/esptool.py --chip esp32s2 merge_bin \
-o installer/web_factory.bin \
--flash_mode dio \
--flash_freq 40m \
--flash_size 4MB \
0x1000 installer/firmware/bootloader.bin \
0x8000 installer/firmware/partitions.bin \
0xe000 installer/firmware/boot_app0.bin \
0x10000 installer/firmware/firmware.bin \
0x3D0000 installer/firmware/spiffs.bin
elif [ "${{ matrix.target.chip }}" == "esp32s3" ]; then
python installer/bin/esptool/esptool.py --chip esp32s3 merge_bin \
-o installer/web_factory.bin \
--flash_mode dio \
--flash_freq 40m \
--flash_size 8MB \
0x0000 installer/firmware/bootloader.bin \
0x8000 installer/firmware/partitions.bin \
0xe000 installer/firmware/boot_app0.bin \
0x10000 installer/firmware/firmware.bin \
0x3D0000 installer/firmware/spiffs.bin
elif [ "${{ matrix.target.chip }}" == "esp32c3" ]; then
python installer/bin/esptool/esptool.py --chip esp32c3 merge_bin \
-o installer/web_factory.bin \
--flash_mode dio \
--flash_freq 40m \
--flash_size 4MB \
0x1000 installer/firmware/bootloader.bin \
0x8000 installer/firmware/partitions.bin \
0xe000 installer/firmware/boot_app0.bin \
0x10000 installer/firmware/firmware.bin \
0x3D0000 installer/firmware/spiffs.bin
fi
- name: Install Zip
run: sudo apt-get install zip
@@ -66,5 +166,5 @@ jobs:
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: ./installer.zip
asset_name: ${{ matrix.target }}.zip
asset_name: ${{ matrix.target.name }}.zip
asset_content_type: application/zip

View File

@@ -11,18 +11,9 @@ jobs:
strategy:
fail-fast: false
matrix:
target:
- "ttgo-lora32-v21"
- "heltec-lora32-v2"
- "heltec_wifi_lora_32_V3"
- "ESP32_DIY_LoRa"
- "ESP32_DIY_1W_LoRa"
- "ttgo-t-beam-v1_2"
- "ttgo-t-beam-v1"
- "ttgo-t-beam-v1_SX1268"
- "ttgo-t-beam-v1_2_SX1262"
- "heltec_wireless_stick"
- "heltec_ht-ct62"
target:
- name: ttgo-lora32-v21
chip: esp32
steps:
- uses: actions/checkout@v3
@@ -34,7 +25,7 @@ jobs:
run: pip install --upgrade platformio
- name: Build target
run: pio run -e ${{ matrix.target }}
run: pio run -e ${{ matrix.target.name }}
- name: Build FS
run: pio run --target buildfs -e ${{ matrix.target }}
run: pio run --target buildfs -e ${{ matrix.target.name }}

104
README.md
View File

@@ -1,52 +1,90 @@
# Richonguzman / CA2RXU LoRa APRS iGate/Digirepeater
# CA2RXU LoRa APRS iGate/Digirepeater
This firmware is for using ESP32 based boards with LoRa Modules and GPS to live in the APRS world.
![Screenshot](https://github.com/richonguzman/LoRa_APRS_iGate/blob/main/images/iGateOledScreen.jpeg)
__(NOTE: This iGate Firmware was develop to work with all LoRa APRS Trackers and specially with this firmware <a href="https://github.com/richonguzman/LoRa_APRS_Tracker" target="_blank">LoRa APRS Tracker</a>)__
__(This iGate Firmware works with all LoRa Tracker Firmwares (specially this <a href="https://github.com/richonguzman/LoRa_APRS_Tracker" target="_blank">LoRa APRS Tracker Firmware</a>))__
<br />
___________________________________________________
____________________________________________________
## You can support this project to continue to grow:
[<img src="https://github.com/richonguzman/LoRa_APRS_Tracker/blob/main/images/github-sponsors.png">](https://github.com/sponsors/richonguzman) [<img src="https://github.com/richonguzman/LoRa_APRS_Tracker/blob/main/images/paypalme.png">](http://paypal.me/richonguzman)
____________________________________________________
<br />
This next generation LoRa iGate can work as:
- pure RX-iGate,
- Rx+Tx-iGate and distribute messages and weather forecasts to heard trackers, and
- Digipeater in simplex or split-frequency environment.
In all configurations the display shows the current stationMode, heard packets and events the iGate is currently performing.
But under the hood is much more:
- Web Configuration UI.
- Sending events to remote syslog server.
- OTA update capability (for Firmware and Filesystem).
- RX first, TX will only be done if there is no traffic on the frequency.
- automatic update of the Lora symbol at APRS-IS, black "L" for pure RX, red "L" for TX capability, green star "L" for digipeater and blue round "L" for WX iGate.
- support for multiple WLAN with corresponding coordinates.
- support for BME/BMP280 and BME680 sensors, sending to WX data to APRS-IS.
and more will come:
- More Web UI Station Information
# WEB FLASHER/INSTALLER is <a href="https://richonguzman.github.io/lora-igate-web-flasher/installer.html" target="_blank">here</a>
____________________________________________________
# WIKI
### Supported Boards and buying links --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/Z.-------Supported-Boards-and-Buying-Links" target="_blank">here</a>.
### FAQ, BME280, TNC and more --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/00.-FAQ-(frequently-asked-questions)" target="_blank">here</a>.
### Installation Guide --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/01.-Installation-Guide" target="_blank">here</a>.
<br />
*(Wiki has all configuration explanation, supported boards list, adding BME/BMP Wx modules and more)*
# SUPPORTED BOARDS
### Buying links --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/108.-Supported-Boards-and-Buying-Links" target="_blank">here</a>.
(NOTE: all boards with 433-868-915 MHz versions)
- TTGO Lilygo LoRa32 T3S3 V1.2 and LoRa32 V2.1 (V1.6 is the same).
- TTGO T-Beam V1.0 , V1.1, V1.2 (also variations with SX1262 and SX1268 LoRa Modules).
- HELTEC V2, V3 , Wireless Stick, Wireless Stick Lite, HT-CT62, Wireless Tracker, Wireless Paper.
- QRP Labs LightGateway 1.0.
- ESP32 Wroom + SX1278 LoRa Module or Ebyte 400M30S (or 900M30S) 1W LoRa Module for a DIY Versions.
- ESP32C3 + Ebyte 400M30S(or 900M30S) 1W LoRa Module for another DIY version.
- ESP32 + 4G/LTE A7670 Modem + SX1278 DIY Version.
- Wemos Lolin32 Oled + SX1278 DIY Version.
<br />
____________________________________________________
## Timeline (Versions):
- 2024.10.29 Added LILYGO Lora32 T3S3 support.
- 2024.10.25 Added QRP Labs LightGateway 1.0 support.
- 2024.10.21 Boards with GPS can now send Real-GPS Beacon (also posible: GPS ambiguity of ~ 1 km).
- 2024.10.14 Received Packets in WebUI show real Local Time (NTP with GMT offset).
- 2024.10.08 New EcoMode for Remote Digirepeaters without WiFi/WiFiAP, Screen, Leds (Example: LILYGO LoRa32 uses only 24mA, with WifiAP and all was 150mA). APRS Message/Queries can start/stop this mode too.
- 2024.10.06 Cross Frequency Digirepeater Rules added.
- 2024.09.23 Libraries Update for SDK3
- 2024.09.23 Added Enconded Telemetry for Battery (+ External Voltage) in Station GPS Beacon Packet.
- 2024.08.23 Wemos S2 Mini DIY LoRa added.
- 2024.08.19 HELTEC Wireless Paper working (still missing Epaper code).
- 2024.08.13 Web Authentication for WebUI. Thanks Mitja S57PNX.
- 2024.08.05 WIDE2-n added to WIDE1-n in Digirepeater Modes.
- 2024.06.27 External Voltage Divider Resistor configuration on WebUI. Thanks Tilen S54B.
- 2024.06.26 Personal Note information on WebUI for the Station. Thanks Tilen S54B.
- 2024.06.24 Callsign Validation fix. Thanks Helge SA7SKY.
- 2024.06.21 Tx packets coming from APRS-IS are (now) formatted into 3rd Party (as they should have been since the beginning). Thanks Lynn KJ4ERJ and Geoffrey F4FXL.
- 2024.06.18 All boards with 433 / 868 / 915 MHz versions.
- 2024.06.10 ESP32C3 + 1W LoRa Module (E22 400M30S) support added.
- 2024.06.09 Si7021 module added (with autodetected I2C Address)
- 2024.06.08 Callsign Validation for all Station that iGate/Digi hears.
- 2024.05.27 Battery Monitor for internal and External Voltages (to make board sleep and avoid low discharge of batterys) T-Beam boards now with Battery readings as well.
- 2024.05.23 Forced Reboot Mode added.
- 2024.05.22 Experimental backup-Digirepeater-Mode when "only" iGate mode loses WiFi connection added.
- 2024.05.20 WebConfig update to control whether Messages and Objects should be Tx to RF.
- 2024.05.17 HELTEC Wireless Stick Lite v3 support added.
- 2024.05.14 BME modules will be autodetected (I2C Address and if it is BME280/BMP280/BME680).
- 2024.05.13 PacketBuffer for Rx (25 Seg).
- 2024.05.11 HELTEC Wireless Tracker support added.
- 2024.04.23 T-LoRa32 v1.6/v2.1 with 915MHz support added.
- 2024.04.23 ESP32 + 4G/LTE MODEM A7670SA + LoRa (SX1278) support added.
- 2024.04.22 Wemos Lolin32 OLED DIY LoRa support added .
- 2024.04.21 WEB INSTALLER (thanks Damian SQ2CPA).
- 2024.04.20 New Output Buffer process: no more packets lost.
- 2024.04.13 Received Packets added on WebUI.
- 2024.04.09 iGate/Digirepeater own GPS beacon is encoded (Base91) now.
- 2024.03.18 OE5HWN MeshCom board support added.
@@ -55,22 +93,22 @@ ____________________________________________________
- 2024.01.19 TextSerialOutputForApp added to get text from Serial-Output over USB into PC for PinPoint App (https://www.pinpointaprs.com) and APRSIS32 App (http://aprsisce.wikidot.com)
- 2024.01.12 Added iGate Mode to also repeat packets (like a iGate+DigiRepeater) in stationMode 2 and 5.
- 2024.01.11 Added iGate Mode to enable APRS-IS and LoRa beacon report at the same time.
- 2024.01.05 Added support for Lilygo TTGO T-Beam V1, V1.2, V1 + SX1268, V1.2 + SX1262.
- 2024.01.02 Added support for EByte 400M30S 1Watt LoRa module for DIY ESP32 iGate.
- 2024.01.05 Lilygo TTGO T-Beam V1, V1.2, V1 + SX1268, V1.2 + SX1262 support added.
- 2024.01.02 EByte 400M30S 1 Watt LoRa module for DIY ESP32 iGate support added.
- 2023.12.27 HELTEC V3 board support added. Thanks Luc ON2ON.
- 2023.12.26 Added BME680 module to BME/BMP280 modules supported.
- 2023.12.07 MIC-E process and syslog added.
- 2023.12.26 BME680 module support added.
- 2023.12.07 MIC-E process and Syslog added.
- 2023.12.06 HELTEC V2 board support added.
- 2023.11.26 Small correction to enable Syslog in stationMode5.
- 2023.10.09 Added "WIDE1-1" to Tx packets from iGate to be *repeated* by Digirepeaters.
- 2023.10.09 Added Support also for BMP280 module.
- 2023.10.09 BMP280 module support added.
- 2023.08.20 Added External Voltage Measurement (Max 15V!)
- 2023.08.05 Ground Height Correction for Pressure readings added.
- 2023.07.31 StationMode5 added: iGate when WiFi and APRS available, DigiRepeater when not.
- 2023.07.16 Small OTA, BME module update.
- 2023.07.05 Adding monitor info of Battery connected.
- 2023.06.18 Info on Oled Screen mayor update, added RSSI and Distance to Listened Station.
- 2023.06.17 Support for BME280 Module (Temperature, Humidity, Pressure) added.
- 2023.06.17 BME280 Module (Temperature, Humidity, Pressure) support added.
- 2023.06.12 Syslog added.
- 2023.06.10 OTA update support for Firmware and Filesystem.
- 2023.06.08 Adding Digirepeater Functions.
@@ -84,4 +122,4 @@ ____________________________________________________
__________________________________________
# Hope You Enjoy this, 73 !! CA2RXU , Valparaiso, Chile
# Hope You Enjoy this, 73! CA2RXU, Valparaiso, Chile

View File

@@ -3,7 +3,7 @@
"wifi": {
"autoAP": {
"password": "1234567890",
"powerOff": 10
"timeout": 10
},
"AP": []
},
@@ -18,21 +18,18 @@
"sendViaAPRSIS": false,
"sendViaRF": false
},
"digi": {
"mode": 0
},
"tnc": {
"enableServer": false,
"enableSerial": false,
"acceptOwn": false
},
"aprs_is": {
"active": false,
"passcode": "XYZVW",
"server": "rotate.aprs2.net",
"port": 14580,
"filter": "m/10",
"toRF": false
"messagesToRF": false,
"objectsToRF": false
},
"digi": {
"mode": 0,
"ecoMode": false
},
"lora": {
"txFreq": 433775000,
@@ -49,24 +46,51 @@
"timeout": 4,
"turn180": false
},
"battery": {
"sendInternalVoltage": false,
"monitorInternalVoltage": false,
"internalSleepVoltage": 2.9,
"sendExternalVoltage": false,
"externalVoltagePin": 34,
"monitorExternalVoltage": false,
"externalSleepVoltage": 10.9,
"voltageDividerR1": 100.0,
"voltageDividerR2": 27.0,
"sendVoltageAsTelemetry": true
},
"wxsensor": {
"active": false,
"heightCorrection": 0,
"temperatureCorrection": 0.0
},
"syslog": {
"active": false,
"server": "192.168.0.100",
"port": 514
},
"bme": {
"active": false
"tnc": {
"enableServer": false,
"enableSerial": false,
"acceptOwn": false
},
"ota": {
"username": "",
"password": ""
},
"webadmin": {
"username": "admin",
"password": ""
},
"ntp": {
"gmtCorrection": 0
},
"other": {
"rememberStationTime": 30,
"sendBatteryVoltage": false,
"externalVoltageMeasurement": false,
"externalVoltagePin": 34,
"lowPowerMode": false,
"lowVoltageCutOff": 0
}
"lowVoltageCutOff": 0,
"backupDigiMode": false,
"rebootMode": false,
"rebootModeTime": 6
},
"personalNote": ""
}

BIN
data_embed/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 B

File diff suppressed because it is too large Load Diff

View File

@@ -74,16 +74,15 @@ logCheckbox.addEventListener("change", function () {
function loadSettings(settings) {
currentSettings = settings;
// General
document.getElementById("callsign").value = settings.callsign;
// document.getElementById("stationMode").value = settings.stationMode;
document.getElementById("bme.active").checked = settings.bme.active;
document.getElementById("beacon.comment").value = settings.beacon.comment;
document.getElementById("beacon.symbol").value = settings.beacon.symbol;
document.getElementById("beacon.overlay").value = settings.beacon.overlay;
document.getElementById("callsign").value = settings.callsign;
document.getElementById("beacon.comment").value = settings.beacon.comment;
document.getElementById("beacon.path").value = settings.beacon.path;
document.getElementById("beacon.symbol").value = settings.beacon.symbol;
document.getElementById("beacon.overlay").value = settings.beacon.overlay;
document.getElementById("personalNote").value = settings.personalNote;
document.getElementById("action.symbol").value = settings.beacon.overlay + settings.beacon.symbol;
document.getElementById("action.symbol").value = settings.beacon.overlay + settings.beacon.symbol;
document.querySelector(".list-networks").innerHTML = "";
document.querySelector(".list-networks").innerHTML = "";
// Networks
const wifiNetworks = settings.wifi.AP || [];
@@ -119,103 +118,107 @@ function loadSettings(settings) {
});
// APRS-IS
document.getElementById("aprs_is.active").checked = settings.aprs_is.active;
document.getElementById("aprs_is.toRF").checked = settings.aprs_is.toRF;
document.getElementById("aprs_is.server").value = settings.aprs_is.server;
document.getElementById("aprs_is.port").value = settings.aprs_is.port;
document.getElementById("aprs_is.filter").value = settings.aprs_is.filter;
document.getElementById("aprs_is.passcode").value =
settings.aprs_is.passcode;
document.getElementById("aprs_is.active").checked = settings.aprs_is.active;
document.getElementById("aprs_is.messagesToRF").checked = settings.aprs_is.messagesToRF;
document.getElementById("aprs_is.objectsToRF").checked = settings.aprs_is.objectsToRF;
document.getElementById("aprs_is.server").value = settings.aprs_is.server;
document.getElementById("aprs_is.port").value = settings.aprs_is.port;
document.getElementById("aprs_is.filter").value = settings.aprs_is.filter;
document.getElementById("aprs_is.passcode").value = settings.aprs_is.passcode;
// Beacon
document.getElementById("beacon.latitude").value = settings.beacon.latitude;
document.getElementById("beacon.longitude").value = settings.beacon.longitude;
document.getElementById("beacon.interval").value = settings.beacon.interval;
document.getElementById("other.rememberStationTime").value = settings.other.rememberStationTime;
document.getElementById("beacon.sendViaAPRSIS").checked = settings.beacon.sendViaAPRSIS;
document.getElementById("beacon.sendViaRF").checked = settings.beacon.sendViaRF;
document.getElementById("beacon.gpsActive").checked = settings.beacon.gpsActive;
document.getElementById("beacon.gpsAmbiguity").checked = settings.beacon.gpsAmbiguity;
// Digi
document.getElementById("digi.mode").value = settings.digi.mode;
document.getElementById("digi.ecoMode").checked = settings.digi.ecoMode;
// LoRa
document.getElementById("lora.txFreq").value = settings.lora.txFreq;
document.getElementById("lora.rxFreq").value = settings.lora.rxFreq;
document.getElementById("lora.txActive").checked = settings.lora.txActive;
document.getElementById("lora.rxActive").checked = settings.lora.rxActive;
document.getElementById("lora.spreadingFactor").value = settings.lora.spreadingFactor;
document.getElementById("lora.signalBandwidth").value = settings.lora.signalBandwidth;
document.getElementById("lora.codingRate4").value = settings.lora.codingRate4;
document.getElementById("lora.power").value = settings.lora.power;
// Display
document.getElementById("display.alwaysOn").checked =
settings.display.alwaysOn;
document.getElementById("display.turn180").checked =
settings.display.turn180;
document.getElementById("display.timeout").value = settings.display.timeout;
document.getElementById("display.alwaysOn").checked = settings.display.alwaysOn;
document.getElementById("display.turn180").checked = settings.display.turn180;
document.getElementById("display.timeout").value = settings.display.timeout;
if (settings.display.alwaysOn) {
timeoutInput.disabled = true;
}
// WiFi Auto AP
document.getElementById("wifi.autoAP.password").value =
settings.wifi.autoAP.password;
document.getElementById("wifi.autoAP.powerOff").value =
settings.wifi.autoAP.powerOff;
// Digi
// document.getElementById("digi.comment").value = settings.digi.comment;
// document.getElementById("digi.latitude").value = settings.digi.latitude;
// document.getElementById("digi.longitude").value = settings.digi.longitude;
document.getElementById("digi.mode").value = settings.digi.mode;
// TNC
if (settings.tnc) {
document.getElementById("tnc.enableServer").checked = settings.tnc.enableServer;
document.getElementById("tnc.enableSerial").checked = settings.tnc.enableSerial;
document.getElementById("tnc.acceptOwn").checked = settings.tnc.acceptOwn;
}
// OTA
document.getElementById("ota.username").value = settings.ota.username;
document.getElementById("ota.password").value = settings.ota.password;
// Beacon
document.getElementById("beacon.interval").value = settings.beacon.interval;
document.getElementById("other.rememberStationTime").value =
settings.other.rememberStationTime;
document.getElementById("other.sendBatteryVoltage").checked =
settings.other.sendBatteryVoltage;
document.getElementById("other.externalVoltageMeasurement").checked =
settings.other.externalVoltageMeasurement;
document.getElementById("other.externalVoltagePin").value =
settings.other.externalVoltagePin;
// document.getElementById("beacon.igateSendsLoRaBeacon").value =
// settings.beacon.igateSendsLoRaBeacon;
// document.getElementById("beacon.igateRepeatLoRaPackets").value =
// settings.beacon.igateRepeatLoRaPackets;
document.getElementById("beacon.path").value = settings.beacon.path;
document.getElementById("beacon.latitude").value = settings.beacon.latitude;
document.getElementById("beacon.longitude").value =
settings.beacon.longitude;
document.getElementById("beacon.sendViaAPRSIS").checked =
settings.beacon.sendViaAPRSIS;
document.getElementById("beacon.sendViaRF").checked =
settings.beacon.sendViaRF;
// Syslog
document.getElementById("syslog.active").checked = settings.syslog.active;
document.getElementById("syslog.server").value = settings.syslog.server;
document.getElementById("syslog.port").value = settings.syslog.port;
// BATTERY
document.getElementById("battery.sendInternalVoltage").checked = settings.battery.sendInternalVoltage;
document.getElementById("battery.monitorInternalVoltage").checked = settings.battery.monitorInternalVoltage;
document.getElementById("battery.internalSleepVoltage").value = settings.battery.internalSleepVoltage.toFixed(1);
document.getElementById("battery.sendExternalVoltage").checked = settings.battery.sendExternalVoltage;
document.getElementById("battery.externalVoltagePin").value = settings.battery.externalVoltagePin;
document.getElementById("battery.voltageDividerR1").value = settings.battery.voltageDividerR1.toFixed(1);
document.getElementById("battery.voltageDividerR2").value = settings.battery.voltageDividerR2.toFixed(1);
document.getElementById("battery.monitorExternalVoltage").checked = settings.battery.monitorExternalVoltage;
document.getElementById("battery.externalSleepVoltage").value = settings.battery.externalSleepVoltage.toFixed(1);
document.getElementById("battery.sendVoltageAsTelemetry").checked = settings.battery.sendVoltageAsTelemetry;
// TELEMETRY WX SENSOR
document.getElementById("wxsensor.active").checked = settings.wxsensor.active;
document.getElementById("wxsensor.heightCorrection").value = settings.wxsensor.heightCorrection;
document.getElementById("wxsensor.temperatureCorrection").value = settings.wxsensor.temperatureCorrection.toFixed(1);
// SYSLOG
document.getElementById("syslog.active").checked = settings.syslog.active;
document.getElementById("syslog.server").value = settings.syslog.server;
document.getElementById("syslog.port").value = settings.syslog.port;
if (settings.syslog.active) {
serverField.disabled = false;
portField.disabled = false;
}
// LoRa
// document.getElementById("lora.digirepeaterTxFreq").value =
// settings.lora.digirepeaterTxFreq;
// document.getElementById("lora.iGateFreq").value = settings.lora.iGateFreq;
// document.getElementById("lora.digirepeaterRxFreq").value =
// settings.lora.digirepeaterRxFreq;
document.getElementById("lora.txFreq").value = settings.lora.txFreq;
document.getElementById("lora.rxFreq").value = settings.lora.rxFreq;
document.getElementById("lora.txActive").checked = settings.lora.txActive;
document.getElementById("lora.rxActive").checked = settings.lora.rxActive;
document.getElementById("lora.spreadingFactor").value =
settings.lora.spreadingFactor;
document.getElementById("lora.signalBandwidth").value =
settings.lora.signalBandwidth;
document.getElementById("lora.codingRate4").value =
settings.lora.codingRate4;
document.getElementById("lora.power").value = settings.lora.power;
// TNC
if (settings.tnc) {
document.getElementById("tnc.enableServer").checked = settings.tnc.enableServer;
document.getElementById("tnc.enableSerial").checked = settings.tnc.enableSerial;
document.getElementById("tnc.acceptOwn").checked = settings.tnc.acceptOwn;
}
// Reboot
document.getElementById("other.rebootMode").checked = settings.other.rebootMode;
document.getElementById("other.rebootModeTime").value = settings.other.rebootModeTime;
// WiFi Auto AP
document.getElementById("wifi.autoAP.password").value = settings.wifi.autoAP.password;
document.getElementById("wifi.autoAP.timeout").value = settings.wifi.autoAP.timeout;
// OTA
document.getElementById("ota.username").value = settings.ota.username;
document.getElementById("ota.password").value = settings.ota.password;
// Webadmin
document.getElementById("webadmin.active").checked = settings.webadmin.active;
document.getElementById("webadmin.username").value = settings.webadmin.username;
document.getElementById("webadmin.password").value = settings.webadmin.password;
// NTP
document.getElementById("ntp.gmtCorrection").value = settings.ntp.gmtCorrection;
// Experimental
document.getElementById("other.lowPowerMode").checked = settings.other.lowPowerMode;
document.getElementById("other.lowVoltageCutOff").value = settings.other.lowVoltageCutOff || 0
document.getElementById("other.backupDigiMode").checked = settings.other.backupDigiMode;
document.getElementById("other.lowPowerMode").checked = settings.other.lowPowerMode;
document.getElementById("other.lowVoltageCutOff").value = settings.other.lowVoltageCutOff || 0
updateImage();
refreshSpeedStandard();
@@ -246,7 +249,7 @@ document.getElementById('reboot').addEventListener('click', function (e) {
showToast("Your device will be rebooted in a while");
});
const bmeCheckbox = document.querySelector("input[name='bme.active']");
const wxsensorCheckbox = document.querySelector("input[name='wxsensor.active']");
const stationModeSelect = document.querySelector("select[name='stationMode']");
@@ -276,26 +279,67 @@ function updateImage() {
}
function toggleFields() {
const externalVoltageMeasurementCheckbox = document.querySelector(
'input[name="other.externalVoltageMeasurement"]'
const sendExternalVoltageCheckbox = document.querySelector(
'input[name="battery.sendExternalVoltage"]'
);
const externalVoltagePinInput = document.querySelector(
'input[name="other.externalVoltagePin"]'
'input[name="battery.externalVoltagePin"]'
);
externalVoltagePinInput.disabled =
!externalVoltageMeasurementCheckbox.checked;
externalVoltagePinInput.disabled = !sendExternalVoltageCheckbox.checked;
voltageDividerR1.disabled = !sendExternalVoltageCheckbox.checked;
voltageDividerR2.disabled = !sendExternalVoltageCheckbox.checked;
const WebadminCheckbox = document.querySelector(
'input[name="webadmin.active"]'
);
const WebadminUsername = document.querySelector(
'input[name="webadmin.username"]'
);
const WebadminPassword = document.querySelector(
'input[name="webadmin.password"]'
);
WebadminUsername.disabled = !WebadminCheckbox.checked;
WebadminPassword.disabled = !WebadminCheckbox.checked;
}
const externalVoltageMeasurementCheckbox = document.querySelector(
'input[name="other.externalVoltageMeasurement"]'
const sendExternalVoltageCheckbox = document.querySelector(
'input[name="battery.sendExternalVoltage"]'
);
const externalVoltagePinInput = document.querySelector(
'input[name="other.externalVoltagePin"]'
'input[name="battery.externalVoltagePin"]'
);
externalVoltageMeasurementCheckbox.addEventListener("change", function () {
const voltageDividerR1 = document.querySelector(
'input[name="battery.voltageDividerR1"]'
);
const voltageDividerR2 = document.querySelector(
'input[name="battery.voltageDividerR2"]'
);
sendExternalVoltageCheckbox.addEventListener("change", function () {
externalVoltagePinInput.disabled = !this.checked;
voltageDividerR1.disabled = !this.checked;
voltageDividerR2.disabled = !this.checked;
});
const WebadminCheckbox = document.querySelector(
'input[name="webadmin.active"]'
);
const WebadminUsername = document.querySelector(
'input[name="webadmin.username"]'
);
const WebadminPassword = document.querySelector(
'input[name="webadmin.password"]'
);
WebadminCheckbox.addEventListener("change", function () {
WebadminUsername.disabled = !this.checked;
WebadminPassword.disabled = !this.checked;
});
document.querySelector(".new button").addEventListener("click", function () {
@@ -469,13 +513,9 @@ function loadReceivedPackets(packets) {
packets.forEach((packet) => {
const element = document.createElement("tr");
date.setTime(packet.millis);
const p = date.toUTCString().split(' ')
element.innerHTML = `
<td>${p[p.length-2]}</td>
<td>${packet.rxTime}</td>
<td>${packet.packet}</td>
<td>${packet.RSSI}</td>
<td>${packet.SNR}</td>

BIN
images/APRSIS32-01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

BIN
images/APRSIS32-02.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
images/APRSIS32-03.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
images/APRSIS32-04.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
images/APRSIS32-05.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
images/APRSIS32-06.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

BIN
images/PinPoint-01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
images/PinPoint-02.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
images/PinPoint-03.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
images/PinPoint-04.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
images/PinPoint-05.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 527 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

BIN
images/QTH-01.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

BIN
images/QTH-02.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
images/Web003-APRS-IS.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

BIN
images/Web004-Beaconing.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

BIN
images/Web006-LoRa.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

BIN
images/Web007-Display.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

BIN
images/Web008-Battery.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 KiB

BIN
images/Web009-Telemetry.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

BIN
images/Web011-TNC.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
images/Web012-Reboot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
images/Web013-AutoAP.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

BIN
images/Web014-OTA.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
images/Web015-Admin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
images/Web016-NTP.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

View File

@@ -1,39 +0,0 @@
@echo off
echo Loading...
where /q python.exe
if %errorlevel% neq 0 (
echo "Python is not installed. Please install it and try again."
exit /b
)
where /q pip
if %errorlevel% neq 0 (
echo "pip is not installed. Please install it and try again."
exit /b
)
pip show pyserial >nul 2>&1
if %errorlevel% neq 0 (
echo "Installing pyserial..."
pip install pyserial
)
echo Your firmware will be upgraded without factory reset.
echo:
echo IF THIS IS YOUR FIRST FLASH ON THIS BOARD PLEASE USE install_with_factory_reset.bat INSTEAD!
echo:
echo Available COM ports:
python.exe -c "import serial.tools.list_ports; print('\n'.join([str(c) for c in serial.tools.list_ports.comports()]))"
echo:
set /p port="Enter COM port (for example COM5): "
python.exe ./bin/esptool/esptool.py --chip esp32 --port "%port%" --baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 firmware/bootloader.bin 0x8000 firmware/partitions.bin 0xe000 firmware/boot_app0.bin 0x10000 firmware/firmware.bin
pause

View File

@@ -1,15 +0,0 @@
#!/bin/bash
echo "Your firmware will be upgraded without factory reset."
echo "IF THIS IS YOUR FIRST FLASH ON THIS BOARD PLEASE USE install_with_factory_reset.sh INSTEAD!"
read -p "Enter COM port (for example /dev/ttyS5): " port
PYTHON_CMD=python
if command -v python3 &> /dev/null
then
PYTHON_CMD=python3
fi
PYTHON_CMD ./bin/esptool/esptool.py --chip esp32 --port "$port" --baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 firmware/bootloader.bin 0x8000 firmware/partitions.bin 0xe000 firmware/boot_app0.bin 0x10000 firmware/firmware.bin
echo "Firmware flashed"

View File

@@ -1,44 +0,0 @@
@echo off
echo Loading...
where /q python.exe
if %errorlevel% neq 0 (
echo "Python is not installed. Please install it and try again."
exit /b
)
where /q pip
if %errorlevel% neq 0 (
echo "pip is not installed. Please install it and try again."
exit /b
)
pip show pyserial >nul 2>&1
if %errorlevel% neq 0 (
echo "Installing pyserial..."
pip install pyserial
)
echo Your current configuration will be LOST!!!
echo Your current configuration will be LOST!!!
echo Your current configuration will be LOST!!!
echo:
echo If you already have this board flashed with our firmware please use install_upgrade.bat instead!
echo:
echo Available COM ports:
python.exe -c "import serial.tools.list_ports; print('\n'.join([str(c) for c in serial.tools.list_ports.comports()]))"
echo:
set /p port="Enter COM port (for example COM5): "
python.exe bin/esptool/esptool.py --chip esp32 --port "%port%" --baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 4MB 2686976 firmware/spiffs.bin
python.exe bin/esptool/esptool.py --chip esp32 --port "%port%" --baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 firmware/bootloader.bin 0x8000 firmware/partitions.bin 0xe000 firmware/boot_app0.bin 0x10000 firmware/firmware.bin
pause

View File

@@ -1,17 +0,0 @@
#!/bin/bash
echo "Your firmware will be upgraded without factory reset."
echo "IF THIS IS YOUR FIRST FLASH ON THIS BOARD PLEASE USE install_with_factory_reset.sh INSTEAD!"
read -p "Enter COM port (for example /dev/ttyS5): " port
PYTHON_CMD=python
if command -v python3 &> /dev/null
then
PYTHON_CMD=python3
fi
$PYTHON_CMD ./bin/esptool/esptool.py --chip esp32 --port "$port" --baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 4MB 2686976 firmware/spiffs.bin
$PYTHON_CMD ./bin/esptool/esptool.py --chip esp32 --port "$port" --baud 460800 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 firmware/bootloader.bin 0x8000 firmware/partitions.bin 0xe000 firmware/boot_app0.bin 0x10000 firmware/firmware.bin
echo "Firmware flashed"

View File

@@ -12,7 +12,8 @@
default_envs = ttgo-lora32-v21
[env]
platform = espressif32 @ 6.3.1
platform = espressif32 @ 6.7.0
board_build.partitions = min_spiffs.csv
framework = arduino
monitor_speed = 115200
board_build.embed_files =
@@ -21,137 +22,464 @@ board_build.embed_files =
data_embed/script.js.gz
data_embed/bootstrap.css.gz
data_embed/bootstrap.js.gz
lib_deps =
bblanchon/ArduinoJson@^6.20.2
adafruit/Adafruit GFX Library @ 1.11.5
adafruit/Adafruit SSD1306 @ 2.5.7
mikalhart/TinyGPSPlus @ 1.0.3
adafruit/Adafruit Unified Sensor@^1.1.9
adafruit/Adafruit BME280 Library@^2.2.2
adafruit/Adafruit BMP280 Library@^2.6.8
adafruit/Adafruit BME680 Library@^2.0.4
jgromes/RadioLib @ 6.1.0
lewisxhe/XPowersLib@^0.1.8
ayushsharma82/ElegantOTA@^3.1.0
ottowinter/ESPAsyncWebServer-esphome@3.0.0
esphome/AsyncTCP-esphome@2.1.1
data_embed/favicon.png.gz
extra_scripts =
pre:tools/compress.py
debug_tool = esp-prog
[common]
build_flags =
-Werror -Wall
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
-DRADIOLIB_EXCLUDE_CC1101=1
-DRADIOLIB_EXCLUDE_NRF24=1
-DRADIOLIB_EXCLUDE_RF69=1
-DRADIOLIB_EXCLUDE_SX1231=1
-DRADIOLIB_EXCLUDE_SX1233=1
-DRADIOLIB_EXCLUDE_SI443X=1
-DRADIOLIB_EXCLUDE_RFM2X=1
-DRADIOLIB_EXCLUDE_AFSK=1
-DRADIOLIB_EXCLUDE_BELL=1
-DRADIOLIB_EXCLUDE_HELLSCHREIBER=1
-DRADIOLIB_EXCLUDE_MORSE=1
-DRADIOLIB_EXCLUDE_RTTY=1
-DRADIOLIB_EXCLUDE_SSTV=1
-DRADIOLIB_EXCLUDE_AX25=1
-DRADIOLIB_EXCLUDE_DIRECT_RECEIVE=1
-DRADIOLIB_EXCLUDE_BELL=1
-DRADIOLIB_EXCLUDE_PAGER=1
-DRADIOLIB_EXCLUDE_FSK4=1
-DRADIOLIB_EXCLUDE_APRS=1
-DRADIOLIB_EXCLUDE_LORAWAN=1
lib_deps =
jgromes/RadioLib @ 6.6.0
mikalhart/TinyGPSPlus @ 1.0.3
bblanchon/ArduinoJson @ 6.21.3
adafruit/Adafruit Unified Sensor @ 1.1.14
adafruit/Adafruit BME280 Library @ 2.2.4
adafruit/Adafruit BMP280 Library @ 2.6.8
adafruit/Adafruit BME680 Library @ 2.0.4
adafruit/Adafruit Si7021 Library @ 1.5.3
ayushsharma82/ElegantOTA @ 3.1.5
mathieucarbou/ESPAsyncWebServer @ 3.2.3
mathieucarbou/AsyncTCP @ 3.2.5
arduino-libraries/NTPClient @ 3.2.1
display_libs =
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:ttgo-lora32-v21]
board = ttgo-lora32-v21
build_flags =
-Werror -Wall
-DTTGO_T_LORA32_V2_1
-DHAS_SX127X
${common.build_flags}
-DTTGO_LORA32_V2_1
-DHAS_SX1278
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
-DHAS_ADC_CALIBRATION
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:ttgo-lora32-v21_915]
board = ttgo-lora32-v21
build_flags =
${common.build_flags}
-DTTGO_LORA32_V2_1_915
-DHAS_SX1276
-DHAS_ADC_CALIBRATION
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:heltec-lora32-v2]
board = ttgo-lora32-v21
build_flags =
-Werror -Wall
${common.build_flags}
-DHELTEC_V2
-DHAS_SX127X
-DHAS_SX1278
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:heltec_wifi_lora_32_V3]
board = heltec_wifi_lora_32_V3
board_build.mcu = esp32s3
build_flags =
-Werror -Wall
${common.build_flags}
-DHELTEC_V3
-DHAS_SX126X
-DHAS_SX1262
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:heltec_wireless_stick]
board = esp32-s3-devkitc-1
board_build.mcu = esp32s3
build_flags =
${common.build_flags}
-DHELTEC_WS
-DHAS_SX1262
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:heltec_wireless_stick_lite_v3]
board = esp32-s3-devkitc-1
board_build.mcu = esp32s3
build_flags =
${common.build_flags}
-DHELTEC_WSL_V3
-DHAS_SX1262
lib_deps =
${common.lib_deps}
[env:heltec_wireless_stick_lite_v3_display]
board = esp32-s3-devkitc-1
board_build.mcu = esp32s3
build_flags =
${common.build_flags}
-DHELTEC_WSL_V3_DISPLAY
-DHAS_SX1262
lib_deps =
${common.lib_deps}
[env:ESP32_DIY_LoRa]
board = esp32dev
build_flags =
-Werror -Wall
${common.build_flags}
-DESP32_DIY_LoRa
-DHAS_SX127X
-DHAS_SX1278
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:ESP32_DIY_LoRa_915]
board = esp32dev
build_flags =
${common.build_flags}
-DESP32_DIY_LoRa_915
-DHAS_SX1276
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:ESP32_DIY_1W_LoRa]
board = esp32dev
build_flags =
-Werror -Wall
${common.build_flags}
-DESP32_DIY_1W_LoRa
-DHAS_SX126X
-DHAS_SX1268
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
-DHAS_1W_LORA
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:ESP32_DIY_1W_LoRa_915]
board = esp32dev
build_flags =
${common.build_flags}
-DESP32_DIY_1W_LoRa_915
-DHAS_SX1262
-DHAS_1W_LORA
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:ESP32_DIY_1W_LoRa_LLCC68]
board = esp32dev
build_flags =
${common.build_flags}
-DESP32_DIY_1W_LoRa_LLCC68
-DHAS_LLCC68
-DHAS_1W_LORA
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:ESP32_DIY_1W_LoRa_Mesh_V1_2]
board = esp32dev
build_flags =
${common.build_flags}
-DESP32_DIY_1W_LoRa_Mesh_V1_2
-DHAS_SX1268
-DHAS_1W_LORA
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:ttgo-t-beam-v1_2]
board = ttgo-t-beam
build_flags =
-Werror -Wall
-DTTGO_T_Beam_V1_2
-DHAS_SX127X
${common.build_flags}
-DTTGO_T_BEAM_V1_2
-DHAS_SX1278
-DHAS_AXP2101
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
-DHAS_GPS
lib_deps =
${common.lib_deps}
${common.display_libs}
lewisxhe/XPowersLib @ 0.2.4
[env:ttgo-t-beam-v1_2_915]
board = ttgo-t-beam
build_flags =
${common.build_flags}
-DTTGO_T_BEAM_V1_2_915
-DHAS_SX1276
-DHAS_AXP2101
-DHAS_GPS
lib_deps =
${common.lib_deps}
${common.display_libs}
lewisxhe/XPowersLib @ 0.2.4
[env:ttgo-t-beam-v1]
board = ttgo-t-beam
build_flags =
-Werror -Wall
-DTTGO_T_Beam_V1_0
-DHAS_SX127X
${common.build_flags}
-DTTGO_T_BEAM_V1_0
-DHAS_SX1278
-DHAS_AXP192
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
-DHAS_GPS
lib_deps =
${common.lib_deps}
${common.display_libs}
lewisxhe/XPowersLib @ 0.2.4
[env:ttgo-t-beam-v1_915]
board = ttgo-t-beam
build_flags =
${common.build_flags}
-DTTGO_T_BEAM_V1_0_915
-DHAS_SX1276
-DHAS_AXP192
-DHAS_GPS
lib_deps =
${common.lib_deps}
${common.display_libs}
lewisxhe/XPowersLib @ 0.2.4
[env:ttgo-t-beam-v1_SX1268]
board = ttgo-t-beam
build_flags =
-Werror -Wall
-DTTGO_T_Beam_V1_0_SX1268
-DHAS_SX126X
${common.build_flags}
-DTTGO_T_BEAM_V1_0_SX1268
-DHAS_SX1268
-DHAS_AXP192
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
-DHAS_GPS
lib_deps =
${common.lib_deps}
${common.display_libs}
lewisxhe/XPowersLib @ 0.2.4
[env:ttgo-t-beam-v1_2_SX1262]
board = ttgo-t-beam
build_flags =
-Werror -Wall
-DTTGO_T_Beam_V1_2_SX1262
-DHAS_SX126X
${common.build_flags}
-DTTGO_T_BEAM_V1_2_SX1262
-DHAS_SX1262
-DHAS_AXP2101
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
-DHAS_GPS
lib_deps =
${common.lib_deps}
${common.display_libs}
lewisxhe/XPowersLib @ 0.2.4
[env:OE5HWN_MeshCom]
[env:ESP32_DIY_LoRa_A7670]
board = esp32dev
build_flags =
-Werror -Wall
-DOE5HWN_MeshCom
-DHAS_SX126X
-DHAS_SX1268
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
${common.build_flags}
-DESP32_DIY_LoRa_A7670
-DHAS_SX1278
-DHAS_A7670
lib_deps =
${common.lib_deps}
${common.display_libs}
vshymanskyy/TinyGSM @ 0.12.0
vshymanskyy/StreamDebugger @ 1.0.1
[env:heltec_wireless_stick]
board = heltec_wifi_lora_32_V3
[env:ESP32_DIY_LoRa_A7670_915]
board = esp32dev
build_flags =
${common.build_flags}
-DESP32_DIY_LoRa_A7670_915
-DHAS_SX1276
-DHAS_A7670
lib_deps =
${common.lib_deps}
${common.display_libs}
vshymanskyy/TinyGSM @ 0.12.0
vshymanskyy/StreamDebugger @ 1.0.1
[env:heltec_wireless_tracker]
board = esp32-s3-devkitc-1
board_build.mcu = esp32s3
build_flags =
-Werror -Wall
-DHELTEC_WS
-DHAS_SX126X
${common.build_flags}
-DHELTEC_WIRELESS_TRACKER
-DHAS_SX1262
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
-DHAS_GPS
-DGPS_BAUDRATE=115200
-DHAS_TFT
-D USER_SETUP_LOADED
-D TFT_WIDTH=80
-D TFT_HEIGHT=160
-D ST7735_DRIVER
-D ST7735_GREENTAB160x80
-D TFT_RGB_ORDER=TFT_BGR
-D TFT_MOSI=42
-D TFT_SCLK=41
-D TFT_CS=38
-D TFT_DC=40
-D TFT_RST=39
-D TFT_BL=21
-D TFT_BACKLIGHT_ON=1
-D TOUCH_CS=-1
-D LOAD_GLCD
-D LOAD_FONT2
-D LOAD_FONT4
-D LOAD_FONT6
-D LOAD_FONT7
-D LOAD_FONT8
-D SPI_FREQUENCY=27000000
-D USE_HSPI_PORT
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1
lib_deps =
${common.lib_deps}
bodmer/TFT_eSPI @ 2.5.43
[env:heltec_ht-ct62]
board = heltec_wireless_stick_lite
board_build.mcu = esp32c3
build_flags =
-Werror -Wall
${common.build_flags}
-DHELTEC_HTCT62
-DHAS_SX126X
-DHAS_SX1262
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:heltec_wireless_paper]
board = esp32-s3-devkitc-1
board_build.mcu = esp32s3
build_flags =
${common.build_flags}
-DHELTEC_WP
-DHAS_SX1262
-DHAS_EPAPER
lib_deps =
${common.lib_deps}
[env:OE5HWN_MeshCom]
board = esp32dev
build_flags =
${common.build_flags}
-DOE5HWN_MeshCom
-DHAS_SX1268
-DHAS_1W_LORA
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:WEMOS-LOLIN32-OLED-DIY]
board = lolin32
build_flags =
${common.build_flags}
-DWEMOS_LOLIN32_OLED_DIY_LoRa
-DHAS_SX1278
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:WEMOS-D1-R32-RA02]
board = wemos_d1_uno32
build_flags =
${common.build_flags}
-DWEMOS_D1_R32_RA02
-DHAS_SX1278
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:WEMOS_S2_MINI_DIY_LoRa]
board = lolin_s2_mini
build_flags =
${common.build_flags}
-DWEMOS_S2_MINI_DIY_LoRa
-DHAS_SX1278
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:esp32c3_DIY_1W_LoRa]
board = esp32-c3-devkitm-1
board_build.mcu = esp32c3
build_flags =
${common.build_flags}
-DESP32C3_DIY_1W_LoRa
-DHAS_SX1268
-DHAS_1W_LORA
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:esp32c3_DIY_1W_LoRa_915]
board = esp32-c3-devkitm-1
board_build.mcu = esp32c3
build_flags =
${common.build_flags}
-DESP32C3_DIY_1W_LoRa_915
-DHAS_SX1262
-DHAS_1W_LORA
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:ESP32_C3_OctopusLab_LoRa]
board = esp32-c3-devkitm-1
board_build.mcu = esp32c3
build_flags =
${common.build_flags}
-DESP32_C3_OctopusLab_LoRa
-DHAS_SX1268
-DRADIO_HAS_XTAL
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:QRPLabs_LightGateway_1_0]
board = esp32-s3-devkitc-1
board_build.mcu = esp32s3
build_flags =
${common.build_flags}
-DLIGHTGATEWAY_1_0
-DHAS_SX1268
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1
lib_deps =
${common.lib_deps}
${common.display_libs}
[env:ttgo_lora32_t3s3_v1_2]
board = esp32-s3-devkitc-1
board_build.mcu = esp32s3
board_upload.flash_size = 4MB
build_flags =
${common.build_flags}
-DTTGO_LORA32_T3S3_V1_2
-DHAS_SX1262
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1
lib_deps =
${common.lib_deps}
${common.display_libs}

205
src/A7670_utils.cpp Normal file
View File

@@ -0,0 +1,205 @@
#include "configuration.h"
#include "aprs_is_utils.h"
#include "boards_pinout.h"
#include "A7670_utils.h"
#include "lora_utils.h"
#include "display.h"
#include "utils.h"
#ifdef HAS_A7670
#define TINY_GSM_MODEM_SIM7600 //The AT instruction of A7670 is compatible with SIM7600
#define TINY_GSM_RX_BUFFER 1024 // Set RX buffer to 1Kb
#define SerialAT Serial1
#include <TinyGsmClient.h>
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, Serial);
TinyGsm modem(debugger);
extern Configuration Config;
extern String firstLine;
bool modemStartUp = false;
bool serverStartUp = false;
bool userBytesSended = false;
bool beaconBytesSended = false;
bool beaconSended = false;
bool stationBeacon = false;
extern bool modemLoggedToAPRSIS;
namespace A7670_Utils {
bool checkModemOn() {
bool modemReady = false;
Serial.print("Starting Modem ... ");
displayShow(firstLine, "Starting Modem...", " ", " ", 0);
pinMode(A7670_ResetPin, OUTPUT); //A7670 Reset
digitalWrite(A7670_ResetPin, LOW);
delay(100);
digitalWrite(A7670_ResetPin, HIGH);
delay(3000);
digitalWrite(A7670_ResetPin, LOW);
pinMode(A7670_PWR_PIN, OUTPUT);
digitalWrite(A7670_PWR_PIN, LOW);
delay(100);
digitalWrite(A7670_PWR_PIN, HIGH);
delay(1000);
digitalWrite(A7670_PWR_PIN, LOW);
int i = 20;
while (i) {
SerialAT.println("AT");
delay(500);
if (SerialAT.available()) {
String r = SerialAT.readString();
//Serial.println(r);
if ( r.indexOf("OK") >= 0 ) {
modemReady = true;
i = 1;
Serial.println("Modem Ready!\n");
displayShow(firstLine, "Starting Modem...", "---> Modem Ready", " ", 0);
return true;
}
}
if (!modemReady) {
delay(500);
}
i--;
}
return false;
}
void setup() {
SerialAT.begin(115200, SERIAL_8N1, A7670_RX_PIN, A7670_TX_PIN);
if (checkModemOn()) {;
delay(1000);
//setup_gps(); // if gps active / won't be need for now
} else {
displayShow(firstLine, "Starting Modem...", "---> Failed !!!", " ", 0);
Serial.println(F("*********** Failed to connect to the modem! ***********"));
}
}
bool checkATResponse(const String& ATMessage) {
int delayATMessage = 3000;
bool validAT = false;
//Serial.println(ATMessage);
int i = 10;
while (i) {
if (!validAT) {
SerialAT.println(ATMessage);
}
delay(500);
if (SerialAT.available()) {
String response = SerialAT.readString();
//Serial.println(response); // DEBUG of Modem AT message
if(response.indexOf("verified") >= 0) {
Serial.println("Logged! (User Validated)\n");
displayShow(firstLine, "Connecting APRS-IS...", "---> Logged!", " ", 1000);
Serial.println("#################### APRS-IS FEED ####################");
validAT = true;
i = 1;
delayATMessage = 0;
} else if (ATMessage == "AT+NETOPEN" && response.indexOf("OK") >= 0) {
Serial.println("Port Open!");
displayShow(firstLine, "Opening Port...", "---> Port Open", " ", 0);
validAT = true;
i = 1;
delayATMessage = 0;
} else if (ATMessage == "AT+NETOPEN" && response.indexOf("Network is already opened") >= 0) {
Serial.println("Port Open! (was already opened)");
displayShow(firstLine, "Opening Port...", "---> Port Open", " ", 0);
validAT = true;
i = 1;
delayATMessage = 0;
} else if (ATMessage.indexOf("AT+CIPOPEN") == 0 && response.indexOf("PB DONE") >= 0) {
Serial.println("Contacted!");
displayShow(firstLine, "Connecting APRS-IS...", "---> Contacted", " ", 0);
validAT = true;
i = 1;
delayATMessage = 0;
} else if (ATMessage.indexOf("AT+CIPSEND=0,") == 0 && response.indexOf(">") >= 0) {
Serial.print(".");
validAT = true;
i = 1;
delayATMessage = 0;
} else if (ATMessage.indexOf(Config.callsign) >= 3 && !modemLoggedToAPRSIS && response.indexOf("OK") >= 0 && !stationBeacon) { // login info
validAT = true;
delayATMessage = 0;
} else if (ATMessage.indexOf(Config.callsign) == 0 && !beaconSended && response.indexOf("OK") >= 0 && !stationBeacon) { // self beacon or querys
validAT = true;
i = 1;
delayATMessage = 0;
} else if (stationBeacon && response.indexOf("OK") >= 0) { //upload others beacons
validAT = true;
i = 1;
delayATMessage = 0;
}
}
delay(delayATMessage);
i--;
}
return validAT;
}
void APRS_IS_connect() {
String loginInfo = "user ";
loginInfo += Config.callsign;
loginInfo += " pass ";
loginInfo += String(Config.aprs_is.passcode);
loginInfo += " vers CA2RXU_LoRa_iGate 1.3 filter ";
loginInfo += Config.aprs_is.filter;
Serial.println("-----> Connecting to APRS IS");
while (!modemStartUp) {
Serial.print("Opening Port... ");
displayShow(firstLine, "Opening Port...", " ", " ", 0);
modemStartUp = checkATResponse("AT+NETOPEN");
delay(2000);
} while (!serverStartUp) {
Serial.print("Connecting APRS-IS Server... ");
displayShow(firstLine, "Connecting APRS-IS...", " ", " ", 0);
serverStartUp = checkATResponse("AT+CIPOPEN=0,\"TCP\",\"" + String(Config.aprs_is.server) + "\"," + String(Config.aprs_is.port));
delay(2000);
} while (!userBytesSended) {
Serial.print("Writing User Login Data ");
displayShow(firstLine, "Connecting APRS-IS...", "---> User Login Data", " ", 0);
userBytesSended = checkATResponse("AT+CIPSEND=0," + String(loginInfo.length()+1));
delay(2000);
} while (!modemLoggedToAPRSIS) {
Serial.print(".");
modemLoggedToAPRSIS = checkATResponse(loginInfo);
delay(2000);
}
}
void uploadToAPRSIS(const String& packet) {
beaconBytesSended = checkATResponse("AT+CIPSEND=0," + String(packet.length()+1));
delay(2000);
if (beaconBytesSended) {
Serial.print(".");
beaconSended = checkATResponse(packet);
}
if (!beaconSended) {
Serial.println("------------------------------------> UPLOAD FAILED!!!");
} else {
Serial.println("Packet Uploaded to APRS-IS!");
}
beaconBytesSended = false;
beaconSended = false;
}
void listenAPRSIS() {
if (SerialAT.available()) {
String packetAPRSIS = SerialAT.readStringUntil('\r');
packetAPRSIS.trim();
if (!packetAPRSIS.startsWith("#") && packetAPRSIS.indexOf("+IPD") == -1 && packetAPRSIS.indexOf("RECV") == -1 && packetAPRSIS.length() > 0) {
APRS_IS_Utils::processAPRSISPacket(packetAPRSIS);
}
}
delay(1);
}
}
#endif

17
src/A7670_utils.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef A7670_UTILS_H_
#define A7670_UTILS_H_
#include <Arduino.h>
namespace A7670_Utils {
bool checkModemOn();
void setup();
bool checkATResponse(const String& ATMessage);
void APRS_IS_connect();
void uploadToAPRSIS(const String& packet);
void listenAPRSIS();
}
#endif

View File

@@ -1,165 +1,137 @@
/*______________________________________________________________________________________________________________
██╗ ██████╗ ██████╗ █████╗ █████╗ ██████╗ ██████╗ ███████╗ ██╗ ██████╗ █████╗ ████████╗███████╗
██║ ██╔═══██╗██╔══██╗██╔══██╗ ██╔══██╗██╔══██╗██╔══██╗██╔════╝ ██║██╔════╝ ██╔══██╗╚══██╔══╝██╔════╝
██║ ██║ ██║██████╔╝███████║ ███████║██████╔╝██████╔╝███████╗ ██║██║ ███╗███████║ ██║ █████╗
██║ ██║ ██║██╔══██╗██╔══██║ ██╔══██║██╔═══╝ ██╔══██╗╚════██║ ██║██║ ██║██╔══██║ ██║ ██╔══╝
███████╗╚██████╔╝██║ ██║██║ ██║ ██║ ██║██║ ██║ ██║███████║ ██║╚██████╔╝██║ ██║ ██║ ███████╗
╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝
Ricardo Guzman - CA2RXU
https://github.com/richonguzman/LoRa_APRS_Tracker
(donations : http://paypal.me/richonguzman)
______________________________________________________________________________________________________________*/
#include <ElegantOTA.h>
#include <TinyGPS++.h>
#include <Arduino.h>
#include <WiFi.h>
#include <vector>
#include "configuration.h"
#include "battery_utils.h"
#include "aprs_is_utils.h"
#include "station_utils.h"
#include "boards_pinout.h"
#include "battery_utils.h"
#include "syslog_utils.h"
#include "pins_config.h"
#include "query_utils.h"
#include "power_utils.h"
#include "lora_utils.h"
#include "wifi_utils.h"
#include "digi_utils.h"
#include "gps_utils.h"
#include "bme_utils.h"
#include "web_utils.h"
#include "tnc_utils.h"
#include "ntp_utils.h"
#include "wx_utils.h"
#include "display.h"
#include "utils.h"
#include <ElegantOTA.h>
#include "battery_utils.h"
#ifdef HAS_A7670
#include "A7670_utils.h"
#endif
Configuration Config;
WiFiClient espClient;
String versionDate = "2024.10.29";
Configuration Config;
WiFiClient espClient;
#ifdef HAS_GPS
HardwareSerial gpsSerial(1);
TinyGPSPlus gps;
#endif
String versionDate = "2024.04.13";
uint8_t myWiFiAPIndex = 0;
int myWiFiAPSize = Config.wifiAPs.size();
WiFi_AP *currentWiFi = &Config.wifiAPs[myWiFiAPIndex];
uint8_t myWiFiAPIndex = 0;
int myWiFiAPSize = Config.wifiAPs.size();
WiFi_AP *currentWiFi = &Config.wifiAPs[myWiFiAPIndex];
bool isUpdatingOTA = false;
bool statusAfterBoot = true;
bool beaconUpdate = true;
uint32_t lastBeaconTx = 0;
uint32_t previousWiFiMillis = 0;
uint32_t lastScreenOn = millis();
bool isUpdatingOTA = false;
uint32_t lastBatteryCheck = 0;
uint32_t lastWiFiCheck = 0;
bool WiFiConnect = true;
bool WiFiConnected = false;
bool WiFiAutoAPStarted = false;
long WiFiAutoAPTime = false;
uint32_t lastBatteryCheck = 0;
uint32_t bmeLastReading = -60000;
String batteryVoltage;
std::vector<String> lastHeardStation;
std::vector<String> lastHeardStation_temp;
std::vector<String> packetBuffer;
std::vector<String> packetBuffer_temp;
bool backUpDigiMode = false;
bool modemLoggedToAPRSIS = false;
std::vector<ReceivedPacket> receivedPackets;
String firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, iGateBeaconPacket, iGateLoRaBeaconPacket;
String firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine;
//#define STARTUP_DELAY 5 //min
void setup() {
Serial.begin(115200);
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_HTCT62)
pinMode(batteryPin, INPUT);
#endif
#ifdef HAS_INTERNAL_LED
pinMode(internalLedPin, OUTPUT);
#endif
if (Config.externalVoltageMeasurement) {
pinMode(Config.externalVoltagePin, INPUT);
}
#if defined(TTGO_T_Beam_V1_0) || defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2) || defined(TTGO_T_Beam_V1_2_SX1262)
POWER_Utils::setup();
#endif
delay(1000);
Utils::setupDisplay();
Config.check();
LoRa_Utils::setup();
Utils::validateFreqs();
GPS_Utils::setup();
iGateBeaconPacket = GPS_Utils::generateBeacon();
iGateLoRaBeaconPacket = GPS_Utils::generateiGateLoRaBeacon();
#ifdef HELTEC_HTCT62
if (Config.lowPowerMode) {
gpio_wakeup_enable(GPIO_NUM_3, GPIO_INTR_HIGH_LEVEL);
esp_deep_sleep_enable_gpio_wakeup(GPIO_NUM_3, ESP_GPIO_WAKEUP_GPIO_HIGH);
long lastBeacon = 0;
LoRa_Utils::startReceive();
while (true) {
auto wakeup_reason = esp_sleep_get_wakeup_cause();
if (wakeup_reason == 7) { // packet received
Serial.println("Received packet");
String packet = LoRa_Utils::receivePacket();
Serial.println(packet);
if (Config.digi.mode == 2) { // If Digi enabled
DIGI_Utils::loop(packet); // Send received packet to Digi
}
if (packet.indexOf(Config.callsign + ":?APRSELP{") != -1) { // Send `?APRSELP` to exit low power
Serial.println("Got ?APRSELP message, exiting from low power mode");
break;
};
}
long time = esp_timer_get_time() / 1000000;
if (lastBeacon == 0 || time - lastBeacon >= Config.beacon.interval * 60) {
Serial.println("Sending beacon");
String comment = Config.beacon.comment;
if (Config.sendBatteryVoltage) {
comment += " Batt=" + String(BATTERY_Utils::checkBattery(),2) + "V";
}
if (Config.externalVoltageMeasurement) {
comment += " Ext=" + String(BATTERY_Utils::checkExternalVoltage(),2) + "V";
}
LoRa_Utils::sendNewPacket("APRS", iGateLoRaBeaconPacket + comment);
lastBeacon = time;
}
#ifdef STARTUP_DELAY // (TEST) just to wait for WiFi init of Routers
displayShow("", " STARTUP DELAY ...", "", "", 0);
delay(STARTUP_DELAY * 60 * 1000);
#endif
#ifdef HELTEC_HTCT62
if (Config.lowPowerMode) {
gpio_wakeup_enable(GPIO_NUM_3, GPIO_INTR_HIGH_LEVEL);
esp_deep_sleep_enable_gpio_wakeup(GPIO_NUM_3, ESP_GPIO_WAKEUP_GPIO_HIGH);
long lastBeacon = 0;
LoRa_Utils::startReceive();
while (true) {
auto wakeup_reason = esp_sleep_get_wakeup_cause();
if (wakeup_reason == 7) { // packet received
Serial.println("Received packet");
String packet = LoRa_Utils::receivePacket();
Serial.println(packet);
if (Config.digi.mode == 2) DIGI_Utils::processLoRaPacket(packet);
Serial.println("Sleeping");
if (packet.indexOf(Config.callsign + ":?APRSELP{") != -1) { // Send `?APRSELP` to exit low power
Serial.println("Got ?APRSELP message, exiting from low power mode");
break;
};
}
long time = esp_timer_get_time() / 1000000;
if (lastBeacon == 0 || time - lastBeacon >= Config.beacon.interval * 60) {
Serial.println("Sending beacon");
String comment = Config.beacon.comment;
if (Config.battery.sendInternalVoltage) comment += " Batt=" + String(BATTERY_Utils::checkInternalVoltage(),2) + "V";
if (Config.battery.sendExternalVoltage) comment += " Ext=" + String(BATTERY_Utils::checkExternalVoltage(),2) + "V";
LoRa_Utils::sendNewPacket(GPS_Utils::getiGateLoRaBeaconPacket() + comment);
lastBeacon = time;
}
long sleep = (Config.beacon.interval * 60) - (time - lastBeacon);
Serial.flush();
esp_sleep_enable_timer_wakeup(sleep * 1000000);
esp_light_sleep_start();
Serial.println("Waked up");
LoRa_Utils::startReceive();
Serial.println("Sleeping");
long sleep = (Config.beacon.interval * 60) - (time - lastBeacon);
Serial.flush();
esp_sleep_enable_timer_wakeup(sleep * 1000000);
esp_light_sleep_start();
Serial.println("Waked up");
}
Config.loramodule.rxActive = false;
}
Config.loramodule.rxActive = false;
}
#endif
#endif
DIGI_Utils::checkEcoMode();
WIFI_Utils::setup();
NTP_Utils::setup();
SYSLOG_Utils::setup();
BME_Utils::setup();
WX_Utils::setup();
WEB_Utils::setup();
TNC_Utils::setup();
#ifdef HAS_A7670
A7670_Utils::setup();
#endif
Utils::checkRebootMode();
}
void loop() {
WIFI_Utils::checkIfAutoAPShouldPowerOff();
WIFI_Utils::checkAutoAPTimeout();
if (isUpdatingOTA) {
ElegantOTA.loop();
@@ -172,40 +144,40 @@ void loop() {
thirdLine = Utils::getLocalIP();
WIFI_Utils::checkWiFi(); // Always use WiFi, not related to IGate/Digi mode
// Utils::checkWiFiInterval();
WIFI_Utils::checkWiFi();
if (Config.aprs_is.active && !espClient.connected()) {
APRS_IS_Utils::connect();
}
#ifdef HAS_A7670
if (Config.aprs_is.active && !modemLoggedToAPRSIS) A7670_Utils::APRS_IS_connect();
#else
if (Config.aprs_is.active && (WiFi.status() == WL_CONNECTED) && !espClient.connected()) APRS_IS_Utils::connect();
#endif
NTP_Utils::update();
TNC_Utils::loop();
Utils::checkDisplayInterval();
Utils::checkBeaconInterval();
APRS_IS_Utils::checkStatus(); // Need that to update display, maybe split this and send APRSIS status to display func?
String packet = "";
if (Config.loramodule.rxActive) {
packet = LoRa_Utils::receivePacket(); // We need to fetch LoRa packet above APRSIS and Digi
}
}
if (packet != "") {
if (Config.aprs_is.active) { // If APRSIS enabled
APRS_IS_Utils::processLoRaPacket(packet); // Send received packet to APRSIS
}
if (Config.digi.mode == 2) { // If Digi enabled
DIGI_Utils::loop(packet); // Send received packet to Digi
if (Config.loramodule.txActive && (Config.digi.mode == 2 || Config.digi.mode == 3 || backUpDigiMode)) { // If Digi enabled
STATION_Utils::clean25SegBuffer();
DIGI_Utils::processLoRaPacket(packet); // Send received packet to Digi
}
if (Config.tnc.enableServer) { // If TNC server enabled
TNC_Utils::sendToClients(packet); // Send received packet to TNC KISS
}
if (Config.tnc.enableSerial) { // If Serial KISS enabled
TNC_Utils::sendToSerial(packet); // Send received packet to Serial KISS
}
@@ -214,6 +186,10 @@ void loop() {
if (Config.aprs_is.active) { // If APRSIS enabled
APRS_IS_Utils::listenAPRSIS(); // listen received packet from APRSIS
}
STATION_Utils::processOutputPacketBuffer();
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
Utils::checkRebootTime();
Utils::checkSleepByLowBatteryVoltage(1);
}

View File

@@ -4,33 +4,40 @@
#include "station_utils.h"
#include "syslog_utils.h"
#include "query_utils.h"
#include "lora_utils.h"
#include "A7670_utils.h"
#include "digi_utils.h"
#include "display.h"
#include "utils.h"
extern Configuration Config;
extern WiFiClient espClient;
extern uint32_t lastScreenOn;
extern String firstLine;
extern String secondLine;
extern String thirdLine;
extern String fourthLine;
extern String fifthLine;
extern String sixthLine;
extern String seventhLine;
extern Configuration Config;
extern WiFiClient espClient;
extern uint32_t lastScreenOn;
extern String firstLine;
extern String secondLine;
extern String thirdLine;
extern String fourthLine;
extern String fifthLine;
extern String sixthLine;
extern String seventhLine;
extern bool modemLoggedToAPRSIS;
extern bool backUpDigiMode;
uint32_t lastRxTime = millis();
#ifdef HAS_A7670
extern bool stationBeacon;
#endif
namespace APRS_IS_Utils {
void upload(String line) {
void upload(const String& line) {
espClient.print(line + "\r\n");
}
void connect() {
uint8_t count = 0;
String aprsauth;
Serial.print("Connecting to APRS-IS ... ");
uint8_t count = 0;
while (!espClient.connect(Config.aprs_is.server.c_str(), Config.aprs_is.port) && count < 20) {
Serial.println("Didn't connect with server...");
delay(1000);
@@ -46,11 +53,15 @@ namespace APRS_IS_Utils {
}
else {
Serial.println("Connected!\n(Server: " + String(Config.aprs_is.server) + " / Port: " + String(Config.aprs_is.port) + ")");
// String filter = "t/m/" + Config.callsign + "/" + (String)Config.aprs_is.reportingDistance;
aprsauth = "user " + Config.callsign + " pass " + Config.aprs_is.passcode + " vers CA2RXU_LoRa_iGate 1.3 filter " + Config.aprs_is.filter;
upload(aprsauth);
String aprsAuth = "user ";
aprsAuth += Config.callsign;
aprsAuth += " pass ";
aprsAuth += Config.aprs_is.passcode;
aprsAuth += " vers CA2RXU_LoRa_iGate 2.0 filter ";
aprsAuth += Config.aprs_is.filter;
upload(aprsAuth);
delay(200);
}
}
@@ -59,73 +70,102 @@ namespace APRS_IS_Utils {
String wifiState, aprsisState;
if (WiFi.status() == WL_CONNECTED) {
wifiState = "OK";
}
else {
wifiState = "AP";
if (!Config.display.alwaysOn) {
display_toggle(true);
} else {
if (backUpDigiMode || Config.digi.ecoMode) {
wifiState = "--";
} else {
wifiState = "AP";
}
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
displayToggle(true);
}
lastScreenOn = millis();
}
if (!Config.aprs_is.active) {
aprsisState = "OFF";
} else {
#ifdef HAS_A7670
if (modemLoggedToAPRSIS) {
aprsisState = "OK";
} else {
aprsisState = "--";
}
#else
if (espClient.connected()) {
aprsisState = "OK";
} else {
aprsisState = "--";
}
#endif
if(aprsisState == "--" && !Config.display.alwaysOn && Config.display.timeout != 0) {
displayToggle(true);
lastScreenOn = millis();
}
}
else if (espClient.connected()) {
aprsisState = "OK";
}
else {
aprsisState = "--";
if (!Config.display.alwaysOn) {
display_toggle(true);
}
lastScreenOn = millis();
}
secondLine = "WiFi: " + wifiState + " APRS-IS: " + aprsisState;
secondLine = "WiFi: ";
secondLine += wifiState;
secondLine += " APRS-IS: ";
secondLine += aprsisState;
}
String createPacket(String packet) {
String checkForStartingBytes(const String& packet) {
if (packet.indexOf("\x3c\xff\x01") != -1) {
return packet.substring(0, packet.indexOf("\x3c\xff\x01"));
} else {
return packet;
}
}
String buildPacketToUpload(const String& packet) {
String buildedPacket = packet.substring(3, packet.indexOf(":"));
if (!(Config.aprs_is.active && Config.digi.mode == 0)) { // Check if NOT only IGate
return packet.substring(3, packet.indexOf(":")) + ",qAR," + Config.callsign + packet.substring(packet.indexOf(":"));
}
else {
return packet.substring(3, packet.indexOf(":")) + ",qAO," + Config.callsign + packet.substring(packet.indexOf(":"));
buildedPacket += ",qAR,";
} else {
buildedPacket += ",qAO,";
}
buildedPacket += Config.callsign;
buildedPacket += checkForStartingBytes(packet.substring(packet.indexOf(":")));
return buildedPacket;
}
bool processReceivedLoRaMessage(String sender, String packet) {
String ackMessage, receivedMessage;
bool processReceivedLoRaMessage(const String& sender, const String& packet, bool thirdParty) {
String receivedMessage;
if (packet.indexOf("{") > 0) { // ack?
ackMessage = "ack" + packet.substring(packet.indexOf("{") + 1);
String ackMessage = "ack";
ackMessage.concat(packet.substring(packet.indexOf("{") + 1));
ackMessage.trim();
delay(4000);
//Serial.println(ackMessage);
String addToBuffer = Config.callsign;
addToBuffer += ">APLRG1";
if (!thirdParty) addToBuffer += ",RFONLY";
if (Config.beacon.path != "") {
addToBuffer += ",";
addToBuffer += Config.beacon.path;
}
addToBuffer += "::";
String processedSender = sender;
for (int i = sender.length(); i < 9; i++) {
sender += ' ';
}
if (Config.beacon.path == "") {
LoRa_Utils::sendNewPacket("APRS", Config.callsign + ">APLRG1,RFONLY::" + sender + ":" + ackMessage);
} else {
LoRa_Utils::sendNewPacket("APRS", Config.callsign + ">APLRG1,RFONLY," + Config.beacon.path + "::" + sender + ":" + ackMessage);
processedSender += ' ';
}
addToBuffer += processedSender;
addToBuffer += ":";
addToBuffer += ackMessage;
STATION_Utils::addToOutputPacketBuffer(addToBuffer);
receivedMessage = packet.substring(packet.indexOf(":") + 1, packet.indexOf("{"));
}
else {
} else {
receivedMessage = packet.substring(packet.indexOf(":") + 1);
}
if (receivedMessage.indexOf("?") == 0) {
delay(2000);
if (!Config.display.alwaysOn) {
display_toggle(true);
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
displayToggle(true);
}
LoRa_Utils::sendNewPacket("APRS", QUERY_Utils::process(receivedMessage, sender, "LoRa"));
STATION_Utils::addToOutputPacketBuffer(QUERY_Utils::process(receivedMessage, sender, false, thirdParty));
lastScreenOn = millis();
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, "Callsign = " + sender, "TYPE --> QUERY", 0);
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, "Callsign = " + sender, "TYPE --> QUERY", 0);
return true;
}
else {
@@ -133,106 +173,181 @@ namespace APRS_IS_Utils {
}
}
void processLoRaPacket(String packet) {
if (espClient.connected()) {
bool queryMessage = false;
String aprsPacket, Sender, AddresseeAndMessage, Addressee;
void processLoRaPacket(const String& packet) {
if (espClient.connected() || modemLoggedToAPRSIS) {
if (packet != "") {
if ((packet.substring(0, 3) == "\x3c\xff\x01") && (packet.indexOf("TCPIP") == -1) && (packet.indexOf("NOGATE") == -1) && (packet.indexOf("RFONLY") == -1)) {
Sender = packet.substring(3, packet.indexOf(">"));
STATION_Utils::updateLastHeard(Sender);
//STATION_Utils::updatePacketBuffer(packet);
Utils::typeOfPacket(aprsPacket, "LoRa-APRS");
if (Sender != Config.callsign) { // avoid listening yourself by digirepeating
AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2);
Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
Addressee.trim();
if (packet.indexOf("::") > 10 && Addressee == Config.callsign) { // its a message for me!
queryMessage = processReceivedLoRaMessage(Sender, AddresseeAndMessage);
}
if (!queryMessage) {
aprsPacket = createPacket(packet);
if (!Config.display.alwaysOn) {
display_toggle(true);
}
lastScreenOn = millis();
upload(aprsPacket);
Utils::println("---> Uploaded to APRS-IS");
if ((packet.substring(0, 3) == "\x3c\xff\x01") && (packet.indexOf("NOGATE") == -1) && (packet.indexOf("RFONLY") == -1)) {
int firstColonIndex = packet.indexOf(":");
if (firstColonIndex > 5 && firstColonIndex < (packet.length() - 1) && packet[firstColonIndex + 1] != '}' && packet.indexOf("TCPIP") == -1) {
const String& Sender = packet.substring(3, packet.indexOf(">"));
if (Sender != Config.callsign && Utils::checkValidCallsign(Sender)) {
STATION_Utils::updateLastHeard(Sender);
Utils::typeOfPacket(aprsPacket, "LoRa-APRS");
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
Utils::typeOfPacket(packet.substring(3), 0); // LoRa-APRS
const String& AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2);
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
Addressee.trim();
bool queryMessage = false;
if (packet.indexOf("::") > 10 && Addressee == Config.callsign) { // its a message for me!
queryMessage = processReceivedLoRaMessage(Sender, checkForStartingBytes(AddresseeAndMessage), false);
}
if (!queryMessage) {
const String& aprsPacket = buildPacketToUpload(packet);
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
displayToggle(true);
}
lastScreenOn = millis();
#ifdef HAS_A7670
stationBeacon = true;
A7670_Utils::uploadToAPRSIS(aprsPacket);
stationBeacon = false;
#else
upload(aprsPacket);
#endif
Utils::println("---> Uploaded to APRS-IS");
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
}
}
}
}
}
}
}
}
void processAPRSISPacket(String packet) {
String Sender, AddresseeAndMessage, Addressee, receivedMessage;
String buildPacketToTx(const String& aprsisPacket, uint8_t packetType) {
String packet = aprsisPacket;
packet.trim();
String outputPacket = Config.callsign;
outputPacket += ">APLRG1";
if (Config.beacon.path != "") {
outputPacket += ",";
outputPacket += Config.beacon.path;
}
outputPacket += ":}";
outputPacket += packet.substring(0, packet.indexOf(",")); // Callsign>Tocall
outputPacket.concat(",TCPIP,");
outputPacket.concat(Config.callsign);
outputPacket.concat("*");
switch (packetType) {
case 0: // gps
if (packet.indexOf(":=") > 0) {
outputPacket += packet.substring(packet.indexOf(":="));
} else {
outputPacket += packet.substring(packet.indexOf(":!"));
}
break;
case 1: // messages
outputPacket += packet.substring(packet.indexOf("::"));
break;
case 2: // status
outputPacket += packet.substring(packet.indexOf(":>"));
break;
case 3: // telemetry
outputPacket += packet.substring(packet.indexOf("::"));
break;
case 4: // mic-e
if (packet.indexOf(":`") > 0) {
outputPacket += packet.substring(packet.indexOf(":`"));
} else {
outputPacket += packet.substring(packet.indexOf(":'"));
}
break;
case 5: // object
outputPacket += packet.substring(packet.indexOf(":;"));
break;
}
return outputPacket;
}
void processAPRSISPacket(const String& packet) {
if (!packet.startsWith("#")) {
if (packet.indexOf("::") > 0) {
Sender = packet.substring(0, packet.indexOf(">"));
AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2);
Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
if (Config.aprs_is.messagesToRF && packet.indexOf("::") > 0) {
String Sender = packet.substring(0, packet.indexOf(">"));
const String& AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2);
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
Addressee.trim();
if (Addressee == Config.callsign) { // its for me!
String receivedMessage;
if (AddresseeAndMessage.indexOf("{") > 0) { // ack?
String ackMessage = "ack" + AddresseeAndMessage.substring(AddresseeAndMessage.indexOf("{") + 1);
String ackMessage = "ack";
ackMessage += AddresseeAndMessage.substring(AddresseeAndMessage.indexOf("{") + 1);
ackMessage.trim();
delay(4000);
for (int i = Sender.length(); i < 9; i++) {
Sender += ' ';
}
String ackPacket = Config.callsign + ">APLRG1,TCPIP,qAC::" + Sender + ":" + ackMessage;// + "\n";
upload(ackPacket);
String ackPacket = Config.callsign;
ackPacket += ">APLRG1,TCPIP,qAC::";
ackPacket += Sender;
ackPacket += ":";
ackPacket += ackMessage;
#ifdef HAS_A7670
A7670_Utils::uploadToAPRSIS(ackPacket);
#else
upload(ackPacket);
#endif
receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":") + 1, AddresseeAndMessage.indexOf("{"));
} else {
receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":") + 1);
}
if (receivedMessage.indexOf("?") == 0) {
Utils::println("Received Query APRS-IS : " + packet);
String queryAnswer = QUERY_Utils::process(receivedMessage, Sender, "APRSIS");
String queryAnswer = QUERY_Utils::process(receivedMessage, Sender, true, false);
//Serial.println("---> QUERY Answer : " + queryAnswer.substring(0,queryAnswer.indexOf("\n")));
if (!Config.display.alwaysOn) {
display_toggle(true);
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
displayToggle(true);
}
lastScreenOn = millis();
delay(500);
upload(queryAnswer);
SYSLOG_Utils::log("APRSIS Tx", queryAnswer, 0, 0, 0);
#ifdef HAS_A7670
A7670_Utils::uploadToAPRSIS(queryAnswer);
#else
upload(queryAnswer);
#endif
SYSLOG_Utils::log(2, queryAnswer, 0, 0.0, 0); // APRSIS TX
fifthLine = "APRS-IS ----> APRS-IS";
sixthLine = Config.callsign;
for (int j = sixthLine.length();j < 9;j++) {
sixthLine += " ";
}
sixthLine += "> " + Sender;
seventhLine = "QUERY = " + receivedMessage;
sixthLine += "> ";
sixthLine += Sender;
seventhLine = "QUERY = ";
seventhLine += receivedMessage;
}
} else {
Utils::print("Received from APRS-IS : " + packet);
if (Config.aprs_is.toRF && STATION_Utils::wasHeard(Addressee)) {
LoRa_Utils::sendNewPacket("APRS", LoRa_Utils::generatePacket(packet));
display_toggle(true);
Utils::print("Received Message from APRS-IS : " + packet);
if (STATION_Utils::wasHeard(Addressee)) {
STATION_Utils::addToOutputPacketBuffer(buildPacketToTx(packet, 1));
displayToggle(true);
lastScreenOn = millis();
Utils::typeOfPacket(packet, "APRS-LoRa");
Utils::typeOfPacket(packet, 1); // APRS-LoRa
}
}
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
} else if (Config.aprs_is.objectsToRF && packet.indexOf(":;") > 0) {
Utils::println("Received Object from APRS-IS : " + packet);
STATION_Utils::addToOutputPacketBuffer(buildPacketToTx(packet, 5));
displayToggle(true);
lastScreenOn = millis();
Utils::typeOfPacket(packet, 1); // APRS-LoRa
}
}
}
void listenAPRSIS() {
if (espClient.connected()) {
if (espClient.available()) {
String aprsisPacket = espClient.readStringUntil('\r');
// Serial.println(aprsisPacket);
processAPRSISPacket(aprsisPacket);
#ifdef HAS_A7670
A7670_Utils::listenAPRSIS();
#else
if (espClient.connected()) {
if (espClient.available()) {
String aprsisPacket = espClient.readStringUntil('\r');
// Serial.println(aprsisPacket);
processAPRSISPacket(aprsisPacket);
lastRxTime = millis();
}
}
}
#endif
}
}

View File

@@ -6,14 +6,18 @@
namespace APRS_IS_Utils {
void upload(String line);
void connect();
void checkStatus();
String createPacket(String unprocessedPacket);
bool processReceivedLoRaMessage(String sender, String packet);
void processLoRaPacket(String packet);
void processAPRSISPacket(String packet);
void listenAPRSIS();
void upload(const String& line);
void connect();
void checkStatus();
String checkForStartingBytes(const String& packet);
String buildPacketToUpload(const String& packet);
bool processReceivedLoRaMessage(const String& sender, const String& packet, bool thirdParty);
void processLoRaPacket(const String& packet);
String buildPacketToTx(const String& aprsisPacket, uint8_t packetType);
void processAPRSISPacket(const String& packet);
void listenAPRSIS();
}

View File

@@ -1,18 +1,47 @@
#include <Arduino.h>
#include "battery_utils.h"
#include "configuration.h"
#include "pins_config.h"
#include "boards_pinout.h"
#include "power_utils.h"
#include "utils.h"
extern Configuration Config;
extern uint32_t lastBatteryCheck;
extern Configuration Config;
extern uint32_t lastBatteryCheck;
float adcReadingTransformation = (3.3/4095);
float voltageDividerCorrection = 0.288;
bool shouldSleepLowVoltage = false;
// for External Voltage Measurment (MAX = 15Volts !!!)
float R1 = 100.000; //in Kilo-Ohms
float R2 = 27.000; //in Kilo-Ohms
float readingCorrection = 0.125;
float multiplyCorrection = 0.035;
float adcReadingTransformation = (3.3/4095);
float voltageDividerCorrection = 0.288;
float readingCorrection = 0.125;
float multiplyCorrection = 0.035;
float voltageDividerTransformation = 0.0;
int telemetryCounter = random(1,999);
#ifdef HAS_ADC_CALIBRATION
#include <esp_adc_cal.h>
#if defined(TTGO_LORA32_V2_1) || defined(TTGO_LORA32_V2_1_915)
#define InternalBattery_ADC_Channel ADC1_CHANNEL_7 // t_lora32 pin35
#define ExternalVoltage_ADC_Channel ADC1_CHANNEL_6 // t_lora32 pin34
#endif
#if CONFIG_IDF_TARGET_ESP32
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_VREF
#elif CONFIG_IDF_TARGET_ESP32S2
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP
#elif CONFIG_IDF_TARGET_ESP32C3
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP
#elif CONFIG_IDF_TARGET_ESP32S3
#define ADC_EXAMPLE_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP_FIT
#endif
esp_adc_cal_characteristics_t adc_chars;
#endif
bool calibrationEnable = false;
namespace BATTERY_Utils {
@@ -21,53 +50,217 @@ namespace BATTERY_Utils {
return (voltage - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
float checkBattery() {
int sample;
int sampleSum = 0;
for (int i = 0; i < 100; i++) {
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_HTCT62)
sample = analogRead(batteryPin);
void adcCalibration() {
#ifdef HAS_ADC_CALIBRATION
if (calibrationEnable) {
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(InternalBattery_ADC_Channel, ADC_ATTEN_DB_12);
adc1_config_channel_atten(ExternalVoltage_ADC_Channel, ADC_ATTEN_DB_12);
}
#endif
}
void adcCalibrationCheck() {
#ifdef HAS_ADC_CALIBRATION
esp_err_t ret;
ret = esp_adc_cal_check_efuse(ADC_EXAMPLE_CALI_SCHEME);
/*if (ret == ESP_ERR_NOT_SUPPORTED) {
Serial.println("Calibration scheme not supported, skip software calibration");
} else if (ret == ESP_ERR_INVALID_VERSION) {
Serial.println("eFuse not burnt, skip software calibration");
} else */
if (ret == ESP_OK) {
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_12, ADC_WIDTH_BIT_12, 1100, &adc_chars);
//Serial.printf("eFuse Vref:%u mV\n", adc_chars.vref);
calibrationEnable = true;
} /*else {
Serial.println("Invalid Calibration Arg");
}*/
#endif
}
void setup() {
if ((Config.battery.sendExternalVoltage || Config.battery.monitorExternalVoltage) && Config.battery.voltageDividerR2 != 0) voltageDividerTransformation = (Config.battery.voltageDividerR1 + Config.battery.voltageDividerR2) / Config.battery.voltageDividerR2;
#if defined(HAS_ADC_CALIBRATION)
if (Config.battery.sendInternalVoltage || Config.battery.monitorInternalVoltage || Config.battery.sendExternalVoltage || Config.battery.monitorExternalVoltage) {
adcCalibrationCheck();
adcCalibration();
}
#endif
}
float checkInternalVoltage() {
#if defined(HAS_AXP192) || defined(HAS_AXP2101)
if(POWER_Utils::isBatteryConnected()) {
return POWER_Utils::getBatteryVoltage();
} else {
return 0.0;
}
#else
int sample;
int sampleSum = 0;
#ifdef ADC_CTRL
#if defined(HELTEC_WIRELESS_TRACKER)
digitalWrite(ADC_CTRL, HIGH);
#endif
#if defined(HELTEC_V3) || defined(HELTEC_V2) || defined(HELTEC_WSL_V3) || defined(HELTEC_WP)
digitalWrite(ADC_CTRL, LOW);
#endif
#endif
#if defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
sample = 0;
for (int i = 0; i < 100; i++) {
#if defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_LoRa_915) || defined(ESP32_DIY_1W_LoRa) || defined(ESP32_DIY_1W_LoRa_915)
sample = 0;
#else
#ifdef HAS_ADC_CALIBRATION
if (calibrationEnable){
sample = adc1_get_raw(InternalBattery_ADC_Channel);
} else {
sample = analogRead(BATTERY_PIN);
}
#else
#ifdef BATTERY_PIN
sample = analogRead(BATTERY_PIN);
#else
sample = 0;
#endif
#endif
#endif
sampleSum += sample;
delayMicroseconds(50);
}
#ifdef ADC_CTRL
#if defined(HELTEC_WIRELESS_TRACKER)
digitalWrite(ADC_CTRL, LOW);
#endif
#if defined(HELTEC_V3) || defined(HELTEC_V2) || defined(HELTEC_WSL_V3) || defined(HELTEC_WP)
digitalWrite(ADC_CTRL, HIGH);
#endif
#ifdef HELTEC_WP
double inputDivider = (1.0 / (10.0 + 10.0)) * 10.0; // The voltage divider is a 10k + 10k resistor in series
#else
double inputDivider = (1.0 / (390.0 + 100.0)) * 100.0; // The voltage divider is a 390k + 100k resistor in series, 100k on the low side.
#endif
return (((sampleSum/100) * adcReadingTransformation) / inputDivider) + 0.285; // Yes, this offset is excessive, but the ADC on the ESP32s3 is quite inaccurate and noisy. Adjust to own measurements.
#else
#ifdef HAS_ADC_CALIBRATION
if (calibrationEnable){
float voltage = esp_adc_cal_raw_to_voltage(sampleSum / 100, &adc_chars);
voltage *= 2; // for 100K/100K voltage divider
voltage /= 1000;
return voltage;
} else {
return (2 * (sampleSum/100) * adcReadingTransformation) + voltageDividerCorrection; // raw voltage without mapping
}
#else
return (2 * (sampleSum/100) * adcReadingTransformation) + voltageDividerCorrection; // raw voltage without mapping
#endif
#endif
sampleSum += sample;
delayMicroseconds(50);
}
float voltage = (2 * (sampleSum/100) * adcReadingTransformation) + voltageDividerCorrection;
return voltage; // raw voltage without mapping
// return mapVoltage(voltage, 3.34, 4.71, 3.0, 4.2); // mapped voltage
// return mapVoltage(voltage, 3.34, 4.71, 3.0, 4.2); // mapped voltage
#endif
}
float checkExternalVoltage() {
int sample;
int sampleSum = 0;
for (int i = 0; i < 100; i++) {
sample = analogRead(Config.externalVoltagePin);
#ifdef HAS_ADC_CALIBRATION
if (calibrationEnable){
sample = adc1_get_raw(ExternalVoltage_ADC_Channel);
} else {
sample = analogRead(Config.battery.externalVoltagePin);
}
#else
sample = analogRead(Config.battery.externalVoltagePin);
#endif
sampleSum += sample;
delayMicroseconds(50);
delayMicroseconds(50);
}
float voltage = ((((sampleSum/100)* adcReadingTransformation) + readingCorrection) * ((R1+R2)/R2)) - multiplyCorrection;
return voltage; // raw voltage without mapping
float extVoltage;
#ifdef HAS_ADC_CALIBRATION
if (calibrationEnable){
extVoltage = esp_adc_cal_raw_to_voltage(sampleSum / 100, &adc_chars) * voltageDividerTransformation; // in mV
extVoltage /= 1000;
} else {
extVoltage = ((((sampleSum/100)* adcReadingTransformation) + readingCorrection) * voltageDividerTransformation) - multiplyCorrection;
}
#else
extVoltage = ((((sampleSum/100)* adcReadingTransformation) + readingCorrection) * voltageDividerTransformation) - multiplyCorrection;
#endif
return extVoltage; // raw voltage without mapping
// return mapVoltage(voltage, 5.05, 6.32, 4.5, 5.5); // mapped voltage
}
void checkIfShouldSleep() {
if (lastBatteryCheck == 0 || millis() - lastBatteryCheck >= 15 * 60 * 1000) {
lastBatteryCheck = millis();
float voltage = checkBattery();
if (voltage < Config.lowVoltageCutOff) {
lastBatteryCheck = millis();
if (checkInternalVoltage() < Config.lowVoltageCutOff) {
ESP.deepSleep(1800000000); // 30 min sleep (60s = 60e6)
}
}
}
void startupBatteryHealth() {
#ifdef BATTERY_PIN
if (Config.battery.monitorInternalVoltage && checkInternalVoltage() < Config.battery.internalSleepVoltage + 0.1) {
shouldSleepLowVoltage = true;
}
#endif
#ifndef HELTEC_WP
if (Config.battery.monitorExternalVoltage && checkExternalVoltage() < Config.battery.externalSleepVoltage + 0.1) {
shouldSleepLowVoltage = true;
}
#endif
if (shouldSleepLowVoltage) {
Utils::checkSleepByLowBatteryVoltage(0);
}
}
String generateEncodedTelemetryBytes(float value, bool firstBytes, byte voltageType) { // 0 = internal battery(0-4,2V) , 1 = external battery(0-15V)
String encodedBytes;
int tempValue;
if (firstBytes) {
tempValue = value;
} else {
switch (voltageType) {
case 0:
tempValue = value * 100; // Internal voltage calculation
break;
case 1:
tempValue = (value * 100) / 2; // External voltage calculation
break;
default:
tempValue = value;
break;
}
}
int firstByte = tempValue / 91;
tempValue -= firstByte * 91;
encodedBytes = char(firstByte + 33);
encodedBytes += char(tempValue + 33);
return encodedBytes;
}
String generateEncodedTelemetry() {
String telemetry = "|";
telemetry += generateEncodedTelemetryBytes(telemetryCounter, true, 0);
telemetryCounter++;
if (telemetryCounter == 1000) {
telemetryCounter = 0;
}
if (Config.battery.sendInternalVoltage) telemetry += generateEncodedTelemetryBytes(checkInternalVoltage(), false, 0);
if (Config.battery.sendExternalVoltage) telemetry += generateEncodedTelemetryBytes(checkExternalVoltage(), false, 1);
telemetry += "|";
return telemetry;
}
}

View File

@@ -6,9 +6,16 @@
namespace BATTERY_Utils {
float checkBattery();
float checkExternalVoltage();
void checkIfShouldSleep();
void adcCalibration();
void adcCalibrationCheck();
void setup();
float checkInternalVoltage();
float checkExternalVoltage();
void checkIfShouldSleep(); // ????
void startupBatteryHealth();
String generateEncodedTelemetryBytes(float value, bool firstBytes, byte voltageType);
String generateEncodedTelemetry();
}

View File

@@ -1,185 +0,0 @@
#include "bme_utils.h"
#include "configuration.h"
#include "gps_utils.h"
#include "display.h"
#define SEALEVELPRESSURE_HPA (1013.25)
#define HEIGHT_CORRECTION 0 // in meters
#define CORRECTION_FACTOR (8.2296) // for meters
extern Configuration Config;
extern String fifthLine;
extern uint32_t bmeLastReading;
float newHum, newTemp, newPress, newGas;
namespace BME_Utils {
#ifdef BME280Sensor
Adafruit_BME280 bme;
#endif
#ifdef BMP280Sensor
Adafruit_BMP280 bme;
#endif
#ifdef BME680Sensor
Adafruit_BME680 bme;
#endif
void setup() {
if (Config.bme.active) {
bool status;
status = bme.begin(0x76); // Don't forget to join pins for righ direction on BME280!
if (!status) {
Serial.println("Could not find a valid BME280 or BMP280 sensor, check wiring!");
show_display("ERROR", "", "BME/BMP sensor active", "but no sensor found...");
while (1); // sacar esto para que quede pegado si no encuentra BME280
} else {
#ifdef BME280Sensor
bme.setSampling(Adafruit_BME280::MODE_FORCED,
Adafruit_BME280::SAMPLING_X1,
Adafruit_BME280::SAMPLING_X1,
Adafruit_BME280::SAMPLING_X1,
Adafruit_BME280::FILTER_OFF
);
Serial.println("init : BME280 Module ... done!");
#endif
#ifdef BMP280Sensor
bme.setSampling(Adafruit_BMP280::MODE_FORCED,
Adafruit_BMP280::SAMPLING_X1,
Adafruit_BMP280::SAMPLING_X1,
Adafruit_BMP280::FILTER_OFF
);
Serial.println("init : BMP280 Module ... done!");
#endif
#ifdef BME680Sensor
bme.setTemperatureOversampling(BME680_OS_1X);
bme.setHumidityOversampling(BME680_OS_1X);
bme.setPressureOversampling(BME680_OS_1X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_0);
Serial.println("init : BME680 Module ... done!");
#endif
}
} else {
Serial.println("(BME/BMP sensor not 'active' in 'igate_conf.json')");
}
}
String generateTempString(float bmeTemp) {
String strTemp;
strTemp = String((int)bmeTemp);
switch (strTemp.length()) {
case 1:
return "00" + strTemp;
break;
case 2:
return "0" + strTemp;
break;
case 3:
return strTemp;
break;
default:
return "-999";
}
}
String generateHumString(float bmeHum) {
String strHum;
strHum = String((int)bmeHum);
switch (strHum.length()) {
case 1:
return "0" + strHum;
break;
case 2:
return strHum;
break;
case 3:
if ((int)bmeHum == 100) {
return "00";
} else {
return "-99";
}
break;
default:
return "-99";
}
}
String generatePresString(float bmePress) {
String strPress;
strPress = String((int)bmePress);
switch (strPress.length()) {
case 1:
return "000" + strPress + "0";
break;
case 2:
return "00" + strPress + "0";
break;
case 3:
return "0" + strPress + "0";
break;
case 4:
return strPress + "0";
break;
case 5:
return strPress;
break;
default:
return "-99999";
}
}
String readDataSensor() {
String wx, tempStr, humStr, presStr;
uint32_t lastReading = millis() - bmeLastReading;
if (lastReading > 60*1000) {
#if defined(BME280Sensor) || defined(BMP280Sensor)
bme.takeForcedMeasurement();
newTemp = bme.readTemperature();
newPress = (bme.readPressure() / 100.0F);
#ifdef BME280Sensor
newHum = bme.readHumidity();
#endif
#ifdef BMP280Sensor
newHum = 0;
#endif
#endif
#ifdef BME680Sensor
bme.performReading();
delay(50);
if (bme.endReading()) {
newTemp = bme.temperature;
newPress = (bme.pressure / 100.0F);
newHum = bme.humidity;
newGas = bme.gas_resistance / 1000.0; // in Kilo ohms
}
#endif
bmeLastReading = millis();
}
if (isnan(newTemp) || isnan(newHum) || isnan(newPress)) {
Serial.println("BME/BMP Module data failed");
wx = ".../...g...t...r...p...P...h..b.....";
fifthLine = "";
return wx;
} else {
tempStr = generateTempString((newTemp * 1.8) + 32);
#if defined(BME280Sensor) || defined(BME680Sensor)
humStr = generateHumString(newHum);
#endif
#ifdef BMP280Sensor
humStr = "..";
#endif
presStr = generatePresString(newPress + (HEIGHT_CORRECTION/CORRECTION_FACTOR));
fifthLine = "BME-> " + String(int(newTemp))+"C " + humStr + "% " + presStr.substring(0,4) + "hPa";
wx = ".../...g...t" + tempStr + "r...p...P...h" + humStr + "b" + presStr;
#ifdef BME680Sensor
wx += "Gas: " + String(newGas) + "Kohms ";
#endif
return wx;
}
}
}

View File

@@ -1,33 +0,0 @@
#ifndef BME_UTILS_H_
#define BME_UTILS_H_
#include <Arduino.h>
#include <Adafruit_Sensor.h>
#define BME280Sensor // its set by default but you should comment it with "//"
//#define BMP280Sensor // and delete "//" from the one you want to use.
//#define BME680Sensor
#ifdef BME280Sensor
#include <Adafruit_BME280.h>
#endif
#ifdef BMP280Sensor
#include <Adafruit_BMP280.h>
#endif
#ifdef BME680Sensor
#include <Adafruit_BME680.h>
#endif
namespace BME_Utils {
void setup();
String generateTempString(float bmeTemp);
String generateHumString(float bmeHum);
String generatePresString(float bmePress);
String readDataSensor();
}
#endif

331
src/boards_pinout.h Normal file
View File

@@ -0,0 +1,331 @@
#ifndef PINS_CONFIG_H_
#define PINS_CONFIG_H_
#include <Arduino.h>
#undef OLED_SDA
#undef OLED_SCL
#undef OLED_RST
// LORA MODULES
#if defined(TTGO_LORA32_V2_1) || defined(HELTEC_V2) || defined(ESP32_DIY_LoRa) || defined(TTGO_T_BEAM_V1_2) || defined(TTGO_T_BEAM_V1_0) || defined(TTGO_LORA32_V2_1_915) || defined(ESP32_DIY_LoRa_915) || defined(TTGO_T_BEAM_V1_2_915) || defined(TTGO_T_BEAM_V1_0_915)
#define RADIO_SCLK_PIN 5 // GPIO5 - SX1278 SCK
#define RADIO_MISO_PIN 19 // GPIO19 - SX1278 MISO
#define RADIO_MOSI_PIN 27 // GPIO27 - SX1278 MOSI
#define RADIO_CS_PIN 18 // GPIO18 - SX1278 CS ---> NSS
#define RADIO_RST_PIN 14 // GPIO14 - SX1278 RST
#define RADIO_BUSY_PIN 26 // GPIO26 - SX1278 IRQ ---->DIO0
#endif
#if defined(HELTEC_V3) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY) || defined(HELTEC_WIRELESS_TRACKER) || defined(HELTEC_WS) || defined(HELTEC_WP)
#define RADIO_SCLK_PIN 9 // SX1262 SCK
#define RADIO_MISO_PIN 11 // SX1262 MISO
#define RADIO_MOSI_PIN 10 // SX1262 MOSI
#define RADIO_CS_PIN 8 // SX1262 NSS
#define RADIO_RST_PIN 12 // SX1262 RST
#define RADIO_DIO1_PIN 14 // SX1262 DIO1
#define RADIO_BUSY_PIN 13 // SX1262 BUSY
#endif
#if defined(ESP32_DIY_1W_LoRa) || defined(ESP32_DIY_1W_LoRa_915) || defined(ESP32_DIY_1W_LoRa_LLCC68) // Ebyte E22 400M30S (SX1268) or E22 900M30S (SX1262) or E220 LLCC68
#define RADIO_SCLK_PIN 18
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 23
#define RADIO_CS_PIN 5
#define RADIO_RST_PIN 27
#define RADIO_DIO1_PIN 12
#define RADIO_BUSY_PIN 14
#define RADIO_RXEN 32
#define RADIO_TXEN 25
#endif
#if defined(ESP32_DIY_1W_LoRa_Mesh_V1_2) // https://github.com/NanoVHF/Meshtastic-DIY/tree/main/PCB/ESP-32-devkit_EBYTE-E22/Mesh-v1.02-2LCD-FreePins
#define RADIO_SCLK_PIN 5
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 27
#define RADIO_CS_PIN 18
#define RADIO_RST_PIN 23
#define RADIO_DIO1_PIN 33
#define RADIO_BUSY_PIN 32
#define RADIO_RXEN 14
#define RADIO_TXEN 13
#endif
#ifdef WEMOS_LOLIN32_OLED_DIY_LoRa
#define RADIO_SCLK_PIN 15
#define RADIO_MISO_PIN 13
#define RADIO_MOSI_PIN 12
#define RADIO_CS_PIN 14
#define RADIO_RST_PIN 2
#define RADIO_BUSY_PIN 25
#endif
#if defined(TTGO_T_BEAM_V1_0_SX1268) || defined(TTGO_T_BEAM_V1_2_SX1262)
#define RADIO_SCLK_PIN 5
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 27
#define RADIO_CS_PIN 18
#define RADIO_DIO0_PIN 26
#define RADIO_RST_PIN 23
#define RADIO_DIO1_PIN 33
#define RADIO_BUSY_PIN 32
#endif
#if defined(OE5HWN_MeshCom)
#define RADIO_SCLK_PIN 18
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 23
#define RADIO_CS_PIN 5
#define RADIO_RST_PIN 27
#define RADIO_DIO1_PIN 33
#define RADIO_BUSY_PIN 26
#define RADIO_RXEN 14
#define RADIO_TXEN 13
#endif
#if defined(HELTEC_HTCT62)
#define RADIO_SCLK_PIN 10 // SX1262 SCK
#define RADIO_MISO_PIN 6 // SX1262 MISO
#define RADIO_MOSI_PIN 7 // SX1262 MOSI
#define RADIO_CS_PIN 8 // SX1262 NSS
#define RADIO_RST_PIN 5 // SX1262 RST
#define RADIO_DIO1_PIN 3 // SX1262 DIO1
#define RADIO_BUSY_PIN 4 // SX1262 BUSY
#endif
#if defined(ESP32_DIY_LoRa_A7670) || defined(ESP32_DIY_LoRa_A7670_915)
#define RADIO_SCLK_PIN 18
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 23
#define RADIO_CS_PIN 2
#define RADIO_RST_PIN 0
#define RADIO_BUSY_PIN 32
#define A7670_PWR_PIN 4
#define A7670_ResetPin 5
#define A7670_TX_PIN 26
#define A7670_RX_PIN 27
#endif
#ifdef WEMOS_D1_R32_RA02
#define RADIO_SCLK_PIN 18
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 23
#define RADIO_CS_PIN 5
#define RADIO_BUSY_PIN 12
#define RADIO_RST_PIN 13
#define RADIO_DIO1_PIN 14
#define OLED_SDA 21
#define OLED_SCL 22
#define OLED_RST 36
#endif
#if defined(ESP32C3_DIY_1W_LoRa) || defined(ESP32C3_DIY_1W_LoRa_915)
#define RADIO_SCLK_PIN 8
#define RADIO_MISO_PIN 9
#define RADIO_MOSI_PIN 10
#define RADIO_CS_PIN 5
#define RADIO_RST_PIN 4
#define RADIO_DIO1_PIN 2
#define RADIO_BUSY_PIN 3
#define RADIO_RXEN 6
#define RADIO_TXEN 7
#endif
#ifdef WEMOS_S2_MINI_DIY_LoRa
#define RADIO_SCLK_PIN 36
#define RADIO_MISO_PIN 37
#define RADIO_MOSI_PIN 35
#define RADIO_CS_PIN 34
#define RADIO_BUSY_PIN 38
#define RADIO_RST_PIN 33
#endif
#ifdef LIGHTGATEWAY_1_0
#define RADIO_VCC_PIN 21
#define RADIO_SCLK_PIN 12
#define RADIO_MISO_PIN 13
#define RADIO_MOSI_PIN 11
#define RADIO_CS_PIN 10
#define RADIO_RST_PIN 9
#define RADIO_DIO1_PIN 5
#define RADIO_BUSY_PIN 6
#define RADIO_RXEN 42
#define RADIO_TXEN 14
#endif
// OLED
#if defined(TTGO_LORA32_V2_1) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) || defined(TTGO_T_BEAM_V1_0) || defined(TTGO_T_BEAM_V1_2) || defined(TTGO_T_BEAM_V1_0_SX1268) || defined(TTGO_T_BEAM_V1_2_SX1262) || defined(OE5HWN_MeshCom) || defined(ESP32_DIY_LoRa_A7670) || defined(TTGO_LORA32_V2_1_915) || defined(ESP32_DIY_LoRa_915) || defined(TTGO_T_BEAM_V1_0_915) || defined(TTGO_T_BEAM_V1_2_915) || defined(ESP32_DIY_LoRa_A7670_915) || defined(ESP32_DIY_1W_LoRa_915) || defined(ESP32_DIY_1W_LoRa_LLCC68) || defined(ESP32_DIY_1W_LoRa_Mesh_V1_2)
#define OLED_SDA 21
#define OLED_SCL 22
#define OLED_RST -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#endif
#if defined(HELTEC_V2) || defined(HELTEC_WS)
#define OLED_SDA 4
#define OLED_SCL 15
#define OLED_RST 16
#endif
#if defined(HELTEC_V3)
#define OLED_SDA 17
#define OLED_SCL 18
#define OLED_RST 21
#endif
#ifdef WEMOS_LOLIN32_OLED_DIY_LoRa
#define OLED_SDA 5
#define OLED_SCL 4
#define OLED_RST -1
#endif
#ifdef LIGHTGATEWAY_1_0
#define OLED_SDA 3
#define OLED_SCL 4
#define OLED_RST -1
#endif
#if !defined(HELTEC_HTCT62) && !defined(HELTEC_WSL_V3) && !defined(ESP32C3_DIY_1W_LoRa) && !defined(ESP32C3_DIY_1W_LoRa_915) && !defined(WEMOS_S2_MINI_DIY_LoRa)
#define HAS_DISPLAY
#endif
// Leds and other stuff
#ifdef HELTEC_HTCT62
#define BATTERY_PIN 1
#endif
#ifdef WEMOS_S2_MINI_DIY_LoRa
#define INTERNAL_LED_PIN 15
#endif
#if defined(TTGO_LORA32_V2_1) || defined(TTGO_LORA32_V2_1_915)
#define INTERNAL_LED_PIN 25 // Green Led
#define BATTERY_PIN 35
#endif
#if defined(HELTEC_V2)
#define INTERNAL_LED_PIN 25
#define BATTERY_PIN 37
#define ADC_CTRL 21
#endif
#if defined(HELTEC_V3) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY) || defined(HELTEC_WS)
#define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1
#define VEXT_CTRL 36
#define ADC_CTRL 37
#define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42
#ifdef HELTEC_WSL_V3_DISPLAY
#define OLED_RST -1
#endif
#endif
#if defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_LoRa_915) || defined(ESP32_DIY_1W_LoRa) || defined(ESP32_DIY_1W_LoRa_915)
#define INTERNAL_LED_PIN 2
#endif
#if defined(ESP32_DIY_LoRa_A7670) || defined(ESP32_DIY_LoRa_A7670_915)
#define INTERNAL_LED_PIN 13 // 13 for V1.1 and 12 for V1.0
#define BATTERY_PIN 35
#endif
#ifdef HELTEC_WIRELESS_TRACKER
#define INTERNAL_LED_PIN 18
#define BATTERY_PIN 1
#define ADC_CTRL 2 // HELTEC Wireless Tracker ADC_CTRL = HIGH powers the voltage divider to read BatteryPin. Only on V05 = V1.1
#define VEXT_CTRL 3 // To turn on GPS and TFT
#define BOARD_I2C_SDA 7
#define BOARD_I2C_SCL 6
#endif
#ifdef HELTEC_WP
#define INTERNAL_LED_PIN 18
#define BATTERY_PIN 20
#define ADC_CTRL 19
#define VEXT_CTRL 45
#define BOARD_I2C_SDA 37
#define BOARD_I2C_SCL 36
#define EPAPER_BUSY 7
#define EPAPER_RST 6
#define EPAPER_DC 5
#define EPAPER_CS 4
#define EPAPER_SCL 3
#define EPAPER_SDA 2
#endif
#ifdef ESP32_C3_DIY_LoRa // just testing!
#define OLED_SDA 8
#define OLED_SCL 9
#define OLED_RST 10
#define RADIO_SCLK_PIN 4
#define RADIO_MISO_PIN 5
#define RADIO_MOSI_PIN 6
#define RADIO_CS 7
#define RADIO_RST_PIN 3
#define RADIO_IRQ_PIN 2
#endif
#if defined(ESP32_C3_OctopusLab_LoRa)
#define OLED_SDA 0
#define OLED_SCL 1
#define OLED_RST -1
#define RADIO_SCLK_PIN 6
#define RADIO_MISO_PIN 4
#define RADIO_MOSI_PIN 7
#define RADIO_CS_PIN 5
#define RADIO_DIO1_PIN 3
#define RADIO_RST_PIN -1
#define RADIO_BUSY_PIN 8
#endif
#ifdef LIGHTGATEWAY_1_0
#define BUTTON_PIN 0
#define INTERNAL_LED_PIN 16
#endif
// GPS
#if defined(TTGO_T_BEAM_V1_2) || defined(TTGO_T_BEAM_V1_2_915) || defined(TTGO_T_BEAM_V1_0) || defined(TTGO_T_BEAM_V1_0_915) || defined(TTGO_T_BEAM_V1_0_SX1268) || defined(TTGO_T_BEAM_V1_2_SX1262)
#define GPS_RX 12
#define GPS_TX 34
#endif
#if defined( HELTEC_WIRELESS_TRACKER)
#define GPS_RX 34
#define GPS_TX 33
#endif
/* (Same pins for LILYGO LoRa32 and ESP32 Wroom Dev )
SX1278-------------------> ESP32 ttgo-lora32-v21 and ESP32 WROOM Dev
GND GND
DIO1 -
DIO2 -
DIO3 -
VCC 3.3V
MISO 19
MOSI 27
SCLK 5
NSS 18
DIO0 26
REST 14
GND - */
#ifdef TTGO_LORA32_T3S3_V1_2
#define RADIO_SCLK_PIN 5 // SX1262 SCK
#define RADIO_MISO_PIN 3 // SX1262 MISO
#define RADIO_MOSI_PIN 6 // SX1262 MOSI
#define RADIO_CS_PIN 7 // SX1262 NSS
#define RADIO_RST_PIN 8 // SX1262 RST
#define RADIO_DIO1_PIN 33 // SX1262 DIO1
#define RADIO_BUSY_PIN 34 // SX1262 BUSY
#define OLED_SDA 18
#define OLED_SCL 17
#define OLED_RST -1
#define INTERNAL_LED_PIN 37 // Green Led
#define BATTERY_PIN 1
#endif
#endif

View File

@@ -3,101 +3,107 @@
#include "configuration.h"
#include "display.h"
void Configuration::check() {
if (reload) {
show_display("------- UPDATE ------", "config is old", "device will update", "and then reboot", 1000);
writeFile();
ESP.restart();
}
}
void Configuration::writeFile() {
Serial.println("Saving config..");
StaticJsonDocument<2048> data;
StaticJsonDocument<2560> data;
File configFile = SPIFFS.open("/igate_conf.json", "w");
if (wifiAPs[0].ssid != "") { // We don't want to save Auto AP empty SSID
for (int i = 0; i < wifiAPs.size(); i++) {
data["wifi"]["AP"][i]["ssid"] = wifiAPs[i].ssid;
data["wifi"]["AP"][i]["password"] = wifiAPs[i].password;
// data["wifi"]["AP"][i]["latitude"] = wifiAPs[i].latitude;
// data["wifi"]["AP"][i]["longitude"] = wifiAPs[i].longitude;
}
}
data["wifi"]["autoAP"]["password"] = wifiAutoAP.password;
data["wifi"]["autoAP"]["powerOff"] = wifiAutoAP.powerOff;
data["wifi"]["autoAP"]["password"] = wifiAutoAP.password;
data["wifi"]["autoAP"]["timeout"] = wifiAutoAP.timeout;
data["callsign"] = callsign;
// data["stationMode"] = stationMode; // only check for config version
// data["iGateComment"] = iGateComment;
data["callsign"] = callsign;
// data["other"]["beaconInterval"] = beaconInterval;
// data["other"]["igateSendsLoRaBeacons"] = igateSendsLoRaBeacons;
// data["other"]["igateRepeatsLoRaPackets"] = igateRepeatsLoRaPackets;
data["other"]["rememberStationTime"] = rememberStationTime;
data["other"]["sendBatteryVoltage"] = sendBatteryVoltage;
data["other"]["externalVoltageMeasurement"] = externalVoltageMeasurement;
data["other"]["externalVoltagePin"] = externalVoltagePin;
data["aprs_is"]["active"] = aprs_is.active;
data["aprs_is"]["passcode"] = aprs_is.passcode;
data["aprs_is"]["server"] = aprs_is.server;
data["aprs_is"]["port"] = aprs_is.port;
data["aprs_is"]["filter"] = aprs_is.filter;
data["aprs_is"]["messagesToRF"] = aprs_is.messagesToRF;
data["aprs_is"]["objectsToRF"] = aprs_is.objectsToRF;
data["digi"]["mode"] = digi.mode;
// data["digi"]["comment"] = digi.comment;
// data["digi"]["latitude"] = digi.latitude;
// data["digi"]["longitude"] = digi.longitude;
data["beacon"]["comment"] = beacon.comment;
data["beacon"]["interval"] = beacon.interval;
data["beacon"]["latitude"] = beacon.latitude;
data["beacon"]["longitude"] = beacon.longitude;
data["beacon"]["overlay"] = beacon.overlay;
data["beacon"]["symbol"] = beacon.symbol;
data["beacon"]["sendViaAPRSIS"] = beacon.sendViaAPRSIS;
data["beacon"]["sendViaRF"] = beacon.sendViaRF;
data["beacon"]["path"] = beacon.path;
data["tnc"]["enableServer"] = tnc.enableServer;
data["tnc"]["enableSerial"] = tnc.enableSerial;
data["tnc"]["acceptOwn"] = tnc.acceptOwn;
data["beacon"]["gpsActive"] = beacon.gpsActive;
data["beacon"]["gpsAmbiguity"] = beacon.gpsAmbiguity;
data["aprs_is"]["active"] = aprs_is.active;
data["aprs_is"]["passcode"] = aprs_is.passcode;
data["aprs_is"]["server"] = aprs_is.server;
data["aprs_is"]["port"] = aprs_is.port;
data["aprs_is"]["filter"] = aprs_is.filter;
data["aprs_is"]["toRF"] = aprs_is.toRF;
data["digi"]["mode"] = digi.mode;
data["digi"]["ecoMode"] = digi.ecoMode;
data["beacon"]["comment"] = beacon.comment;
// data["beacon"]["igateRepeatsLoRaPackets"] = beacon.igateRepeatsLoRaPackets;
// data["beacon"]["igateSendsLoRaBeacons"] = beacon.igateSendsLoRaBeacons;
data["beacon"]["interval"] = beacon.interval;
data["beacon"]["latitude"] = beacon.latitude;
data["beacon"]["longitude"] = beacon.longitude;
data["beacon"]["overlay"] = beacon.overlay;
data["beacon"]["symbol"] = beacon.symbol;
data["beacon"]["sendViaAPRSIS"] = beacon.sendViaAPRSIS;
data["beacon"]["sendViaRF"] = beacon.sendViaRF;
data["beacon"]["path"] = beacon.path;
data["lora"]["rxFreq"] = loramodule.rxFreq;
data["lora"]["txFreq"] = loramodule.txFreq;
data["lora"]["spreadingFactor"] = loramodule.spreadingFactor;
data["lora"]["signalBandwidth"] = loramodule.signalBandwidth;
data["lora"]["codingRate4"] = loramodule.codingRate4;
data["lora"]["power"] = loramodule.power;
data["lora"]["txActive"] = loramodule.txActive;
data["lora"]["rxActive"] = loramodule.rxActive;
// data["lora"]["iGateFreq"] = loramodule.iGateFreq;
// data["lora"]["digirepeaterTxFreq"] = loramodule.digirepeaterTxFreq;
// data["lora"]["digirepeaterRxFreq"] = loramodule.digirepeaterRxFreq;
data["lora"]["rxFreq"] = loramodule.rxFreq;
data["lora"]["txFreq"] = loramodule.txFreq;
data["lora"]["spreadingFactor"] = loramodule.spreadingFactor;
data["lora"]["signalBandwidth"] = loramodule.signalBandwidth;
data["lora"]["codingRate4"] = loramodule.codingRate4;
data["lora"]["power"] = loramodule.power;
data["lora"]["txActive"] = loramodule.txActive;
data["lora"]["rxActive"] = loramodule.rxActive;
data["display"]["alwaysOn"] = display.alwaysOn;
data["display"]["timeout"] = display.timeout;
data["display"]["turn180"] = display.turn180;
data["display"]["alwaysOn"] = display.alwaysOn;
data["display"]["timeout"] = display.timeout;
data["display"]["turn180"] = display.turn180;
data["battery"]["sendInternalVoltage"] = battery.sendInternalVoltage;
data["battery"]["monitorInternalVoltage"] = battery.monitorInternalVoltage;
data["battery"]["internalSleepVoltage"] = battery.internalSleepVoltage;
data["syslog"]["active"] = syslog.active;
data["syslog"]["server"] = syslog.server;
data["syslog"]["port"] = syslog.port;
data["battery"]["sendExternalVoltage"] = battery.sendExternalVoltage;
data["battery"]["externalVoltagePin"] = battery.externalVoltagePin;
data["battery"]["monitorExternalVoltage"] = battery.monitorExternalVoltage;
data["battery"]["externalSleepVoltage"] = battery.externalSleepVoltage;
data["battery"]["voltageDividerR1"] = battery.voltageDividerR1;
data["battery"]["voltageDividerR2"] = battery.voltageDividerR2;
data["bme"]["active"] = bme.active;
data["battery"]["sendVoltageAsTelemetry"] = battery.sendVoltageAsTelemetry;
data["wxsensor"]["active"] = wxsensor.active;
data["wxsensor"]["heightCorrection"] = wxsensor.heightCorrection;
data["wxsensor"]["temperatureCorrection"] = wxsensor.temperatureCorrection;
data["ota"]["username"] = ota.username;
data["ota"]["password"] = ota.password;
data["syslog"]["active"] = syslog.active;
data["syslog"]["server"] = syslog.server;
data["syslog"]["port"] = syslog.port;
data["other"]["lowPowerMode"] = lowPowerMode;
data["other"]["lowVoltageCutOff"] = lowVoltageCutOff;
data["tnc"]["enableServer"] = tnc.enableServer;
data["tnc"]["enableSerial"] = tnc.enableSerial;
data["tnc"]["acceptOwn"] = tnc.acceptOwn;
data["other"]["rebootMode"] = rebootMode;
data["other"]["rebootModeTime"] = rebootModeTime;
data["ota"]["username"] = ota.username;
data["ota"]["password"] = ota.password;
data["other"]["rememberStationTime"] = rememberStationTime;
data["other"]["backupDigiMode"] = backupDigiMode;
data["other"]["lowPowerMode"] = lowPowerMode;
data["other"]["lowVoltageCutOff"] = lowVoltageCutOff;
data["personalNote"] = personalNote;
data["webadmin"]["active"] = webadmin.active;
data["webadmin"]["username"] = webadmin.username;
data["webadmin"]["password"] = webadmin.password;
data["ntp"]["gmtCorrection"] = ntp.gmtCorrection;
serializeJson(data, configFile);
@@ -112,7 +118,7 @@ bool Configuration::readFile() {
File configFile = SPIFFS.open("/igate_conf.json", "r");
if (configFile) {
StaticJsonDocument<2048> data;
StaticJsonDocument<2560> data;
DeserializationError error = deserializeJson(data, configFile);
if (error) {
@@ -128,120 +134,92 @@ bool Configuration::readFile() {
wifiAPs.push_back(wifiap);
}
wifiAutoAP.password = data["wifi"]["autoAP"]["password"].as<String>();
wifiAutoAP.powerOff = data["wifi"]["autoAP"]["powerOff"].as<int>();
wifiAutoAP.password = data["wifi"]["autoAP"]["password"] | "1234567890";
wifiAutoAP.timeout = data["wifi"]["autoAP"]["timeout"] | 10;
callsign = data["callsign"].as<String>();
rememberStationTime = data["other"]["rememberStationTime"].as<int>();
sendBatteryVoltage = data["other"]["sendBatteryVoltage"].as<bool>();
externalVoltageMeasurement = data["other"]["externalVoltageMeasurement"].as<bool>();
externalVoltagePin = data["other"]["externalVoltagePin"].as<int>();
callsign = data["callsign"] | "NOCALL-10";
rememberStationTime = data["other"]["rememberStationTime"] | 30;
aprs_is.passcode = data["aprs_is"]["passcode"].as<String>();
aprs_is.server = data["aprs_is"]["server"].as<String>();
aprs_is.port = data["aprs_is"]["port"].as<int>();
beacon.latitude = data["beacon"]["latitude"] | 0.0;
beacon.longitude = data["beacon"]["longitude"] | 0.0;
beacon.comment = data["beacon"]["comment"] | "LoRa APRS";
beacon.interval = data["beacon"]["interval"] | 15;
beacon.overlay = data["beacon"]["overlay"] | "L";
beacon.symbol = data["beacon"]["symbol"] | "a";
beacon.path = data["beacon"]["path"] | "WIDE1-1";
beacon.sendViaAPRSIS = data["beacon"]["sendViaAPRSIS"] | false;
beacon.sendViaRF = data["beacon"]["sendViaRF"] | false;
loramodule.spreadingFactor = data["lora"]["spreadingFactor"].as<int>();
loramodule.signalBandwidth = data["lora"]["signalBandwidth"].as<long>();
loramodule.codingRate4 = data["lora"]["codingRate4"].as<int>();
loramodule.power = data["lora"]["power"].as<int>();
display.alwaysOn = data["display"]["alwaysOn"].as<bool>();
display.timeout = data["display"]["timeout"].as<int>();
display.turn180 = data["display"]["turn180"].as<bool>();
syslog.active = data["syslog"]["active"].as<bool>();
syslog.server = data["syslog"]["server"].as<String>();
syslog.port = data["syslog"]["port"].as<int>();
bme.active = data["bme"]["active"].as<bool>();
ota.username = data["ota"]["username"].as<String>();
ota.password = data["ota"]["password"].as<String>();
tnc.enableServer = data["tnc"]["enableServer"].as<bool>();
tnc.enableSerial = data["tnc"]["enableSerial"].as<bool>();
tnc.acceptOwn = data["tnc"]["acceptOwn"].as<bool>();
lowPowerMode = data["other"]["lowPowerMode"].as<bool>();
lowVoltageCutOff = data["other"]["lowVoltageCutOff"].as<double>();
int stationMode = data["stationMode"].as<int>(); // deprecated but need to specify config version
if (stationMode == 0) {
// Load new settings
beacon.latitude = data["beacon"]["latitude"].as<double>();
beacon.longitude = data["beacon"]["longitude"].as<double>();
beacon.comment = data["beacon"]["comment"].as<String>();
beacon.overlay = data["beacon"]["overlay"].as<String>();
beacon.symbol = data["beacon"]["symbol"].as<String>();
beacon.interval = data["beacon"]["interval"].as<int>();
// beacon.igateSendsLoRaBeacons = data["beacon"]["igateSendsLoRaBeacons"].as<bool>();
// beacon.igateRepeatsLoRaPackets = data["beacon"]["igateRepeatsLoRaPackets"].as<bool>();
beacon.sendViaAPRSIS = data["beacon"]["sendViaAPRSIS"].as<bool>();
beacon.sendViaRF = data["beacon"]["sendViaRF"].as<bool>();
beacon.path = data["beacon"]["path"].as<String>();
digi.mode = data["digi"]["mode"].as<int>();
aprs_is.active = data["aprs_is"]["active"].as<bool>();
aprs_is.filter = data["aprs_is"]["filter"].as<String>();
aprs_is.toRF = data["aprs_is"]["toRF"].as<bool>();
loramodule.txFreq = data["lora"]["txFreq"].as<long>();
loramodule.rxFreq = data["lora"]["rxFreq"].as<long>();
loramodule.txActive = data["lora"]["txActive"].as<bool>();
loramodule.rxActive = data["lora"]["rxActive"].as<bool>();
} else {
// Load old settings and put into new variables not actual config
String iGateComment = data["iGateComment"].as<String>();
int beaconInterval = data["other"]["beaconInterval"].as<int>();
// bool igateSendsLoRaBeacons = data["other"]["igateSendsLoRaBeacons"].as<bool>();
// bool igateRepeatsLoRaPackets = data["other"]["igateRepeatsLoRaPackets"].as<bool>();
long iGateFreq = data["lora"]["iGateFreq"].as<long>();
long digirepeaterTxFreq = data["lora"]["digirepeaterTxFreq"].as<long>();
long digirepeaterRxFreq = data["lora"]["digirepeaterRxFreq"].as<long>();
beacon.gpsActive = data["beacon"]["gpsActive"] | false;
beacon.gpsAmbiguity = data["beacon"]["gpsAmbiguity"] | false;
String digiComment = data["digi"]["comment"].as<String>();
double digiLatitude = data["digi"]["latitude"].as<double>();
double digiLongitude = data["digi"]["longitude"].as<double>();
aprs_is.active = data["aprs_is"]["active"] | false;
aprs_is.passcode = data["aprs_is"]["passcode"] | "XYZWV";
aprs_is.server = data["aprs_is"]["server"] | "rotate.aprs2.net";
aprs_is.port = data["aprs_is"]["port"] | 14580;
aprs_is.filter = data["aprs_is"]["filter"] | "m/10";
aprs_is.messagesToRF = data["aprs_is"]["messagesToRF"] | false;
aprs_is.objectsToRF = data["aprs_is"]["objectsToRF"] | false;
digi.mode = data["digi"]["mode"] | 0;
digi.ecoMode = data["digi"]["ecoMode"] | false;
beacon.latitude = digiLatitude;
beacon.longitude = digiLongitude;
beacon.interval = beaconInterval;
// beacon.igateSendsLoRaBeacons = igateSendsLoRaBeacons;
// beacon.igateRepeatsLoRaPackets = igateRepeatsLoRaPackets;
loramodule.txFreq = digirepeaterTxFreq;
loramodule.rxFreq = digirepeaterRxFreq;
loramodule.rxActive = true;
beacon.sendViaAPRSIS = true;
beacon.sendViaRF = false;
loramodule.txFreq = data["lora"]["txFreq"] | 433775000;
loramodule.rxFreq = data["lora"]["rxFreq"] | 433775000;
loramodule.spreadingFactor = data["lora"]["spreadingFactor"] | 12;
loramodule.signalBandwidth = data["lora"]["signalBandwidth"] | 125000;
loramodule.codingRate4 = data["lora"]["codingRate4"] | 5;
loramodule.power = data["lora"]["power"] | 20;
loramodule.txActive = data["lora"]["txActive"] | false;
loramodule.rxActive = data["lora"]["rxActive"] | false;
switch (stationMode) {
case 1: // IGate only
// aprs_is.active = true; // better don't do that automatically
beacon.comment = iGateComment;
loramodule.rxFreq = iGateFreq;
break;
case 5: // Digi + IGate
case 2: // Digi + IGate
// aprs_is.active = true; // better don't do that automatically
// digi.mode = 2; // better don't do that automatically
beacon.comment = digiComment;
loramodule.rxFreq = iGateFreq;
break;
case 3: // Digi
case 4: // Digi
// digi.mode = 2; // better don't do that automatically
beacon.comment = digiComment;
break;
}
display.alwaysOn = data["display"]["alwaysOn"] | true;
display.timeout = data["display"]["timeout"] | 4;
display.turn180 = data["display"]["turn180"] | false;
reload = true;
}
battery.sendInternalVoltage = data["battery"]["sendInternalVoltage"] | false;
battery.monitorInternalVoltage = data["battery"]["monitorInternalVoltage"] | false;
battery.internalSleepVoltage = data["battery"]["internalSleepVoltage"] | 2.9;
battery.sendExternalVoltage = data["battery"]["sendExternalVoltage"] | false;
battery.externalVoltagePin = data["battery"]["externalVoltagePin"] | 34;
battery.monitorExternalVoltage = data["battery"]["monitorExternalVoltage"] | false;
battery.externalSleepVoltage = data["battery"]["externalSleepVoltage"] | 10.9;
battery.voltageDividerR1 = data["battery"]["voltageDividerR1"] | 100.0;
battery.voltageDividerR2 = data["battery"]["voltageDividerR2"] | 27.0;
battery.sendVoltageAsTelemetry = data["battery"]["sendVoltageAsTelemetry"] | false;
wxsensor.active = data["wxsensor"]["active"] | false;
wxsensor.heightCorrection = data["wxsensor"]["heightCorrection"] | 0;
wxsensor.temperatureCorrection = data["wxsensor"]["temperatureCorrection"] | 0.0;
syslog.active = data["syslog"]["active"] | false;
syslog.server = data["syslog"]["server"] | "192.168.0.100";
syslog.port = data["syslog"]["port"] | 514;
tnc.enableServer = data["tnc"]["enableServer"] | false;
tnc.enableSerial = data["tnc"]["enableSerial"] | false;
tnc.acceptOwn = data["tnc"]["acceptOwn"] | false;
ota.username = data["ota"]["username"] | "";
ota.password = data["ota"]["password"] | "";
webadmin.active = data["webadmin"]["active"] | false;
webadmin.username = data["webadmin"]["username"] | "admin";
webadmin.password = data["webadmin"]["password"] | "";
ntp.gmtCorrection = data["ntp"]["gmtCorrection"] | 0;
lowPowerMode = data["other"]["lowPowerMode"] | false;
lowVoltageCutOff = data["other"]["lowVoltageCutOff"] | 0;
backupDigiMode = data["other"]["backupDigiMode"] | false;
rebootMode = data["other"]["rebootMode"] | false;
rebootModeTime = data["other"]["rebootModeTime"] | 6;
personalNote = data["personalNote"] | "personal note here...";
if (wifiAPs.size() == 0) { // If we don't have any WiFi's from config we need to add "empty" SSID for AUTO AP
WiFi_AP wifiap;
@@ -260,87 +238,102 @@ bool Configuration::readFile() {
}
void Configuration::init() {
reload = false;
WiFi_AP wifiap;
wifiap.ssid = "";
wifiap.password = "";
// wifiap.latitude = 0.0; // deprecated
// wifiap.longitude = 0.0; // deprecated
wifiap.ssid = "";
wifiap.password = "";
wifiAPs.push_back(wifiap);
wifiAutoAP.password = "1234567890";
wifiAutoAP.powerOff = 15;
wifiAutoAP.password = "1234567890";
wifiAutoAP.timeout = 10;
callsign = "N0CALL";
// stationMode = 1; // deprecated
// iGateComment = "LoRa_APRS_iGate Development"; // deprecated
callsign = "N0CALL-10";
beacon.comment = "LoRa APRS"; // new
beacon.latitude = 0.0; // new
beacon.longitude = 0.0; // new
beacon.interval = 15; // new
// beacon.igateRepeatsLoRaPackets = false; // new
// beacon.igateSendsLoRaBeacons = false; // new
beacon.overlay = "L"; // new
beacon.symbol = "#"; // new
beacon.sendViaAPRSIS = true; // new
beacon.sendViaRF = false; // new
beacon.path = "WIDE1-1"; // new
beacon.comment = "LoRa APRS";
beacon.latitude = 0.0;
beacon.longitude = 0.0;
beacon.interval = 15;
beacon.overlay = "L";
beacon.symbol = "a";
beacon.sendViaAPRSIS = true;
beacon.sendViaRF = false;
beacon.path = "WIDE1-1";
beacon.gpsActive = false;
beacon.gpsAmbiguity = false;
digi.mode = 0; // new
// digi.comment = "LoRa_APRS_iGate Development"; // deprecated
// digi.latitude = 0.0; // deprecated
// digi.longitude = 0.0; // deprecated
digi.mode = 0;
digi.ecoMode = false;
tnc.enableServer = false;
tnc.enableSerial = false;
tnc.acceptOwn = false;
tnc.enableServer = false;
tnc.enableSerial = false;
tnc.acceptOwn = false;
aprs_is.active = false; // new
aprs_is.passcode = "XYZVW";
aprs_is.server = "rotate.aprs2.net";
aprs_is.port = 14580;
aprs_is.filter = "m/10"; // new
aprs_is.toRF = false; // new
aprs_is.active = false;
aprs_is.passcode = "XYZVW";
aprs_is.server = "rotate.aprs2.net";
aprs_is.port = 14580;
aprs_is.filter = "m/10";
aprs_is.messagesToRF = false;
aprs_is.objectsToRF = false;
// loramodule.iGateFreq = 433775000; // deprecated
// loramodule.digirepeaterTxFreq = 433775000; // deprecated
// loramodule.digirepeaterRxFreq = 433900000; // deprecated
loramodule.txFreq = 433775000; // new
loramodule.rxFreq = 433775000; // new
loramodule.spreadingFactor = 12;
loramodule.signalBandwidth = 125000;
loramodule.codingRate4 = 5;
loramodule.power = 20;
loramodule.txActive = false; // new
loramodule.rxActive = true; // new
loramodule.txFreq = 433775000;
loramodule.rxFreq = 433775000;
loramodule.spreadingFactor = 12;
loramodule.signalBandwidth = 125000;
loramodule.codingRate4 = 5;
loramodule.power = 20;
loramodule.txActive = false;
loramodule.rxActive = true;
display.alwaysOn = true;
display.timeout = 4;
display.turn180 = false;
display.alwaysOn = true;
display.timeout = 4;
display.turn180 = false;
syslog.active = false;
syslog.server = "192.168.0.100";
syslog.port = 514;
syslog.active = false;
syslog.server = "192.168.0.100";
syslog.port = 514;
bme.active = false;
wxsensor.active = false;
wxsensor.heightCorrection = 0;
wxsensor.temperatureCorrection = 0.0;
ota.username = "";
ota.password = "";
ota.username = "";
ota.password = "";
// beaconInterval = 15; // deprecated
// igateSendsLoRaBeacons = false; // deprecated
// igateRepeatsLoRaPackets = false; // deprecated
rememberStationTime = 30;
sendBatteryVoltage = false;
externalVoltageMeasurement = false;
externalVoltagePin = 34;
rememberStationTime = 30;
lowPowerMode = false;
lowVoltageCutOff = 0;
battery.sendInternalVoltage = false;
battery.monitorInternalVoltage = false;
battery.internalSleepVoltage = 2.9;
Serial.println("todo escrito");
battery.sendExternalVoltage = false;
battery.externalVoltagePin = 34;
battery.monitorExternalVoltage = false;
battery.externalSleepVoltage = 10.9;
battery.voltageDividerR1 = 100.0;
battery.voltageDividerR2 = 27.0;
battery.sendVoltageAsTelemetry = true;
lowPowerMode = false;
lowVoltageCutOff = 0;
backupDigiMode = false;
rebootMode = false;
rebootModeTime = 0;
personalNote = "";
webadmin.active = false;
webadmin.username = "admin";
webadmin.password = "";
ntp.gmtCorrection = 0;
Serial.println("All is Written!");
}
Configuration::Configuration() {

View File

@@ -9,57 +9,53 @@ class WiFi_AP {
public:
String ssid;
String password;
// double latitude; // deprecated
// double longitude; // deprecated
};
class WiFi_Auto_AP {
public:
String password;
int powerOff;
int timeout;
};
class Beacon {
class BEACON {
public:
double latitude; // new
double longitude; // new
String comment; // new
String overlay; // new
String symbol; // new
int interval; // new
bool sendViaRF; // new
bool sendViaAPRSIS; // new
String path; // new
};
class DIGI {
public:
int mode; // new
// String comment; // deprecated
// double latitude; // deprecated
// double longitude; // deprecated
double latitude;
double longitude;
String comment;
int interval;
String overlay;
String symbol;
String path;
bool sendViaRF;
bool sendViaAPRSIS;
bool gpsActive;
bool gpsAmbiguity;
};
class APRS_IS {
public:
bool active; // new
bool active;
String passcode;
String server;
int port;
// int reportingDistance; // deprecated
String filter; // new
bool toRF; // new
String filter;
bool messagesToRF;
bool objectsToRF;
};
class DIGI {
public:
int mode;
bool ecoMode;
};
class LoraModule {
public:
// long iGateFreq; // deprecated
// long digirepeaterTxFreq; // deprecated
// long digirepeaterRxFreq; // deprecated
long txFreq; // new
long rxFreq; // new
bool txActive; // new
bool rxActive; // new
long txFreq;
long rxFreq;
bool txActive;
bool rxActive;
int spreadingFactor;
long signalBandwidth;
int codingRate4;
@@ -73,11 +69,25 @@ public:
bool turn180;
};
class TNC {
class BATTERY {
public:
bool enableServer;
bool enableSerial;
bool acceptOwn;
bool sendInternalVoltage;
bool monitorInternalVoltage;
float internalSleepVoltage;
bool sendExternalVoltage;
int externalVoltagePin;
bool monitorExternalVoltage;
float externalSleepVoltage;
float voltageDividerR1;
float voltageDividerR2;
bool sendVoltageAsTelemetry;
};
class WXSENSOR {
public:
bool active;
int heightCorrection;
float temperatureCorrection;
};
class SYSLOG {
@@ -87,9 +97,11 @@ public:
int port;
};
class BME {
class TNC {
public:
bool active;
bool enableServer;
bool enableSerial;
bool acceptOwn;
};
class OTA {
@@ -98,39 +110,47 @@ public:
String password;
};
class WEBADMIN {
public:
bool active;
String username;
String password;
};
class NTP {
public:
int gmtCorrection;
};
class Configuration {
public:
bool reload;
String callsign;
// int stationMode; // deprecated
// String iGateComment; // deprecated
// int beaconInterval; // deprecated
// bool igateSendsLoRaBeacons; // deprecated
// bool igateRepeatsLoRaPackets; // deprecated
int rememberStationTime;
bool sendBatteryVoltage;
bool externalVoltageMeasurement;
int externalVoltagePin;
bool lowPowerMode;
double lowVoltageCutOff;
std::vector<WiFi_AP> wifiAPs;
WiFi_Auto_AP wifiAutoAP;
Beacon beacon; // new
DIGI digi;
TNC tnc; // new
APRS_IS aprs_is;
LoraModule loramodule;
Display display;
SYSLOG syslog;
BME bme;
OTA ota;
String callsign;
int rememberStationTime;
bool lowPowerMode;
double lowVoltageCutOff;
bool backupDigiMode;
bool rebootMode;
int rebootModeTime;
String personalNote;
std::vector<WiFi_AP> wifiAPs;
WiFi_Auto_AP wifiAutoAP;
BEACON beacon;
APRS_IS aprs_is;
DIGI digi;
LoraModule loramodule;
Display display;
BATTERY battery;
WXSENSOR wxsensor;
SYSLOG syslog;
TNC tnc;
OTA ota;
WEBADMIN webadmin;
NTP ntp;
void init();
void writeFile();
void check();
Configuration();
private:

View File

@@ -3,9 +3,9 @@
#include "station_utils.h"
#include "aprs_is_utils.h"
#include "query_utils.h"
#include "lora_utils.h"
#include "digi_utils.h"
#include "wifi_utils.h"
#include "lora_utils.h"
#include "gps_utils.h"
#include "display.h"
#include "utils.h"
@@ -20,65 +20,143 @@ extern String fourthLine;
extern String fifthLine;
extern String sixthLine;
extern String seventhLine;
extern bool backUpDigiMode;
namespace DIGI_Utils {
String generateDigiRepeatedPacket(String packet, String callsign) {
String sender, temp0, tocall, path;
sender = packet.substring(0, packet.indexOf(">"));
temp0 = packet.substring(packet.indexOf(">") + 1, packet.indexOf(":"));
if (temp0.indexOf(",") > 2) {
tocall = temp0.substring(0, temp0.indexOf(","));
path = temp0.substring(temp0.indexOf(",") + 1, temp0.indexOf(":"));
if (path.indexOf("WIDE1-") >= 0) {
String hop = path.substring(path.indexOf("WIDE1-") + 6, path.indexOf("WIDE1-") + 7);
if (hop.toInt() >= 1 && hop.toInt() <= 7) {
if (hop.toInt() == 1) {
path.replace("WIDE1-1", callsign + "*");
}
else {
path.replace("WIDE1-" + hop, callsign + "*,WIDE1-" + String(hop.toInt() - 1));
}
String repeatedPacket = sender + ">" + tocall + "," + path + packet.substring(packet.indexOf(":"));
return repeatedPacket;
String buildPacket(const String& path, const String& packet, bool thirdParty, bool crossFreq) {
if (!crossFreq) {
String packetToRepeat = packet.substring(0, packet.indexOf(",") + 1);
String tempPath = path;
if (path.indexOf("WIDE1-1") != -1 && (Config.digi.mode == 2 || Config.digi.mode == 3)) {
tempPath.replace("WIDE1-1", Config.callsign + "*");
} else if (path.indexOf("WIDE2-") != -1 && Config.digi.mode == 3) {
if (path.indexOf(",WIDE1*") != -1) {
tempPath.remove(path.indexOf(",WIDE1*"), 7);
}
else {
if (path.indexOf("*") != -1) {
tempPath.remove(path.indexOf("*"), 1);
}
if (path.indexOf("WIDE2-1") != -1) {
tempPath.replace("WIDE2-1", Config.callsign + "*");
} else if (path.indexOf("WIDE2-2") != -1) {
tempPath.replace("WIDE2-2", Config.callsign + "*,WIDE2-1");
} else {
return "";
}
}
else {
packetToRepeat += tempPath;
if (thirdParty) {
packetToRepeat += APRS_IS_Utils::checkForStartingBytes(packet.substring(packet.indexOf(":}")));
} else {
packetToRepeat += APRS_IS_Utils::checkForStartingBytes(packet.substring(packet.indexOf(":")));
}
return packetToRepeat;
} else { // CrossFreq Digirepeater
String suffix = thirdParty ? ":}" : ":";
String packetToRepeat = packet.substring(0, packet.indexOf(suffix));
String terms[] = {",WIDE1*", ",WIDE2*", "*"};
for (String term : terms) {
int index = packetToRepeat.indexOf(term);
if (index != -1) {
packetToRepeat.remove(index, term.length());
}
}
packetToRepeat += ",";
packetToRepeat += Config.callsign;
packetToRepeat += "*";
packetToRepeat += APRS_IS_Utils::checkForStartingBytes(packet.substring(packet.indexOf(suffix)));
return packetToRepeat;
}
}
String generateDigiRepeatedPacket(const String& packet, bool thirdParty){
String temp;
if (thirdParty) { // only header is used
const String& header = packet.substring(0, packet.indexOf(":}"));
temp = header.substring(header.indexOf(">") + 1);
} else {
temp = packet.substring(packet.indexOf(">") + 1, packet.indexOf(":"));
}
if (temp.indexOf(",") > 2) { // checks for path
const String& path = temp.substring(temp.indexOf(",") + 1); // after tocall
if (Config.digi.mode == 2 || backUpDigiMode) {
if (path.indexOf("WIDE1-1") != - 1) {
return buildPacket(path, packet, thirdParty, false);
} else if (path.indexOf("WIDE1-1") == -1 && (abs(Config.loramodule.txFreq - Config.loramodule.rxFreq) >= 125000)) { // CrossFreq Digi
return buildPacket(path, packet, thirdParty, true);
} else {
return "";
}
} else if (Config.digi.mode == 3) {
if (path.indexOf("WIDE1-1") != -1 || path.indexOf("WIDE2-") != -1) {
int wide1Index = path.indexOf("WIDE1-1");
int wide2Index = path.indexOf("WIDE2-");
// WIDE1-1 && WIDE2-n / only WIDE1-1 / only WIDE2-n
if ((wide1Index != -1 && wide2Index != -1 && wide1Index < wide2Index) || (wide1Index != -1 && wide2Index == -1) || (wide1Index == -1 && wide2Index != -1)) {
return buildPacket(path, packet, thirdParty, false);
}
return "";
} else if (path.indexOf("WIDE1-1") == -1 && path.indexOf("WIDE2-") == -1 && (abs(Config.loramodule.txFreq - Config.loramodule.rxFreq) >= 125000)) { // CrossFreq Digi
return buildPacket(path, packet, thirdParty, true);
} else {
return "";
}
} else {
return "";
}
}
else {
} else if (temp.indexOf(",") == -1 && (Config.digi.mode == 2 || backUpDigiMode || Config.digi.mode == 3) && (abs(Config.loramodule.txFreq - Config.loramodule.rxFreq) >= 125000)) {
return buildPacket("", packet, thirdParty, true);
} else {
return "";
}
}
void processPacket(String packet) {
bool queryMessage = false;
String loraPacket, Sender, AddresseeAndMessage, Addressee;
void processLoRaPacket(const String& packet) {
if (packet != "") {
if ((packet.substring(0, 3) == "\x3c\xff\x01") && (packet.indexOf("NOGATE") == -1)) {
Sender = packet.substring(3, packet.indexOf(">"));
if (Sender != Config.callsign) {
STATION_Utils::updateLastHeard(Sender);
// STATION_Utils::updatePacketBuffer(packet);
Utils::typeOfPacket(packet.substring(3), "Digi");
AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2);
Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
Addressee.trim();
if (packet.indexOf("::") > 10 && Addressee == Config.callsign) { // its a message for me!
queryMessage = APRS_IS_Utils::processReceivedLoRaMessage(Sender, AddresseeAndMessage);
bool thirdPartyPacket = false;
String temp, Sender;
int firstColonIndex = packet.indexOf(":");
if (firstColonIndex > 5 && firstColonIndex < (packet.length() - 1) && packet[firstColonIndex + 1] == '}' && packet.indexOf("TCPIP") > 0) { // 3rd Party
thirdPartyPacket = true;
temp = packet.substring(packet.indexOf(":}") + 2);
Sender = temp.substring(0, temp.indexOf(">"));
} else {
temp = packet.substring(3);
Sender = packet.substring(3, packet.indexOf(">"));
}
if (Sender != Config.callsign) { // Avoid listening to own packets
if (!thirdPartyPacket && !Utils::checkValidCallsign(Sender)) {
return;
}
if (!queryMessage && packet.indexOf("WIDE1-") > 10 && Config.digi.mode == 2) { // If should repeat packet (WIDE1 Digi)
loraPacket = generateDigiRepeatedPacket(packet.substring(3), Config.callsign);
if (loraPacket != "") {
delay(500);
LoRa_Utils::sendNewPacket("APRS", loraPacket);
display_toggle(true);
lastScreenOn = millis();
if (STATION_Utils::check25SegBuffer(Sender, temp.substring(temp.indexOf(":") + 2)) || Config.lowPowerMode) {
STATION_Utils::updateLastHeard(Sender);
Utils::typeOfPacket(temp, 2); // Digi
bool queryMessage = false;
if (temp.indexOf("::") > 10) { // it's a message
String AddresseeAndMessage = temp.substring(temp.indexOf("::") + 2);
String Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
Addressee.trim();
if (Addressee == Config.callsign) { // it's a message for me!
queryMessage = APRS_IS_Utils::processReceivedLoRaMessage(Sender, AddresseeAndMessage, thirdPartyPacket);
}
}
if (!queryMessage) {
String loraPacket = generateDigiRepeatedPacket(packet.substring(3), thirdPartyPacket);
if (loraPacket != "") {
if (Config.lowPowerMode) {
LoRa_Utils::sendNewPacket(loraPacket);
} else {
STATION_Utils::addToOutputPacketBuffer(loraPacket);
}
displayToggle(true);
lastScreenOn = millis();
}
}
}
}
@@ -86,8 +164,12 @@ namespace DIGI_Utils {
}
}
void loop(String packet) {
processPacket(packet);
void checkEcoMode() {
if (Config.digi.ecoMode) {
Config.display.alwaysOn = false;
Config.display.timeout = 0;
setCpuFrequencyMhz(10);
}
}
}

View File

@@ -6,9 +6,10 @@
namespace DIGI_Utils {
String generateDigiRepeatedPacket(String packet, String callsign);
void processPacket(String packet);
void loop(String packet);
String buildPacket(const String& path, const String& packet, bool thirdParty, bool crossFreq);
String generateDigiRepeatedPacket(const String& packet, bool thirdParty);
void processLoRaPacket(const String& packet);
void checkEcoMode();
}

View File

@@ -1,185 +1,223 @@
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <Wire.h>
#include "configuration.h"
#include "pins_config.h"
#include "boards_pinout.h"
#include "display.h"
#ifdef HAS_DISPLAY
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);
#ifdef HAS_TFT
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
#ifdef HELTEC_WIRELESS_TRACKER
#define bigSizeFont 2.5
#define smallSizeFont 1.5
#define lineSpacing 12
#endif
#else
#if HAS_EPAPER
//
#else
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#if defined(HELTEC_V3) || defined(HELTEC_WS)
#define OLED_DISPLAY_HAS_RST_PIN
#endif
#ifdef HELTEC_WSL_V3_DISPLAY
Adafruit_SSD1306 display(128, 64, &Wire1, OLED_RST);
#else
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RST);
#endif
#endif
#endif
#endif
extern Configuration Config;
extern Configuration Config;
String oldHeader, oldFirstLine, oldSecondLine, oldThirdLine, oldFourthLine, oldFifthLine, oldSixthLine;
bool displayFound = false;
void setup_display() {
#ifdef HAS_DISPLAY
Wire.begin(OLED_SDA, OLED_SCL);
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
if (Config.display.turn180) {
display.setRotation(2);
}
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(1);
display.display();
delay(1000);
void cleanTFT() {
#ifdef HAS_TFT
tft.fillScreen(TFT_BLACK);
#endif
}
void display_toggle(bool toggle) {
void displaySetup() {
#ifdef HAS_DISPLAY
if (toggle) {
display.ssd1306_command(SSD1306_DISPLAYON);
delay(500);
#ifdef HAS_TFT
tft.init();
tft.begin();
if (Config.display.turn180) {
tft.setRotation(3);
} else {
tft.setRotation(1);
}
tft.setTextFont(0);
tft.fillScreen(TFT_BLACK);
#else
#if HAS_EPAPER
//
#else
#ifdef OLED_DISPLAY_HAS_RST_PIN
pinMode(OLED_RST, OUTPUT);
digitalWrite(OLED_RST, LOW);
delay(20);
digitalWrite(OLED_RST, HIGH);
#endif
if(display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
displayFound = true;
if (Config.display.turn180) {
display.setRotation(2);
}
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(1);
display.display();
}
#endif
#endif
delay(1000);
#endif
}
void displayToggle(bool toggle) {
#ifdef HAS_DISPLAY
if (toggle) {
#ifdef HAS_TFT
digitalWrite(TFT_BL, HIGH);
#else
#if HAS_EPAPER
// ... to be continued
#else
if (displayFound) display.ssd1306_command(SSD1306_DISPLAYON);
#endif
#endif
} else {
#ifdef HAS_TFT
digitalWrite(TFT_BL, LOW);
#else
#if HAS_EPAPER
// ... to be continued
#else
if (displayFound) display.ssd1306_command(SSD1306_DISPLAYOFF);
#endif
#endif
}
#endif
}
bool shouldCleanTFT(const String& header, const String& line1, const String& line2, const String& line3) {
if (oldHeader != header || oldFirstLine != line1 || oldSecondLine != line2 || oldThirdLine != line3) {
oldHeader = header;
oldFirstLine = line1;
oldSecondLine = line2;
oldThirdLine = line3;
return true;
} else {
display.ssd1306_command(SSD1306_DISPLAYOFF);
return false;
}
}
bool shouldCleanTFT(const String& header, const String& line1, const String& line2, const String& line3, const String& line4, const String& line5, const String& line6) {
if (oldHeader != header || oldFirstLine != line1 || oldSecondLine != line2 || oldThirdLine != line3 || oldFourthLine != line4 || oldFifthLine != line5 || oldSixthLine != line6) {
oldHeader = header;
oldFirstLine = line1;
oldSecondLine = line2;
oldThirdLine = line3;
oldFourthLine = line4;
oldFifthLine = line5;
oldSixthLine = line6;
return true;
} else {
return false;
}
}
void displayShow(const String& header, const String& line1, const String& line2, const String& line3, int wait) {
#ifdef HAS_DISPLAY
const String* const lines[] = {&line1, &line2, &line3};
#ifdef HAS_TFT
if (shouldCleanTFT(header, line1, line2, line3)) {
cleanTFT();
}
tft.setTextColor(TFT_WHITE,TFT_BLACK);
tft.setTextSize(bigSizeFont);
tft.setCursor(0, 0);
tft.print(header);
tft.setTextSize(smallSizeFont);
for (int i = 0; i < 3; i++) {
tft.setCursor(0, ((lineSpacing * (2 + i)) - 2));
tft.print(*lines[i]);
}
#else
#ifdef HAS_EPAPER
// ... to be continued
#else
if (displayFound) {
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(header);
for (int i = 0; i < 3; i++) {
display.setCursor(0, 8 + (8 * i));
display.println(*lines[i]);
}
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(1);
display.display();
}
#endif
#endif
delay(wait);
#endif
}
void show_display(String line1, int wait) {
void displayShow(const String& header, const String& line1, const String& line2, const String& line3, const String& line4, const String& line5, const String& line6, int wait) {
#ifdef HAS_DISPLAY
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(line1);
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(1);
display.display();
delay(wait);
#endif
}
void show_display(String line1, String line2, int wait) {
#ifdef HAS_DISPLAY
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(line1);
display.setCursor(0, 8);
display.println(line2);
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(1);
display.display();
delay(wait);
#endif
}
void show_display(String line1, String line2, String line3, int wait) {
#ifdef HAS_DISPLAY
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(line1);
display.setCursor(0, 8);
display.println(line2);
display.setCursor(0, 16);
display.println(line3);
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(1);
display.display();
delay(wait);
#endif
}
void show_display(String line1, String line2, String line3, String line4, int wait) {
#ifdef HAS_DISPLAY
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(line1);
display.setCursor(0, 8);
display.println(line2);
display.setCursor(0, 16);
display.println(line3);
display.setCursor(0, 24);
display.println(line4);
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(1);
display.display();
delay(wait);
#endif
}
void show_display(String line1, String line2, String line3, String line4, String line5, int wait) {
#ifdef HAS_DISPLAY
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(line1);
display.setCursor(0, 8);
display.println(line2);
display.setCursor(0, 16);
display.println(line3);
display.setCursor(0, 24);
display.println(line4);
display.setCursor(0, 32);
display.println(line5);
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(1);
display.display();
delay(wait);
#endif
}
void show_display(String line1, String line2, String line3, String line4, String line5, String line6, int wait) {
#ifdef HAS_DISPLAY
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(line1);
display.setCursor(0, 8);
display.println(line2);
display.setCursor(0, 16);
display.println(line3);
display.setCursor(0, 24);
display.println(line4);
display.setCursor(0, 32);
display.println(line5);
display.setCursor(0, 40);
display.println(line6);
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(1);
display.display();
delay(wait);
#endif
}
void show_display(String line1, String line2, String line3, String line4, String line5, String line6, String line7, int wait) {
#ifdef HAS_DISPLAY
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);
display.setCursor(0, 0);
display.println(line1);
display.setTextSize(1);
display.setCursor(0, 16);
display.println(line2);
display.setCursor(0, 24);
display.println(line3);
display.setCursor(0, 32);
display.println(line4);
display.setCursor(0, 40);
display.println(line5);
display.setCursor(0, 48);
display.println(line6);
display.setCursor(0, 56);
display.println(line7);
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(1);
display.display();
delay(wait);
const String* const lines[] = {&line1, &line2, &line3, &line4, &line5, &line6};
#ifdef HAS_TFT
if (shouldCleanTFT(header, line1, line2, line3, line4, line5, line6)) {
cleanTFT();
}
tft.setTextColor(TFT_WHITE,TFT_BLACK);
tft.setTextSize(bigSizeFont);
tft.setCursor(0, 0);
tft.print(header);
tft.setTextSize(smallSizeFont);
for (int i = 0; i < 6; i++) {
tft.setCursor(0, ((lineSpacing * (2 + i)) - 2));
tft.print(*lines[i]);
}
#else
#ifdef HAS_EPAPER
// ... to be continued
#else
if (displayFound) {
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(2);
display.setCursor(0, 0);
display.println(header);
display.setTextSize(1);
for (int i = 0; i < 6; i++) {
display.setCursor(0, 16 + (8 * i));
display.println(*lines[i]);
}
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(1);
display.display();
}
#endif
#endif
delay(wait);
#endif
}

View File

@@ -3,20 +3,16 @@
#include <Arduino.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
void cleanTFT();
void displaySetup();
void displayToggle(bool toggle);
void setup_display();
void display_toggle(bool toggle);
bool shouldCleanTFT(const String& header, const String& line1, const String& line2, const String& line3);
bool shouldCleanTFT(const String& header, const String& line1, const String& line2, const String& line3, const String& line4, const String& line5, const String& line6);
void show_display(String line1, int wait = 0);
void show_display(String line1, String line2, int wait = 0);
void show_display(String line1, String line2, String line3, int wait = 0);
void show_display(String line1, String line2, String line3, String line4, int wait = 0);
void show_display(String line1, String line2, String line3, String line4, String line5, int wait = 0);
void show_display(String line1, String line2, String line3, String line4, String line5, String line6, int wait = 0);
void show_display(String line1, String line2, String line3, String line4, String line5, String line6, String line7, int wait = 0);
void displayShow(const String& header, const String& line1, const String& line2, const String& line3, int wait = 0);
void displayShow(const String& header, const String& line1, const String& line2, const String& line3, const String& line4, const String& line5, const String& line6, int wait = 0);
#endif

View File

@@ -1,15 +1,30 @@
#include <TinyGPS++.h>
#include <WiFi.h>
#include "configuration.h"
#include "boards_pinout.h"
#include "gps_utils.h"
#include "display.h"
#include "utils.h"
extern Configuration Config;
extern WiFiClient espClient;
String distance;
#ifdef GPS_BAUDRATE
#define GPS_BAUD GPS_BAUDRATE
#else
#define GPS_BAUD 9600
#endif
extern Configuration Config;
extern WiFiClient espClient;
extern HardwareSerial gpsSerial;
extern TinyGPSPlus gps;
String distance, iGateBeaconPacket, iGateLoRaBeaconPacket;
namespace GPS_Utils {
String getiGateLoRaBeaconPacket() {
return iGateLoRaBeaconPacket;
}
char *ax25_base91enc(char *s, uint8_t n, uint32_t v) {
for(s += n, *s = '\0'; n; n--) {
*(--s) = v % 91 + 33;
@@ -18,20 +33,32 @@ namespace GPS_Utils {
return(s);
}
String encodeGPS(float latitude, float longitude, String overlay, String symbol) {
float roundToTwoDecimals(float degrees) {
return round(degrees * 100) / 100;
}
String encodeGPS(float latitude, float longitude, const String& overlay, const String& symbol) {
String encodedData = overlay;
uint32_t aprs_lat, aprs_lon;
aprs_lat = 900000000 - latitude * 10000000;
float processedLatitude = latitude;
float processedLongitude = longitude;
if (Config.beacon.gpsActive && Config.beacon.gpsAmbiguity) {
processedLatitude = roundToTwoDecimals(latitude);
processedLongitude = roundToTwoDecimals(longitude);
}
aprs_lat = 900000000 - processedLatitude * 10000000;
aprs_lat = aprs_lat / 26 - aprs_lat / 2710 + aprs_lat / 15384615;
aprs_lon = 900000000 + longitude * 10000000 / 2;
aprs_lon = 900000000 + processedLongitude * 10000000 / 2;
aprs_lon = aprs_lon / 26 - aprs_lon / 2710 + aprs_lon / 15384615;
String Ns, Ew, helper;
if(latitude < 0) { Ns = "S"; } else { Ns = "N"; }
if(latitude < 0) { latitude= -latitude; }
if(processedLatitude < 0) { Ns = "S"; } else { Ns = "N"; }
if(processedLatitude < 0) { processedLatitude = -processedLatitude; }
if(longitude < 0) { Ew = "W"; } else { Ew = "E"; }
if(longitude < 0) { longitude= -longitude; }
if(processedLongitude < 0) { Ew = "W"; } else { Ew = "E"; }
if(processedLongitude < 0) { processedLongitude = -processedLongitude; }
char helper_base91[] = {"0000\0"};
int i;
@@ -43,31 +70,50 @@ namespace GPS_Utils {
for (i = 0; i < 4; i++) {
encodedData += helper_base91[i];
}
encodedData += symbol + " x" + "\x47";
encodedData += symbol;
encodedData += " ";
encodedData += "\x47";
return encodedData;
}
String generateBeacon() {
String beaconPacket = Config.callsign + ">APLRG1," + Config.beacon.path;
if (Config.aprs_is.active && Config.digi.mode == 0) { // If APRSIS enabled and Digi disabled
beaconPacket += ",qAC";
}
return beaconPacket + ":!" + encodeGPS(Config.beacon.latitude, Config.beacon.longitude, Config.beacon.overlay, Config.beacon.symbol);;
void generateBeaconFirstPart() {
String beaconPacket = Config.callsign;
beaconPacket += ">APLRG1";
if (Config.beacon.path.indexOf("WIDE") == 0) {
beaconPacket += ",";
beaconPacket += Config.beacon.path;
}
iGateBeaconPacket = beaconPacket;
iGateBeaconPacket += ",qAC:!";
iGateLoRaBeaconPacket = beaconPacket;
iGateLoRaBeaconPacket += ":!";
}
String generateiGateLoRaBeacon() {
return Config.callsign + ">APLRG1," + Config.beacon.path + ":!" + encodeGPS(Config.beacon.latitude, Config.beacon.longitude, Config.beacon.overlay, Config.beacon.symbol);
void generateBeacons() {
if (Config.callsign.indexOf("NOCALL-10") != 0 && !Utils::checkValidCallsign(Config.callsign)) {
displayShow("***** ERROR ******", "CALLSIGN = NOT VALID!", "", "Only Rx Mode Active", 3000);
Config.loramodule.txActive = false;
Config.aprs_is.messagesToRF = false;
Config.aprs_is.objectsToRF = false;
Config.beacon.sendViaRF = false;
Config.digi.mode = 0;
Config.backupDigiMode = false;
}
generateBeaconFirstPart();
String encodedGPS = encodeGPS(Config.beacon.latitude, Config.beacon.longitude, Config.beacon.overlay, Config.beacon.symbol);
iGateBeaconPacket += encodedGPS;
iGateLoRaBeaconPacket += encodedGPS;
}
double calculateDistanceTo(double latitude, double longitude) {
return TinyGPSPlus::distanceBetween(Config.beacon.latitude,Config.beacon.longitude, latitude, longitude) / 1000.0;
}
String decodeEncodedGPS(String packet) {
String GPSPacket = packet.substring(packet.indexOf(":!")+3);
String encodedLatitude = GPSPacket.substring(0,4);
String encodedLongtitude = GPSPacket.substring(4,8);
String decodeEncodedGPS(const String& packet) {
const String& GPSPacket = packet.substring(packet.indexOf(":!")+3);
const String& encodedLatitude = GPSPacket.substring(0,4);
const String& encodedLongtitude = GPSPacket.substring(4,8);
const String& comment = GPSPacket.substring(12);
int Y1 = int(encodedLatitude[0]);
int Y2 = int(encodedLatitude[1]);
@@ -80,43 +126,69 @@ namespace GPS_Utils {
int X3 = int(encodedLongtitude[2]);
int X4 = int(encodedLongtitude[3]);
float decodedLongitude = -180.0 + ((((X1-33) * pow(91,3)) + ((X2-33) * pow(91,2)) + ((X3-33) * 91) + X4-33) / 190463.0);
distance = String(calculateDistanceTo(decodedLatitude, decodedLongitude),1);
return String(decodedLatitude,5) + "N / " + String(decodedLongitude,5) + "E / " + distance + "km";
String decodedGPS = String(decodedLatitude,5);
decodedGPS += "N / ";
decodedGPS += String(decodedLongitude,5);
decodedGPS += "E / ";
decodedGPS += distance;
decodedGPS += "km";
if (comment != "") {
decodedGPS += " / ";
decodedGPS += comment;
}
return decodedGPS;
}
String getReceivedGPS(String packet) {
String getReceivedGPS(const String& packet) {
String infoGPS;
if (packet.indexOf(":!") > 10) {
infoGPS = packet.substring(packet.indexOf(":!")+2);
infoGPS = packet.substring(packet.indexOf(":!") + 2);
} else if (packet.indexOf(":=") > 10) {
infoGPS = packet.substring(packet.indexOf(":=")+2);
infoGPS = packet.substring(packet.indexOf(":=") + 2);
}
String Latitude = infoGPS.substring(0,8);
String Longitude = infoGPS.substring(9,18);
const String& Latitude = infoGPS.substring(0,8);
const String& Longitude = infoGPS.substring(9,18);
const String& comment = infoGPS.substring(19);
float convertedLatitude, convertedLongitude;
String firstLatPart = Latitude.substring(0,2);
String secondLatPart = Latitude.substring(2,4);
String thirdLatPart = Latitude.substring(Latitude.indexOf(".")+1,Latitude.indexOf(".")+3);
String firstLngPart = Longitude.substring(0,3);
String secondLngPart = Longitude.substring(3,5);
String thirdLngPart = Longitude.substring(Longitude.indexOf(".")+1,Longitude.indexOf(".")+3);
const String& firstLatPart = Latitude.substring(0,2);
const String& secondLatPart = Latitude.substring(2,4);
const String& thirdLatPart = Latitude.substring(Latitude.indexOf(".") + 1, Latitude.indexOf(".") + 3);
convertedLatitude = firstLatPart.toFloat() + (secondLatPart.toFloat()/60) + (thirdLatPart.toFloat()/(60*100));
const String& firstLngPart = Longitude.substring(0,3);
const String& secondLngPart = Longitude.substring(3,5);
const String& thirdLngPart = Longitude.substring(Longitude.indexOf(".") + 1, Longitude.indexOf(".") + 3);
convertedLongitude = firstLngPart.toFloat() + (secondLngPart.toFloat()/60) + (thirdLngPart.toFloat()/(60*100));
String LatSign = String(Latitude[7]);
String LngSign = String(Longitude[8]);
if (LatSign == "S") {
if (String(Latitude[7]) == "S") {
convertedLatitude = -convertedLatitude;
}
if (LngSign == "W") {
if (String(Longitude[8]) == "W") {
convertedLongitude = -convertedLongitude;
}
distance = String(calculateDistanceTo(convertedLatitude, convertedLongitude),1);
return String(convertedLatitude,5) + "N / " + String(convertedLongitude,5) + "E / " + distance + "km";
String decodedGPS = String(convertedLatitude,5);
decodedGPS += "N / ";
decodedGPS += String(convertedLongitude,5);
decodedGPS += "E / ";
decodedGPS += distance;
decodedGPS += "km";
if (comment != "") {
decodedGPS += " / ";
decodedGPS += comment;
}
return decodedGPS;
}
String getDistance(String packet) {
String getDistanceAndComment(const String& packet) {
uint8_t encodedBytePosition = 0;
if (packet.indexOf(":!") > 10) {
encodedBytePosition = packet.indexOf(":!") + 14;
@@ -135,4 +207,19 @@ namespace GPS_Utils {
}
}
void setup() {
#ifdef HAS_GPS
if (Config.beacon.gpsActive) {
gpsSerial.begin(GPS_BAUD, SERIAL_8N1, GPS_TX, GPS_RX);
}
#endif
generateBeacons();
}
void getData() {
while (gpsSerial.available() > 0) {
gps.encode(gpsSerial.read());
}
}
}

View File

@@ -5,15 +5,18 @@
namespace GPS_Utils {
String getiGateLoRaBeaconPacket();
char *ax25_base91enc(char *s, uint8_t n, uint32_t v);
String encodeGPS(float latitude, float longitude, const String& overlay, const String& symbol);
void generateBeaconFirstPart();
void generateBeacons();
String decodeEncodedGPS(const String& packet);
String getReceivedGPS(const String& packet);
String getDistanceAndComment(const String& packet);
char *ax25_base91enc(char *s, uint8_t n, uint32_t v);
String encodeGPS(float latitude, float longitude, String overlay, String symbol);
String generateBeacon();
String generateiGateLoRaBeacon();
double calculateDistanceCourse(double latitude, double longitude);
String decodeEncodedGPS(String packet);
String getReceivedGPS(String packet);
String getDistance(String packet);
void setup();
void getData();
}

View File

@@ -2,29 +2,39 @@
#include <WiFi.h>
#include "configuration.h"
#include "aprs_is_utils.h"
#include "boards_pinout.h"
#include "syslog_utils.h"
#include "pins_config.h"
#include "ntp_utils.h"
#include "display.h"
#include "utils.h"
extern Configuration Config;
extern Configuration Config;
extern uint32_t lastRxTime;
extern std::vector<ReceivedPacket> receivedPackets;
bool transmissionFlag = true;
bool ignorePacket = false;
bool operationDone = true;
bool operationDone = true;
bool transmitFlag = true;
#ifdef HAS_SX1262
SX1262 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN);
SX1262 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN);
#endif
#ifdef HAS_SX1268
SX1268 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN);
#if defined(LIGHTGATEWAY_1_0)
SPIClass loraSPI(FSPI);
SX1268 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN, loraSPI);
#else
SX1268 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN);
#endif
#endif
#ifdef HAS_SX1278
SX1278 radio = new Module(RADIO_CS_PIN, RADIO_BUSY_PIN, RADIO_RST_PIN);
SX1278 radio = new Module(RADIO_CS_PIN, RADIO_BUSY_PIN, RADIO_RST_PIN);
#endif
#ifdef HAS_SX1276
SX1276 radio = new Module(RADIO_CS_PIN, RADIO_BUSY_PIN, RADIO_RST_PIN);
#endif
#if defined(HAS_LLCC68) //LLCC68 supports spreading factor only in range of 5-11!
LLCC68 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN);
#endif
int rssi, freqError;
@@ -37,24 +47,33 @@ namespace LoRa_Utils {
}
void setup() {
SPI.begin(RADIO_SCLK_PIN, RADIO_MISO_PIN, RADIO_MOSI_PIN);
#ifdef LIGHTGATEWAY_1_0
pinMode(RADIO_VCC_PIN,OUTPUT);
digitalWrite(RADIO_VCC_PIN,HIGH);
loraSPI.begin(RADIO_SCLK_PIN, RADIO_MISO_PIN, RADIO_MOSI_PIN, RADIO_CS_PIN);
#else
SPI.begin(RADIO_SCLK_PIN, RADIO_MISO_PIN, RADIO_MOSI_PIN);
#endif
float freq = (float)Config.loramodule.rxFreq / 1000000;
#if defined(RADIO_HAS_XTAL)
radio.XTAL = true;
#endif
int state = radio.begin(freq);
if (state == RADIOLIB_ERR_NONE) {
Utils::println("Initializing LoRa Module");
} else {
Utils::println("Starting LoRa failed!");
Utils::println("Starting LoRa failed! State: " + String(state));
while (true);
}
#ifdef HAS_SX127X
radio.setDio0Action(setFlag, RISING);
#if defined(HAS_SX1262) || defined(HAS_SX1268) || defined(HAS_LLCC68)
if (!Config.lowPowerMode) {
radio.setDio1Action(setFlag);
} else {
radio.setDIOMapping(1, RADIOLIB_SX126X_IRQ_RX_DONE);
}
#endif
#ifdef HAS_SX126X
if (!Config.lowPowerMode) {
radio.setDio1Action(setFlag);
} else {
radio.setDIOMapping(1, RADIOLIB_SX126X_IRQ_RX_DONE);
}
#if defined(HAS_SX1278) || defined(HAS_SX1276)
radio.setDio0Action(setFlag, RISING);
#endif
radio.setSpreadingFactor(Config.loramodule.spreadingFactor);
float signalBandwidth = Config.loramodule.signalBandwidth/1000;
@@ -62,20 +81,31 @@ namespace LoRa_Utils {
radio.setCodingRate(Config.loramodule.codingRate4);
radio.setCRC(true);
#if defined(ESP32_DIY_1W_LoRa)
radio.setRfSwitchPins(RADIO_RXEN, RADIO_TXEN);
#if (defined(RADIO_RXEN) && defined(RADIO_TXEN)) || defined(LIGHTGATEWAY_1_0) // QRP Labs LightGateway has 400M22S (SX1268)
radio.setRfSwitchPins(RADIO_RXEN, RADIO_TXEN);
#endif
#if defined(HAS_SX127X) || ESP32_DIY_1W_LoRa
state = radio.setOutputPower(Config.loramodule.power); // max value 20dB for 400M30S as it has Low Noise Amp
#endif
#if defined(HELTEC_V3) || defined(HELTEC_WS) || defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2_SX1262)
state = radio.setOutputPower(Config.loramodule.power + 2); // values available: 10, 17, 22 --> if 20 in tracker_conf.json it will be updated to 22.
#ifdef HAS_1W_LORA // Ebyte E22 400M30S (SX1268) / 900M30S (SX1262) / Ebyte E220 400M30S (LLCC68)
state = radio.setOutputPower(Config.loramodule.power); // max value 20dB for 1W modules as they have Low Noise Amp
radio.setCurrentLimit(140); // to be validated (100 , 120, 140)?
#endif
#if defined(HAS_SX1278) || defined(HAS_SX1276)
state = radio.setOutputPower(Config.loramodule.power); // max value 20dB for 400M30S as it has Low Noise Amp
radio.setCurrentLimit(100); // to be validated (80 , 100)?
#endif
#if (defined(HAS_SX1268) || defined(HAS_SX1262)) && !defined(HAS_1W_LORA)
state = radio.setOutputPower(Config.loramodule.power + 2); // values available: 10, 17, 22 --> if 20 in tracker_conf.json it will be updated to 22.
radio.setCurrentLimit(140);
#endif
#if defined(HAS_SX1262) || defined(HAS_SX1268) || defined(HAS_LLCC68)
radio.setRxBoostedGainMode(true);
#endif
if (state == RADIOLIB_ERR_NONE) {
Utils::println("init : LoRa Module ... done!");
} else {
Utils::println("Starting LoRa failed!");
Utils::println("Starting LoRa failed! State: " + String(state));
while (true);
}
}
@@ -92,127 +122,110 @@ namespace LoRa_Utils {
radio.setFrequency(freq);
}
void sendNewPacket(const String& typeOfMessage, const String& newPacket) {
void sendNewPacket(const String& newPacket) {
if (!Config.loramodule.txActive) return;
if (Config.loramodule.txFreq != Config.loramodule.rxFreq) {
changeFreqTx();
}
#ifdef HAS_INTERNAL_LED
digitalWrite(internalLedPin, HIGH);
#ifdef INTERNAL_LED_PIN
if (!Config.digi.ecoMode) digitalWrite(INTERNAL_LED_PIN, HIGH);
#endif
int state = radio.transmit("\x3c\xff\x01" + newPacket);
transmissionFlag = true;
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE) {
if (Config.syslog.active && WiFi.status() == WL_CONNECTED) {
SYSLOG_Utils::log("Tx", newPacket, 0, 0, 0);
SYSLOG_Utils::log(3, newPacket, 0, 0.0, 0); // TX
}
Utils::print("---> LoRa Packet Tx : ");
Utils::println(newPacket);
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
Utils::println(F("too long!"));
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
Utils::println(F("timeout!"));
} else {
Utils::print(F("failed, code "));
Utils::println(String(state));
}
#ifdef HAS_INTERNAL_LED
digitalWrite(internalLedPin, LOW);
#ifdef INTERNAL_LED_PIN
if (!Config.digi.ecoMode) digitalWrite(INTERNAL_LED_PIN, LOW);
#endif
if (Config.loramodule.txFreq != Config.loramodule.rxFreq) {
changeFreqRx();
}
//ignorePacket = true;
}
String generatePacket(String aprsisPacket) {
String firstPart, messagePart;
aprsisPacket.trim();
firstPart = aprsisPacket.substring(0, aprsisPacket.indexOf(","));
messagePart = aprsisPacket.substring(aprsisPacket.indexOf("::") + 2);
return firstPart + ",TCPIP,WIDE1-1," + Config.callsign + "::" + messagePart;
}
String packetSanitization(String packet) {
/*String packetSanitization(const String& packet) {
String sanitizedPacket = packet;
if (packet.indexOf("\0") > 0) {
packet.replace("\0", "");
sanitizedPacket.replace("\0", "");
}
if (packet.indexOf("\r") > 0) {
packet.replace("\r", "");
sanitizedPacket.replace("\r", "");
}
if (packet.indexOf("\n") > 0) {
packet.replace("\n", "");
sanitizedPacket.replace("\n", "");
}
return packet;
}
return sanitizedPacket;
}*/
void startReceive() {
radio.startReceive();
}
String receivePacket() {
if(!operationDone && !Config.lowPowerMode) return "";
operationDone = false;
String packet = "";
if (operationDone || Config.lowPowerMode) {
operationDone = false;
if (transmitFlag && !Config.lowPowerMode) {
radio.startReceive();
transmitFlag = false;
} else {
int state = radio.readData(packet);
if (state == RADIOLIB_ERR_NONE) {
if (packet != "") {
rssi = radio.getRSSI();
snr = radio.getSNR();
freqError = radio.getFrequencyError();
Utils::println("<--- LoRa Packet Rx : " + packet.substring(3));
Utils::println("(RSSI:" + String(rssi) + " / SNR:" + String(snr) + " / FreqErr:" + String(freqError) + ")");
String loraPacket = "";
if (transmissionFlag && !Config.lowPowerMode) {
radio.startReceive();
transmissionFlag = false;
} else {
int state = radio.readData(loraPacket);
if (state == RADIOLIB_ERR_NONE) {
if (loraPacket != "" && !ignorePacket) {
rssi = radio.getRSSI();
snr = radio.getSNR();
freqError = radio.getFrequencyError();
Utils::println("<--- LoRa Packet Rx : " + loraPacket);
Utils::println("(RSSI:" + String(rssi) + " / SNR:" + String(snr) + " / FreqErr:" + String(freqError) + ")");
if (!Config.lowPowerMode) {
ReceivedPacket receivedPacket;
receivedPacket.millis = millis();
receivedPacket.packet = loraPacket.substring(3);
receivedPacket.RSSI = rssi;
receivedPacket.SNR = snr;
if (receivedPackets.size() >= 20) {
receivedPackets.erase(receivedPackets.begin());
if (!Config.lowPowerMode && !Config.digi.ecoMode) {
if (receivedPackets.size() >= 10) {
receivedPackets.erase(receivedPackets.begin());
}
ReceivedPacket receivedPacket;
receivedPacket.rxTime = NTP_Utils::getFormatedTime();
receivedPacket.packet = packet.substring(3);
receivedPacket.RSSI = rssi;
receivedPacket.SNR = snr;
receivedPackets.push_back(receivedPacket);
}
receivedPackets.push_back(receivedPacket);
}
if (Config.syslog.active && WiFi.status() == WL_CONNECTED) {
SYSLOG_Utils::log(1, packet, rssi, snr, freqError); // RX
}
lastRxTime = millis();
return packet;
}
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
rssi = radio.getRSSI();
snr = radio.getSNR();
freqError = radio.getFrequencyError();
Utils::println(F("CRC error!"));
if (Config.syslog.active && WiFi.status() == WL_CONNECTED) {
SYSLOG_Utils::log("Rx", loraPacket, rssi, snr, freqError);
SYSLOG_Utils::log(0, packet, rssi, snr, freqError); // CRC
}
return loraPacket;
}
} else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
// timeout occurred while waiting for a packet
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
Utils::println(F("CRC error!"));
if (Config.syslog.active && WiFi.status() == WL_CONNECTED) {
SYSLOG_Utils::log("Rx", "RADIOLIB_ERR_CRC_MISMATCH", 0,0,0);
packet = "";
} else {
Utils::print(F("failed, code "));
Utils::println(String(state));
packet = "";
}
loraPacket = "";
} else {
Utils::print(F("failed, code "));
Utils::println(String(state));
}
if (ignorePacket) {
Utils::println("<--- LoRa Packet Rx : " + loraPacket);
Utils::println("Received own packet. Ignoring");
ignorePacket = false;
return "";
}
}
return loraPacket;
return packet;
}
void sleepRadio() {
radio.sleep();
}
}

View File

@@ -6,14 +6,14 @@
namespace LoRa_Utils {
void setup();
void sendNewPacket(const String &typeOfMessage, const String &newPacket);
String generatePacket(String aprsisPacket);
String packetSanitization(String packet);
String receivePacket();
void changeFreqTx();
void changeFreqRx();
void startReceive();
void setup();
void sendNewPacket(const String& newPacket);
//String packetSanitization(const String& packet);
String receivePacket();
void changeFreqTx();
void changeFreqRx();
void startReceive(); // ???
void sleepRadio();
}

34
src/ntp_utils.cpp Normal file
View File

@@ -0,0 +1,34 @@
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <WiFi.h>
#include "configuration.h"
#include "ntp_utils.h"
#include "time.h"
extern Configuration Config;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 0, 15 * 60 * 1000); // Update interval 15 min
namespace NTP_Utils {
void setup() {
if (WiFi.status() == WL_CONNECTED && !Config.digi.ecoMode && Config.callsign != "NOCALL-10") {
int gmt = Config.ntp.gmtCorrection * 3600;
timeClient.setTimeOffset(gmt);
timeClient.begin();
}
}
void update() {
if (WiFi.status() == WL_CONNECTED && !Config.digi.ecoMode && Config.callsign != "NOCALL-10") timeClient.update();
}
String getFormatedTime() {
if (!Config.digi.ecoMode) return timeClient.getFormattedTime();
return "DigiEcoMode Active";
}
}

14
src/ntp_utils.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef NTP_UTILS_H_
#define NTP_UTILS_H_
#include <Arduino.h>
namespace NTP_Utils {
void setup();
void update();
String getFormatedTime();
}
#endif

View File

@@ -29,31 +29,31 @@ namespace OTA_Utils {
void onOTAStart() {
Serial.println("OTA update started!");
display_toggle(true);
displayToggle(true);
lastScreenOn = millis();
show_display("", "", "", " OTA update started!", "", "", "", 1000);
displayShow("", "", "", " OTA update started!", "", "", "", 1000);
isUpdatingOTA = true;
}
void onOTAProgress(size_t current, size_t final) {
if (millis() - ota_progress_millis > 1000) {
display_toggle(true);
displayToggle(true);
lastScreenOn = millis();
ota_progress_millis = millis();
Serial.printf("OTA Progress Current: %u bytes, Final: %u bytes\n", current, final);
show_display("", "", " OTA Progress : " + String((current*100)/final) + "%", "", "", "", "", 100);
displayShow("", "", " OTA Progress : " + String((current*100)/final) + "%", "", "", "", "", 100);
}
}
void onOTAEnd(bool success) {
display_toggle(true);
displayToggle(true);
lastScreenOn = millis();
if (success) {
Serial.println("OTA update finished successfully!");
show_display("", "", " OTA update success!", "", " Rebooting ...", "", "", 4000);
displayShow("", "", " OTA update success!", "", " Rebooting ...", "", "", 4000);
} else {
Serial.println("There was an error during OTA update!");
show_display("", "", " OTA update fail!", "", "", "", "", 4000);
displayShow("", "", " OTA update fail!", "", "", "", "", 4000);
}
isUpdatingOTA = false;
}

View File

@@ -1,148 +0,0 @@
#ifndef PINS_CONFIG_H_
#define PINS_CONFIG_H_
#include <Arduino.h>
#undef OLED_SDA
#undef OLED_SCL
#undef OLED_RST
// LORA MODULES
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(ESP32_DIY_LoRa) || defined(TTGO_T_Beam_V1_2) || defined(TTGO_T_Beam_V1_0)
#define RADIO_SCLK_PIN 5 // GPIO5 - SX1278 SCK
#define RADIO_MISO_PIN 19 // GPIO19 - SX1278 MISO
#define RADIO_MOSI_PIN 27 // GPIO27 - SX1278 MOSI
#define RADIO_CS_PIN 18 // GPIO18 - SX1278 CS ---> NSS
#define RADIO_RST_PIN 14 // GPIO14 - SX1278 RST
#define RADIO_BUSY_PIN 26 // GPIO26 - SX1278 IRQ ---->DIO0
#endif
#if defined(HELTEC_V3) || defined(HELTEC_WS)
#define RADIO_SCLK_PIN 9 // SX1262 SCK
#define RADIO_MISO_PIN 11 // SX1262 MISO
#define RADIO_MOSI_PIN 10 // SX1262 MOSI
#define RADIO_CS_PIN 8 // SX1262 NSS
#define RADIO_RST_PIN 12 // SX1262 RST
#define RADIO_DIO1_PIN 14 // SX1262 DIO1
#define RADIO_BUSY_PIN 13 // SX1262 BUSY
#endif
#ifdef ESP32_DIY_1W_LoRa // Ebyte E22 400M30S / SX1268
#define RADIO_SCLK_PIN 18
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 23
#define RADIO_CS_PIN 5
#define RADIO_RST_PIN 27
#define RADIO_DIO1_PIN 12
#define RADIO_BUSY_PIN 14
#define RADIO_RXEN 32
#define RADIO_TXEN 25
#endif
#if defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2_SX1262)
#define RADIO_SCLK_PIN 5
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 27
#define RADIO_CS_PIN 18
#define RADIO_DIO0_PIN 26
#define RADIO_RST_PIN 23
#define RADIO_DIO1_PIN 33
#define RADIO_BUSY_PIN 32
#endif
#if defined(OE5HWN_MeshCom)
#define RADIO_SCLK_PIN 18
#define RADIO_MISO_PIN 19
#define RADIO_MOSI_PIN 23
#define RADIO_CS_PIN 5
#define RADIO_RST_PIN 27
#define RADIO_DIO1_PIN 33
#define RADIO_BUSY_PIN 26
#define RADIO_RXEN 14
#define RADIO_TXEN 13
#endif
#ifdef HELTEC_HTCT62
#define RADIO_SCLK_PIN 10 // SX1262 SCK
#define RADIO_MISO_PIN 6 // SX1262 MISO
#define RADIO_MOSI_PIN 7 // SX1262 MOSI
#define RADIO_CS_PIN 8 // SX1262 NSS
#define RADIO_RST_PIN 5 // SX1262 RST
#define RADIO_DIO1_PIN 3 // SX1262 DIO1
#define RADIO_BUSY_PIN 4 // SX1262 BUSY
#endif
// OLED
#if defined(TTGO_T_LORA32_V2_1) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa) || defined(TTGO_T_Beam_V1_0) || defined(TTGO_T_Beam_V1_2) || defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2_SX1262) || defined(OE5HWN_MeshCom)
#define OLED_SDA 21
#define OLED_SCL 22
#define OLED_RST -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#endif
#ifdef HELTEC_V2
#define OLED_SDA 4
#define OLED_SCL 15
#define OLED_RST 16
#endif
#if defined(HELTEC_V3) || defined(HELTEC_WS)
#define OLED_SDA 17
#define OLED_SCL 18
#define OLED_RST 21
#endif
#ifndef HELTEC_HTCT62
#define HAS_DISPLAY
#endif
// Leds and other stuff
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(HELTEC_WS) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
#define HAS_INTERNAL_LED
#endif
#ifdef HELTEC_HTCT62
#define batteryPin 1
#endif
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2)
#define internalLedPin 25 // Green Led
#define batteryPin 35
#endif
#if defined(HELTEC_V3) || defined(HELTEC_WS)
#define internalLedPin 35
#endif
#if defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
#define internalLedPin 2
#endif
#ifdef ESP32_C3_DIY_LoRa
#define OLED_SDA 8
#define OLED_SCL 9
#define OLED_RST 10
#define RADIO_SCLK_PIN 4
#define RADIO_MISO_PIN 5
#define RADIO_MOSI_PIN 6
#define RADIO_CS 7
#define RADIO_RST_PIN 3
#define RADIO_IRQ_PIN 2
#endif
/* (Same pins for LILYGO LoRa32 and ESP32 Wroom Dev )
SX1278-------------------> ESP32 ttgo-lora32-v21 and ESP32 WROOM Dev
GND GND
DIO1 -
DIO2 -
DIO3 -
VCC 3.3V
MISO 19
MOSI 27
SCLK 5
NSS 18
DIO0 26
REST 14
GND - */
#endif

View File

@@ -1,18 +1,19 @@
#include "configuration.h"
#include "battery_utils.h"
#include "boards_pinout.h"
#include "power_utils.h"
#include "pins_config.h"
#if defined(HAS_AXP192) || defined(HAS_AXP2101)
#define I2C_SDA 21
#define I2C_SCL 22
#define IRQ_PIN 35
#define I2C_SDA 21
#define I2C_SCL 22
#define IRQ_PIN 35
#endif
#ifdef HAS_AXP192
XPowersAXP192 PMU;
XPowersAXP192 PMU;
#endif
#ifdef HAS_AXP2101
XPowersAXP2101 PMU;
XPowersAXP2101 PMU;
#endif
extern Configuration Config;
@@ -20,111 +21,197 @@ extern Configuration Config;
namespace POWER_Utils {
bool BatteryIsConnected = false;
String batteryVoltage = "";
String batteryChargeDischargeCurrent = "";
double getBatteryVoltage() {
#if defined(HAS_AXP192) || defined(HAS_AXP2101)
return (PMU.getBattVoltage() / 1000.0);
#else
return 0.0;
#endif
}
bool isBatteryConnected() {
#if defined(HAS_AXP192) || defined(HAS_AXP2101)
return PMU.isBatteryConnect();
#else
return false;
#endif
}
void activateMeasurement() {
#if defined(HAS_AXP192) || defined(HAS_AXP2101)
PMU.disableTSPinMeasure();
PMU.enableBattDetection();
PMU.enableVbusVoltageMeasure();
PMU.enableBattVoltageMeasure();
PMU.enableSystemVoltageMeasure();
PMU.disableTSPinMeasure();
PMU.enableBattDetection();
PMU.enableVbusVoltageMeasure();
PMU.enableBattVoltageMeasure();
PMU.enableSystemVoltageMeasure();
#endif
}
void activateGPS() {
#ifdef HAS_AXP192
PMU.setLDO3Voltage(3300);
PMU.enableLDO3();
#endif
#ifdef HAS_AXP2101
PMU.setALDO3Voltage(3300);
PMU.enableALDO3();
#endif
#ifdef HELTEC_WIRELESS_TRACKER
digitalWrite(VEXT_CTRL, HIGH);
#endif
//gpsIsActive = true;
}
void deactivateGPS() {
#ifdef HAS_AXP192
PMU.disableLDO3();
#endif
#ifdef HAS_AXP2101
PMU.disableALDO3();
#endif
#ifdef HELTEC_WIRELESS_TRACKER
digitalWrite(VEXT_CTRL, LOW);
#endif
//gpsIsActive = false;
}
void activateLoRa() {
#ifdef HAS_AXP192
PMU.setLDO2Voltage(3300);
PMU.enableLDO2();
PMU.setLDO2Voltage(3300);
PMU.enableLDO2();
#endif
#ifdef HAS_AXP2101
PMU.setALDO2Voltage(3300);
PMU.enableALDO2();
PMU.setALDO2Voltage(3300);
PMU.enableALDO2();
#endif
}
void deactivateLoRa() {
#ifdef HAS_AXP192
PMU.disableLDO2();
PMU.disableLDO2();
#endif
#ifdef HAS_AXP2101
PMU.disableALDO2();
PMU.disableALDO2();
#endif
}
bool begin(TwoWire &port) {
#if defined(HAS_AXP192)
bool result = PMU.begin(Wire, AXP192_SLAVE_ADDRESS, I2C_SDA, I2C_SCL);
if (result) {
PMU.disableDC2();
PMU.disableLDO2();
PMU.disableLDO3();
PMU.setDC1Voltage(3300);
PMU.enableDC1();
PMU.setProtectedChannel(XPOWERS_DCDC3);
PMU.disableIRQ(XPOWERS_AXP192_ALL_IRQ);
}
return result;
bool result = PMU.begin(Wire, AXP192_SLAVE_ADDRESS, I2C_SDA, I2C_SCL);
if (result) {
PMU.disableDC2();
PMU.disableLDO2();
PMU.disableLDO3();
PMU.setDC1Voltage(3300);
PMU.enableDC1();
PMU.setProtectedChannel(XPOWERS_DCDC3);
PMU.disableIRQ(XPOWERS_AXP192_ALL_IRQ);
}
return result;
#elif defined(HAS_AXP2101)
bool result = PMU.begin(Wire, AXP2101_SLAVE_ADDRESS, I2C_SDA, I2C_SCL);
if (result) {
PMU.disableDC2();
PMU.disableDC3();
PMU.disableDC4();
PMU.disableDC5();
PMU.disableALDO1();
PMU.disableALDO4();
PMU.disableBLDO1();
PMU.disableBLDO2();
PMU.disableDLDO1();
PMU.disableDLDO2();
PMU.setDC1Voltage(3300);
PMU.enableDC1();
PMU.setButtonBatteryChargeVoltage(3300);
PMU.enableButtonBatteryCharge();
PMU.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
}
return result;
bool result = PMU.begin(Wire, AXP2101_SLAVE_ADDRESS, I2C_SDA, I2C_SCL);
if (result) {
PMU.disableDC2();
PMU.disableDC3();
PMU.disableDC4();
PMU.disableDC5();
PMU.disableALDO1();
PMU.disableALDO4();
PMU.disableBLDO1();
PMU.disableBLDO2();
PMU.disableDLDO1();
PMU.disableDLDO2();
PMU.setDC1Voltage(3300);
PMU.enableDC1();
PMU.setButtonBatteryChargeVoltage(3300);
PMU.enableButtonBatteryCharge();
PMU.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
}
return result;
#else
return true;
return true;
#endif
}
void setup() {
Wire.end();
#ifdef HAS_AXP192
Wire.begin(SDA, SCL);
if (begin(Wire)) {
Serial.println("AXP192 init done!");
} else {
Serial.println("AXP192 init failed!");
}
activateLoRa();
activateMeasurement();
PMU.setChargerTerminationCurr(XPOWERS_AXP192_CHG_ITERM_LESS_10_PERCENT);
PMU.setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
PMU.setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_780MA);
PMU.setSysPowerDownVoltage(2600);
Wire.begin(SDA, SCL);
if (begin(Wire)) {
Serial.println("AXP192 init done!");
} else {
Serial.println("AXP192 init failed!");
}
activateLoRa();
activateMeasurement();
PMU.setChargerTerminationCurr(XPOWERS_AXP192_CHG_ITERM_LESS_10_PERCENT);
PMU.setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
PMU.setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_780MA);
PMU.setSysPowerDownVoltage(2600);
#endif
#ifdef HAS_AXP2101
Wire.begin(SDA, SCL);
if (begin(Wire)) {
Serial.println("AXP2101 init done!");
} else {
Serial.println("AXP2101 init failed!");
}
activateLoRa();
activateMeasurement();
PMU.setPrechargeCurr(XPOWERS_AXP2101_PRECHARGE_200MA);
PMU.setChargerTerminationCurr(XPOWERS_AXP2101_CHG_ITERM_25MA);
PMU.setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2);
PMU.setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_800MA);
PMU.setSysPowerDownVoltage(2600);
Wire.begin(SDA, SCL);
if (begin(Wire)) {
Serial.println("AXP2101 init done!");
} else {
Serial.println("AXP2101 init failed!");
}
activateLoRa();
activateMeasurement();
PMU.setPrechargeCurr(XPOWERS_AXP2101_PRECHARGE_200MA);
PMU.setChargerTerminationCurr(XPOWERS_AXP2101_CHG_ITERM_25MA);
PMU.setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2);
PMU.setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_800MA);
PMU.setSysPowerDownVoltage(2600);
#endif
#ifdef BATTERY_PIN
pinMode(BATTERY_PIN, INPUT);
#endif
#ifdef INTERNAL_LED_PIN
pinMode(INTERNAL_LED_PIN, OUTPUT);
#endif
if (Config.battery.sendExternalVoltage || Config.battery.monitorExternalVoltage) {
pinMode(Config.battery.externalVoltagePin, INPUT);
}
#ifdef VEXT_CTRL
pinMode(VEXT_CTRL,OUTPUT); // GPS + TFT on HELTEC Wireless_Tracker and only for Oled in HELTEC V3
#ifndef HELTEC_WSL_V3
digitalWrite(VEXT_CTRL, HIGH);
#endif
#ifdef HELTEC_WP
digitalWrite(VEXT_CTRL, LOW);
#endif
#endif
#ifdef HAS_GPS
if (Config.beacon.gpsActive) activateGPS();
#endif
#ifdef ADC_CTRL
pinMode(ADC_CTRL, OUTPUT);
#endif
#if defined(HELTEC_WIRELESS_TRACKER)
Wire.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif
#if defined(HELTEC_V3) || defined(HELTEC_WP) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY)
Wire1.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif
#if defined(HELTEC_V3) || defined(HELTEC_WS) || defined(LIGHTGATEWAY_1_0) || defined(TTGO_LORA32_T3S3_V1_2)
Wire.begin(OLED_SDA, OLED_SCL);
#endif
delay(1000);
BATTERY_Utils::setup();
BATTERY_Utils::startupBatteryHealth();
}
}

View File

@@ -2,16 +2,24 @@
#define POWER_UTILS_H_
#include <Arduino.h>
#include "XPowersLib.h"
#if defined(HAS_AXP192) || defined(HAS_AXP2101)
#include "XPowersLib.h"
#else
#include <Wire.h>
#endif
namespace POWER_Utils {
void activateMeasurement();
void activateLoRa();
void deactivateLoRa();
bool begin(TwoWire &port);
void setup();
double getBatteryVoltage();
bool isBatteryConnected();
void activateMeasurement();
void activateGPS();
void deactivateGPS();
void activateLoRa();
void deactivateLoRa();
bool begin(TwoWire &port);
void setup();
}

View File

@@ -1,52 +1,89 @@
#include "configuration.h"
#include "station_utils.h"
#include "query_utils.h"
#include "lora_utils.h"
extern Configuration Config;
extern std::vector<String> lastHeardStation;
extern std::vector<String> lastHeardStation_temp;
extern String versionDate;
extern Configuration Config;
extern std::vector<LastHeardStation> lastHeardStations;
extern String versionDate;
extern int rssi;
extern float snr;
extern int freqError;
namespace QUERY_Utils {
String process(String query, String station, String queryOrigin) {
String process(const String& query, const String& station, bool queryFromAPRSIS, bool thirdParty) {
String answer;
if (query=="?APRS?" || query=="?aprs?" || query=="?Aprs?" || query=="H" || query=="h" || query=="HELP" || query=="Help" || query=="help" || query=="?") {
answer = "?APRSV ?APRSP ?APRSL ?APRSH ?WHERE callsign";
} else if (query=="?APRSV" || query=="?aprsv" || query=="?Aprsv") {
answer = "CA2RXU_LoRa_iGate 1.3 v" + versionDate;
} else if (query=="?APRSP" || query=="?aprsp" || query=="?Aprsp") {
answer = "iGate QTH: " + String(Config.beacon.latitude,2) + " " + String(Config.beacon.longitude,2);
} else if (query=="?APRSL" || query=="?aprsl" || query=="?Aprsl") {
if (lastHeardStation.size() == 0) {
answer = "No Station Listened in the last " + String(Config.rememberStationTime) + "min.";
String queryQuestion = query;
queryQuestion.toUpperCase();
if (queryQuestion == "?APRS?" || queryQuestion == "H" || queryQuestion == "HELP" || queryQuestion=="?") {
answer.concat("?APRSV ?APRSP ?APRSL ?APRSH ?WHERE callsign");
} else if (queryQuestion == "?APRSV") {
answer.concat("CA2RXU_LoRa_iGate 2.0 v");
answer.concat(versionDate);
} else if (queryQuestion == "?APRSP") {
answer.concat("iGate QTH: ");
answer.concat(String(Config.beacon.latitude,3));
answer.concat(" ");
answer.concat(String(Config.beacon.longitude,3));
} else if (queryQuestion == "?APRSL") {
if (lastHeardStations.size() == 0) {
char answerArray[50];
snprintf(answerArray, sizeof(answerArray), "No Station Listened in the last %d min.", Config.rememberStationTime);
answer.concat(answerArray);
} else {
for (int i=0; i<lastHeardStation.size(); i++) {
answer += lastHeardStation[i].substring(0,lastHeardStation[i].indexOf(",")) + " ";
for (int i=0; i<lastHeardStations.size(); i++) {
answer += lastHeardStations[i].station + " ";
}
answer.trim();
}
} else if (query.indexOf("?APRSH") == 0 || query.indexOf("?aprsh") == 0 || query.indexOf("?Aprsh") == 0) {
} else if (queryQuestion == "?APRSSR") {
char signalData[35];
snprintf(signalData, sizeof(signalData), " %ddBm / %.2fdB / %dHz", rssi, snr, freqError);
answer.concat(signalData);
} else if (queryQuestion.indexOf("?APRSH") == 0) {
// sacar callsign despues de ?APRSH
Serial.println("escuchaste a X estacion? en las ultimas 24 o 8 horas?");
answer = "APRSH on development 73!";
} else if (query.indexOf("?WHERE") == 0) {
answer.concat("?APRSH on development 73!");
} else if (queryQuestion.indexOf("?WHERE") == 0) {
// agregar callsign para completar donde esta X callsign --> posicion
Serial.println("estaciones escuchadas directo (ultimos 30 min)");
answer = "?WHERE on development 73!";
answer.concat("?WHERE on development 73!");
} else if (queryQuestion.indexOf("?APRSEEM") == 0 && Config.digi.ecoMode == true) { // Exit DigiRepeater EcoMode
answer = "DigiEcoMode:Stop";
Config.digi.ecoMode = false;
Config.display.alwaysOn = true;
Config.display.timeout = 10;
} else if (queryQuestion.indexOf("?APRSSEM") == 0 && Config.digi.ecoMode == false) { // Start DigiRepeater EcoMode
answer = "DigiEcoMode:Start";
Config.digi.ecoMode = true;
} else if (queryQuestion.indexOf("?APRSEMS") == 0) { // DigiRepeater EcoMode Status
answer = (Config.digi.ecoMode) ? "DigiEcoMode:ON" : "DigiEcoMode:OFF";
}
for(int i = station.length(); i < 9; i++) {
station += ' ';
}
if (queryOrigin == "APRSIS") {
return Config.callsign + ">APLRG1,TCPIP,qAC::" + station + ":" + answer;// + "\n";
} else { //} if (queryOrigin == "LoRa") {
if (Config.beacon.path == "") {
return Config.callsign + ">APLRG1,RFONLY::" + station + ":" + answer;
} else {
return Config.callsign + ">APLRG1,RFONLY," + Config.beacon.path + "::" + station + ":" + answer;
String queryAnswer = Config.callsign;
queryAnswer += ">APLRG1";
if (queryFromAPRSIS) {
queryAnswer += ",TCPIP,qAC";
} else {
if (!thirdParty) queryAnswer += ",RFONLY";
if (Config.beacon.path != "") {
queryAnswer += ",";
queryAnswer += Config.beacon.path;
}
}
queryAnswer += "::";
String processedStation = station;
for (int i = station.length(); i < 9; i++) {
processedStation += ' ';
}
queryAnswer += processedStation;
queryAnswer += ":";
queryAnswer += answer;
return queryAnswer;
}
}

View File

@@ -6,7 +6,7 @@
namespace QUERY_Utils {
String process(String query, String station, String queryOrigin);
String process(const String& query, const String& station, bool queryFromAPRSIS, bool thirdParty);
}

View File

@@ -1,65 +1,68 @@
#include "station_utils.h"
#include "battery_utils.h"
#include "aprs_is_utils.h"
#include "configuration.h"
#include "lora_utils.h"
#include "display.h"
#include "utils.h"
#include <vector>
extern Configuration Config;
extern std::vector<String> lastHeardStation;
extern std::vector<String> lastHeardStation_temp;
extern std::vector<String> packetBuffer;
extern std::vector<String> packetBuffer_temp;
extern String fourthLine;
extern Configuration Config;
extern uint32_t lastRxTime;
extern String fourthLine;
extern bool shouldSleepLowVoltage;
uint32_t lastTxTime = millis();
std::vector<LastHeardStation> lastHeardStations;
std::vector<String> outputPacketBuffer;
std::vector<Packet25SegBuffer> packet25SegBuffer;
namespace STATION_Utils {
void deleteNotHeard() {
for (int i = 0; i < lastHeardStation.size(); i++) {
String deltaTimeString = lastHeardStation[i].substring(lastHeardStation[i].indexOf(",") + 1);
uint32_t deltaTime = deltaTimeString.toInt();
if ((millis() - deltaTime) < Config.rememberStationTime * 60 * 1000) {
lastHeardStation_temp.push_back(lastHeardStation[i]);
std::vector<LastHeardStation> lastHeardStation_temp;
for (int i = 0; i < lastHeardStations.size(); i++) {
if (millis() - lastHeardStations[i].lastHeardTime < Config.rememberStationTime * 60 * 1000) {
lastHeardStation_temp.push_back(lastHeardStations[i]);
}
}
lastHeardStation.clear();
lastHeardStations.clear();
for (int j = 0; j < lastHeardStation_temp.size(); j++) {
lastHeardStation.push_back(lastHeardStation_temp[j]);
lastHeardStations.push_back(lastHeardStation_temp[j]);
}
lastHeardStation_temp.clear();
}
void updateLastHeard(String station) {
void updateLastHeard(const String& station) {
deleteNotHeard();
bool stationHeard = false;
for (int i = 0; i < lastHeardStation.size(); i++) {
if (lastHeardStation[i].substring(0, lastHeardStation[i].indexOf(",")) == station) {
lastHeardStation[i] = station + "," + String(millis());
for (int i = 0; i < lastHeardStations.size(); i++) {
if (lastHeardStations[i].station == station) {
lastHeardStations[i].lastHeardTime = millis();
stationHeard = true;
}
}
if (!stationHeard) {
lastHeardStation.push_back(station + "," + String(millis()));
LastHeardStation lastStation;
lastStation.lastHeardTime = millis();
lastStation.station = station;
lastHeardStations.push_back(lastStation);
}
fourthLine = "Stations (" + String(Config.rememberStationTime) + "min) = ";
if (lastHeardStation.size() < 10) {
fourthLine = "Stations (";
fourthLine += String(Config.rememberStationTime);
fourthLine += "min) = ";
if (lastHeardStations.size() < 10) {
fourthLine += " ";
}
fourthLine += String(lastHeardStation.size());
// DEBUG ONLY
// Serial.print("Stations Near (last " + String(Config.rememberStationTime) + " minutes): ");
// for (int k=0; k<lastHeardStation.size(); k++) {
// Serial.print(lastHeardStation[k].substring(0,lastHeardStation[k].indexOf(","))); Serial.print(" ");
// }
// Serial.println("");
fourthLine += String(lastHeardStations.size());
}
bool wasHeard(String station) {
bool wasHeard(const String& station) {
deleteNotHeard();
for (int i = 0; i < lastHeardStation.size(); i++) {
if (lastHeardStation[i].substring(0, lastHeardStation[i].indexOf(",")) == station) {
for (int i = 0; i < lastHeardStations.size(); i++) {
if (lastHeardStations[i].station == station) {
Utils::println(" ---> Listened Station");
return true;
}
@@ -68,37 +71,65 @@ namespace STATION_Utils {
return false;
}
void checkBuffer() {
for (int i = 0; i < packetBuffer.size(); i++) {
String deltaTimeString = packetBuffer[i].substring(0, packetBuffer[i].indexOf(","));
uint32_t deltaTime = deltaTimeString.toInt();
if ((millis() - deltaTime) < 60 * 1000) { // cambiar a 15 segundos?
packetBuffer_temp.push_back(packetBuffer[i]);
void clean25SegBuffer() {
if (!packet25SegBuffer.empty()) {
if ((millis() - packet25SegBuffer[0].receivedTime) > 25 * 1000) {
packet25SegBuffer.erase(packet25SegBuffer.begin());
}
}
packetBuffer.clear();
for (int j = 0; j < packetBuffer_temp.size(); j++) {
packetBuffer.push_back(packetBuffer_temp[j]);
}
packetBuffer_temp.clear();
// DEBUG ONLY
// for (int i=0; i<packetBuffer.size(); i++) {
// Serial.println(packetBuffer[i]);
// }
}
void updatePacketBuffer(String packet) {
if ((packet.indexOf(":!") == -1) && (packet.indexOf(":=") == -1) && (packet.indexOf(":>") == -1) && (packet.indexOf(":`") == -1)) {
String sender = packet.substring(3, packet.indexOf(">"));
String tempAddressee = packet.substring(packet.indexOf("::") + 2);
String addressee = tempAddressee.substring(0, tempAddressee.indexOf(":"));
addressee.trim();
String message = tempAddressee.substring(tempAddressee.indexOf(":") + 1);
//Serial.println(String(millis()) + "," + sender + "," + addressee + "," + message);
packetBuffer.push_back(String(millis()) + "," + sender + "," + addressee + "," + message);
checkBuffer();
bool check25SegBuffer(const String& station, const String& textMessage) {
bool shouldBeIgnored = false;
if (!packet25SegBuffer.empty()) {
for (int i = 0; i < packet25SegBuffer.size(); i++) {
if (packet25SegBuffer[i].station == station && packet25SegBuffer[i].payload == textMessage) {
shouldBeIgnored = true;
}
}
}
if (shouldBeIgnored) {
return false;
} else {
Packet25SegBuffer packet;
packet.receivedTime = millis();
packet.station = station;
packet.payload = textMessage;
packet25SegBuffer.push_back(packet);
return true;
}
}
void processOutputPacketBuffer() {
int timeToWait = 3 * 1000; // 3 segs between packet Tx and also Rx ???
uint32_t lastRx = millis() - lastRxTime;
uint32_t lastTx = millis() - lastTxTime;
bool saveNewDigiEcoModeConfig = false;
if (outputPacketBuffer.size() > 0 && lastTx > timeToWait && lastRx > timeToWait) {
LoRa_Utils::sendNewPacket(outputPacketBuffer[0]);
if (outputPacketBuffer[0].indexOf("DigiEcoMode:Start") != -1 || outputPacketBuffer[0].indexOf("DigiEcoMode:Stop") != -1) {
saveNewDigiEcoModeConfig = true;
shouldSleepLowVoltage = true; // to make sure all packets in outputPacketBuffer are sended before restart.
}
outputPacketBuffer.erase(outputPacketBuffer.begin());
lastTxTime = millis();
}
if (shouldSleepLowVoltage) {
while (outputPacketBuffer.size() > 0) {
LoRa_Utils::sendNewPacket(outputPacketBuffer[0]);
outputPacketBuffer.erase(outputPacketBuffer.begin());
delay(4000);
}
}
if (saveNewDigiEcoModeConfig) {
Config.writeFile();
displayToggle(false);
ESP.restart();
}
}
void addToOutputPacketBuffer(const String& packet) {
outputPacketBuffer.push_back(packet);
}
}

View File

@@ -1,16 +1,31 @@
#ifndef STATION_UTILS_H_
#define STATION_UTILS_H_
#include <Arduino.h>
struct Packet25SegBuffer {
uint32_t receivedTime;
String station;
String payload;
};
struct LastHeardStation {
uint32_t lastHeardTime;
String station;
};
namespace STATION_Utils {
void deleteNotHeard();
void updateLastHeard(String station);
bool wasHeard(String station);
void checkBuffer();
void updatePacketBuffer(String packet);
void updateLastHeard(const String& station);
bool wasHeard(const String& station);
void clean25SegBuffer();
bool check25SegBuffer(const String& station, const String& textMessage);
void processOutputPacketBuffer();
void addToOutputPacketBuffer(const String& packet);
}

View File

@@ -11,53 +11,98 @@ WiFiUDP udpClient;
namespace SYSLOG_Utils {
void log(String type, String packet, int rssi, float snr, int freqError) {
String syslogPacket = "<165>1 - " + Config.callsign + " CA2RXU_LoRa_iGate_1.3" + " - - - "; //RFC5424 The Syslog Protocol
void log(const uint8_t type, const String& packet, const int rssi, const float snr, const int freqError) {
if (Config.syslog.active && WiFi.status() == WL_CONNECTED) {
if (type == "APRSIS Tx") {
if (packet.indexOf(":>") > 10) {
syslogPacket += type + " / StartUp_Status / " + packet.substring(packet.indexOf(":>")+2);
} else {
syslogPacket += type + " / QUERY / " + packet;
}
} else if (type == "Rx") {
if (packet.indexOf("::") > 10) {
syslogPacket += type + " / MESSAGE / " + packet.substring(3,packet.indexOf(">")) + " ---> " + packet.substring(packet.indexOf("::")+2);
syslogPacket += " / " + String(rssi) + "dBm / " + String(snr) + "dB / " + String(freqError) + "Hz";
} else if (packet.indexOf(":!") > 10 || packet.indexOf(":=") > 10) {
syslogPacket += type + " / GPS / " + packet.substring(3,packet.indexOf(">")) + " / ";
if (packet.indexOf("WIDE1-1") > 10) {
syslogPacket += packet.substring(packet.indexOf(">")+1,packet.indexOf(",")) + " / WIDE1-1 / ";
String syslogPacket = "<165>1 - ";
syslogPacket.concat(Config.callsign);
syslogPacket.concat(" CA2RXU_LoRa_iGate_1.3 - - - "); //RFC5424 The Syslog Protocol
char signalData[35];
snprintf(signalData, sizeof(signalData), " / %ddBm / %.2fdB / %dHz", rssi, snr, freqError);
switch (type) {
case 0: // CRC
syslogPacket.concat("CRC / CRC-ERROR / ");
syslogPacket.concat(packet);
syslogPacket.concat(signalData);
break;
case 1: // RX
syslogPacket.concat("RX / ");
if (packet.indexOf("::") > 10) {
syslogPacket.concat("MESSAGE / ");
syslogPacket.concat(packet.substring(3, packet.indexOf(">")));
syslogPacket.concat(" ---> "); syslogPacket.concat(packet.substring(packet.indexOf("::") + 2));
syslogPacket.concat(signalData);
} else if (packet.indexOf(":!") > 10 || packet.indexOf(":=") > 10) {
syslogPacket.concat("GPS / ");
syslogPacket.concat(packet.substring(3, packet.indexOf(">")));
syslogPacket.concat(" / ");
if (packet.indexOf("WIDE1-1") > 10) {
syslogPacket.concat(packet.substring(packet.indexOf(">") + 1, packet.indexOf(",")));
syslogPacket.concat(" / WIDE1-1");
} else {
syslogPacket.concat(packet.substring(packet.indexOf(">") + 1, packet.indexOf(":")));
syslogPacket.concat(" / -");
}
syslogPacket.concat(signalData);
syslogPacket.concat(" / ");
syslogPacket.concat(GPS_Utils::getDistanceAndComment(packet));
} else if (packet.indexOf(":>") > 10) {
syslogPacket.concat("STATUS / ");
syslogPacket.concat(packet.substring(3, packet.indexOf(">")));
syslogPacket.concat(" ---> ");
syslogPacket.concat(packet.substring(packet.indexOf(":>") + 2));
syslogPacket.concat(signalData);
} else if (packet.indexOf(":`") > 10) {
syslogPacket.concat("MIC-E / ");
syslogPacket.concat(packet.substring(3, packet.indexOf(">")));
syslogPacket.concat(" ---> ");
syslogPacket.concat(packet.substring(packet.indexOf(":`") + 2));
syslogPacket.concat(signalData);
} else if (packet.indexOf(":T#") >= 10 && packet.indexOf(":=/") == -1) {
syslogPacket.concat("TELEMETRY / ");
syslogPacket.concat(packet.substring(3, packet.indexOf(">")));
syslogPacket.concat(" ---> ");
syslogPacket.concat(packet.substring(packet.indexOf(":T#") + 3));
syslogPacket.concat(signalData);
} else if (packet.indexOf(":;") > 10) {
syslogPacket.concat("OBJECT / ");
syslogPacket.concat(packet.substring(3, packet.indexOf(">")));
syslogPacket.concat(" ---> ");
syslogPacket.concat(packet.substring(packet.indexOf(":;") + 2));
syslogPacket.concat(signalData);
} else {
syslogPacket += packet.substring(packet.indexOf(">")+1,packet.indexOf(":")) + " / - / ";
syslogPacket.concat(packet);
syslogPacket.concat(signalData);
}
syslogPacket += String(rssi) + "dBm / " + String(snr) + "dB / " + String(freqError) + "Hz / " + GPS_Utils::getDistance(packet);
} else if (packet.indexOf(":>") > 10) {
syslogPacket += type + " / STATUS / " + packet.substring(3,packet.indexOf(">")) + " ---> " + packet.substring(packet.indexOf(":>")+2);
syslogPacket += " / " + String(rssi) + "dBm / " + String(snr) + "dB / " + String(freqError) + "Hz";
} else if (packet.indexOf(":`") > 10) {
syslogPacket += type + " / MIC-E / " + packet.substring(3,packet.indexOf(">")) + " ---> " + packet.substring(packet.indexOf(":`")+2);
syslogPacket += " / " + String(rssi) + "dBm / " + String(snr) + "dB / " + String(freqError) + "Hz";
} else if (packet.indexOf(":T#") >= 10 && packet.indexOf(":=/") == -1) {
syslogPacket += type + " / TELEMETRY / " + packet.substring(3,packet.indexOf(">")) + " ---> " + packet.substring(packet.indexOf(":T#")+3);
syslogPacket += " / " + String(rssi) + "dBm / " + String(snr) + "dB / " + String(freqError) + "Hz";
} else if (packet.indexOf(":;") > 10) {
syslogPacket += type + " / OBJECT / " + packet.substring(3,packet.indexOf(">")) + " ---> " + packet.substring(packet.indexOf(":;")+2);
syslogPacket += " / " + String(rssi) + "dBm / " + String(snr) + "dB / " + String(freqError) + "Hz";
} else {
syslogPacket += type + " / " + packet;
syslogPacket += " / " + String(rssi) + "dBm / " + String(snr) + "dB / " + String(freqError) + "Hz";
}
} else if (type == "Tx") {
if (packet.indexOf("RFONLY") > 10) {
syslogPacket += type + " / RFONLY / " + packet;
} else if (packet.indexOf("::") > 10) {
syslogPacket += type + " / MESSAGE / " + packet.substring(0,packet.indexOf(">")) + " ---> " + packet.substring(packet.indexOf("::")+2);
} else {
syslogPacket += type + " / " + packet;
}
} else {
syslogPacket = "<165>1 - ERROR LoRa - - - ERROR / Error in Syslog Packet"; //RFC5424 The Syslog Protocol
break;
case 2: // APRSIS TX
syslogPacket.concat("APRSIS TX / ");
if (packet.indexOf(":>") > 10) {
syslogPacket.concat("StartUp_Status / ");
syslogPacket.concat(packet.substring(packet.indexOf(":>") + 2));
} else {
syslogPacket.concat("QUERY / ");
syslogPacket.concat(packet);
}
break;
case 3: // TX
syslogPacket.concat("TX / ");
if (packet.indexOf("RFONLY") > 10) {
syslogPacket.concat("RFONLY / ");
syslogPacket.concat(packet);
} else if (packet.indexOf("::") > 10) {
syslogPacket.concat("MESSAGE / ");
syslogPacket.concat(packet.substring(0,packet.indexOf(">")));
syslogPacket.concat(" ---> ");
syslogPacket.concat(packet.substring(packet.indexOf("::") + 2));
} else {
syslogPacket.concat(packet);
}
break;
default:
syslogPacket = "<165>1 - ERROR LoRa - - - ERROR / Error in Syslog Packet"; //RFC5424 The Syslog Protocol
break;
}
udpClient.beginPacket(Config.syslog.server.c_str(), Config.syslog.port);
udpClient.write((const uint8_t*)syslogPacket.c_str(), syslogPacket.length());

View File

@@ -6,7 +6,7 @@
namespace SYSLOG_Utils {
void log(String type ,String packet, int rssi, float snr, int freqError);
void log(const uint8_t type ,const String& packet, const int rssi, const float snr, const int freqError);
void setup();
}

View File

@@ -1,8 +1,8 @@
#include <WiFi.h>
#include "kiss_utils.h"
#include "kiss_protocol.h"
#include "lora_utils.h"
#include "configuration.h"
#include "station_utils.h"
#include "utils.h"
extern Configuration Config;
@@ -22,24 +22,20 @@ String inputSerialBuffer = "";
namespace TNC_Utils {
void setup() {
if (Config.tnc.enableServer) {
if (Config.tnc.enableServer && !Config.digi.ecoMode) {
tncServer.stop();
tncServer.begin();
}
}
void checkNewClients() {
WiFiClient new_client = tncServer.available();
WiFiClient new_client = tncServer.accept();
if (new_client.connected()) {
for (int i = 0; i < MAX_CLIENTS; i++) {
WiFiClient* client = clients[i];
if (client == nullptr) {
clients[i] = new WiFiClient(new_client);
Utils::println("New TNC client connected");
break;
}
}
@@ -48,13 +44,11 @@ namespace TNC_Utils {
void handleInputData(char character, int bufferIndex) {
String* data;
if (bufferIndex == -1) {
data = &inputSerialBuffer;
} else {
data = &inputServerBuffer[bufferIndex];
}
if (data->length() == 0 && character != (char)FEND) {
return;
}
@@ -74,12 +68,11 @@ namespace TNC_Utils {
String sender = frame.substring(0,frame.indexOf(">"));
if (Config.tnc.acceptOwn || sender != Config.callsign) {
LoRa_Utils::sendNewPacket("APRS", frame);
STATION_Utils::addToOutputPacketBuffer(frame);
} else {
Utils::println("Ignored own frame from KISS");
}
}
data->clear();
}
@@ -112,10 +105,10 @@ namespace TNC_Utils {
}
}
void sendToClients(String packet) {
packet = packet.substring(3);
void sendToClients(const String& packet) {
String cleanPacket = packet.substring(3);
const String kissEncoded = encodeKISS(packet);
const String kissEncoded = encodeKISS(cleanPacket);
for (int i = 0; i < MAX_CLIENTS; i++) {
auto client = clients[i];
@@ -129,27 +122,25 @@ namespace TNC_Utils {
}
}
}
Utils::print("---> Sent to TNC : ");
Utils::println(packet);
Utils::println(cleanPacket);
}
void sendToSerial(String packet) {
packet = packet.substring(3);
Serial.print(encodeKISS(packet));
void sendToSerial(const String& packet) {
String cleanPacket = packet.substring(3);
Serial.print(encodeKISS(cleanPacket));
Serial.flush();
}
void loop() {
if (Config.tnc.enableServer) {
checkNewClients();
readFromClients();
}
if (Config.tnc.enableSerial) {
readFromSerial();
if (!Config.digi.ecoMode) {
if (Config.tnc.enableServer) {
checkNewClients();
readFromClients();
}
if (Config.tnc.enableSerial) {
readFromSerial();
}
}
}
}

View File

@@ -8,8 +8,8 @@ namespace TNC_Utils {
void setup();
void loop();
void sendToClients(String packet);
void sendToSerial(String packet);
void sendToClients(const String& packet);
void sendToSerial(const String& packet);
}

View File

@@ -1,21 +1,24 @@
#include <TinyGPS++.h>
#include <WiFi.h>
#include "configuration.h"
#include "station_utils.h"
#include "battery_utils.h"
#include "aprs_is_utils.h"
#include "boards_pinout.h"
#include "syslog_utils.h"
#include "pins_config.h"
#include "wifi_utils.h"
#include "A7670_utils.h"
#include "lora_utils.h"
#include "wifi_utils.h"
#include "gps_utils.h"
#include "bme_utils.h"
#include "wx_utils.h"
#include "display.h"
#include "utils.h"
extern WiFiClient espClient;
extern Configuration Config;
extern WiFiClient espClient;
extern TinyGPSPlus gps;
extern String versionDate;
extern bool statusAfterBoot;
extern String firstLine;
extern String secondLine;
extern String thirdLine;
@@ -23,125 +26,280 @@ extern String fourthLine;
extern String fifthLine;
extern String sixthLine;
extern String seventhLine;
extern uint32_t lastBeaconTx;
extern uint32_t lastScreenOn;
extern bool beaconUpdate;
extern String iGateBeaconPacket;
extern String iGateLoRaBeaconPacket;
extern std::vector<String> lastHeardStation;
extern int rssi;
extern float snr;
extern int freqError;
extern String distance;
extern uint32_t lastWiFiCheck;
extern bool WiFiConnect;
extern bool WiFiConnected;
extern int wxModuleType;
extern bool backUpDigiMode;
extern bool shouldSleepLowVoltage;
extern bool transmitFlag;
extern std::vector<LastHeardStation> lastHeardStations;
bool statusAfterBoot = true;
bool sendStartTelemetry = true;
bool beaconUpdate = true;
uint32_t lastBeaconTx = 0;
uint32_t lastScreenOn = millis();
String beaconPacket;
String secondaryBeaconPacket;
namespace Utils {
void processStatus() {
String status = Config.callsign + ">APLRG1," + Config.beacon.path;
String status = Config.callsign;
status.concat(">APLRG1");
if (Config.beacon.path.indexOf("WIDE") == 0) {
status.concat(",");
status.concat(Config.beacon.path);
}
if (WiFi.status() == WL_CONNECTED && Config.aprs_is.active && Config.beacon.sendViaAPRSIS) {
delay(1000);
status += ",qAC:>https://github.com/richonguzman/LoRa_APRS_iGate " + versionDate;
status.concat(",qAC:>https://github.com/richonguzman/LoRa_APRS_iGate ");
status.concat(versionDate);
APRS_IS_Utils::upload(status);
SYSLOG_Utils::log("APRSIS Tx", status,0,0,0);
SYSLOG_Utils::log(2, status, 0, 0.0, 0); // APRSIS TX
statusAfterBoot = false;
}
if (statusAfterBoot && !Config.beacon.sendViaAPRSIS && Config.beacon.sendViaRF) {
delay(2000);
status += ":>https://github.com/richonguzman/LoRa_APRS_iGate " + versionDate;
LoRa_Utils::sendNewPacket("APRS", status);
status.concat(":>https://github.com/richonguzman/LoRa_APRS_iGate ");
status.concat(versionDate);
STATION_Utils::addToOutputPacketBuffer(status);
statusAfterBoot = false;
}
}
String getLocalIP() {
if (!WiFiConnected) {
if (Config.digi.ecoMode) {
return "** WiFi AP Killed **";
} else if (!WiFiConnected) {
return "IP : 192.168.4.1";
} else if (backUpDigiMode) {
return "- BACKUP DIGI MODE -";
} else {
return "IP : " + String(WiFi.localIP()[0]) + "." + String(WiFi.localIP()[1]) + "." + String(WiFi.localIP()[2]) + "." + String(WiFi.localIP()[3]);
}
}
void setupDisplay() {
setup_display();
#ifdef HAS_INTERNAL_LED
digitalWrite(internalLedPin,HIGH);
displaySetup();
#ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN,HIGH);
#endif
Serial.println("\nStarting Station: " + Config.callsign + " Version: " + versionDate);
show_display(" LoRa APRS", "", " ( iGATE & DIGI )", "", "", "Richonguzman / CA2RXU", " " + versionDate, 4000);
#ifdef HAS_INTERNAL_LED
digitalWrite(internalLedPin,LOW);
Serial.println((Config.digi.ecoMode) ? "(DigiEcoMode: ON)" : "(DigiEcoMode: OFF)");
displayShow(" LoRa APRS", "", "", " ( iGATE & DIGI )", "", "" , " CA2RXU " + versionDate, 4000);
#ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN,LOW);
#endif
firstLine = Config.callsign;
seventhLine = " listening...";
}
void activeStations() {
fourthLine = "Stations (" + String(Config.rememberStationTime) + "min) = ";
if (lastHeardStation.size() < 10) {
fourthLine = "Stations (";
fourthLine.concat(String(Config.rememberStationTime));
fourthLine.concat("min) = ");
if (lastHeardStations.size() < 10) {
fourthLine += " ";
}
fourthLine += String(lastHeardStation.size());
fourthLine.concat(String(lastHeardStations.size()));
}
void sendInitialTelemetryPackets() {
String sender = Config.callsign;
for (int i = sender.length(); i < 9; i++) {
sender += ' ';
}
String baseAPRSISTelemetryPacket = Config.callsign;
baseAPRSISTelemetryPacket += ">APLRG1,TCPIP,qAC::";
baseAPRSISTelemetryPacket += sender;
baseAPRSISTelemetryPacket += ":";
String baseRFTelemetryPacket = Config.callsign;
baseRFTelemetryPacket += ">APLRG1,WIDE1-1::";
baseRFTelemetryPacket += sender;
baseRFTelemetryPacket += ":";
String telemetryPacket1 = "EQNS.";
if (Config.battery.sendInternalVoltage) {
telemetryPacket1 += "0,0.01,0";
}
if (Config.battery.sendExternalVoltage) {
telemetryPacket1 += String(Config.battery.sendInternalVoltage ? "," : "") + "0,0.02,0";
}
String telemetryPacket2 = "UNIT.";
if (Config.battery.sendInternalVoltage) {
telemetryPacket2 += "VDC";
}
if (Config.battery.sendExternalVoltage) {
telemetryPacket2 += String(Config.battery.sendInternalVoltage ? "," : "") + "VDC";
}
String telemetryPacket3 = "PARM.";
if (Config.battery.sendInternalVoltage) {
telemetryPacket3 += "V_Batt";
}
if (Config.battery.sendExternalVoltage) {
telemetryPacket3 += String(Config.battery.sendInternalVoltage ? "," : "") + "V_Ext";
}
if (Config.beacon.sendViaAPRSIS) {
#ifdef HAS_A7670
A7670_Utils::uploadToAPRSIS(baseAPRSISTelemetryPacket + telemetryPacket1);
delay(300);
A7670_Utils::uploadToAPRSIS(baseAPRSISTelemetryPacket + telemetryPacket2);
delay(300);
A7670_Utils::uploadToAPRSIS(baseAPRSISTelemetryPacket + telemetryPacket3);
delay(300);
#else
APRS_IS_Utils::upload(baseAPRSISTelemetryPacket + telemetryPacket1);
delay(300);
APRS_IS_Utils::upload(baseAPRSISTelemetryPacket + telemetryPacket2);
delay(300);
APRS_IS_Utils::upload(baseAPRSISTelemetryPacket + telemetryPacket3);
delay(300);
#endif
delay(300);
} else if (Config.beacon.sendViaRF) {
LoRa_Utils::sendNewPacket(baseRFTelemetryPacket + telemetryPacket1);
delay(3000);
LoRa_Utils::sendNewPacket(baseRFTelemetryPacket + telemetryPacket2);
delay(3000);
LoRa_Utils::sendNewPacket(baseRFTelemetryPacket + telemetryPacket3);
delay(3000);
}
sendStartTelemetry = false;
}
void checkBeaconInterval() {
uint32_t lastTx = millis() - lastBeaconTx;
String beaconPacket = iGateBeaconPacket;
String secondaryBeaconPacket = iGateLoRaBeaconPacket;
if (lastBeaconTx == 0 || lastTx >= Config.beacon.interval * 60 * 1000) {
beaconUpdate = true;
}
#ifdef HAS_GPS
if (Config.beacon.gpsActive && gps.location.lat() == 0.0 && gps.location.lng() == 0.0 && Config.beacon.latitude == 0.0 && Config.beacon.longitude == 0.0) {
GPS_Utils::getData();
beaconUpdate = false;
}
#endif
if (beaconUpdate) {
display_toggle(true);
Utils::println("-- Sending Beacon to APRSIS --");
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
displayToggle(true);
}
if (sendStartTelemetry && Config.battery.sendVoltageAsTelemetry && !Config.wxsensor.active && (Config.battery.sendInternalVoltage || Config.battery.sendExternalVoltage)) {
sendInitialTelemetryPackets();
}
STATION_Utils::deleteNotHeard();
activeStations();
if (Config.bme.active) {
String sensorData = BME_Utils::readDataSensor();
beaconPacket += sensorData;
secondaryBeaconPacket += sensorData;
}
beaconPacket += Config.beacon.comment;
secondaryBeaconPacket += Config.beacon.comment;
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_HTCT62)
if (Config.sendBatteryVoltage) {
beaconPacket += " Batt=" + String(BATTERY_Utils::checkBattery(),2) + "V";
secondaryBeaconPacket += " Batt=" + String(BATTERY_Utils::checkBattery(),2) + "V";
sixthLine = " (Batt=" + String(BATTERY_Utils::checkBattery(),2) + "V)";
}
beaconPacket = iGateBeaconPacket;
secondaryBeaconPacket = iGateLoRaBeaconPacket;
#ifdef HAS_GPS
if (Config.beacon.gpsActive && !Config.digi.ecoMode) {
GPS_Utils::getData();
if (gps.location.isUpdated() && gps.location.lat() != 0.0 && gps.location.lng() != 0.0) {
GPS_Utils::generateBeaconFirstPart();
String encodedGPS = GPS_Utils::encodeGPS(gps.location.lat(), gps.location.lng(), Config.beacon.overlay, Config.beacon.symbol);
beaconPacket = iGateBeaconPacket + encodedGPS;
secondaryBeaconPacket = iGateLoRaBeaconPacket + encodedGPS;
}
}
#endif
if (Config.externalVoltageMeasurement) {
beaconPacket += " Ext=" + String(BATTERY_Utils::checkExternalVoltage(),2) + "V";
secondaryBeaconPacket += " Ext=" + String(BATTERY_Utils::checkExternalVoltage(),2) + "V";
sixthLine = " (Ext V=" + String(BATTERY_Utils::checkExternalVoltage(),2) + "V)";
if (Config.wxsensor.active && wxModuleType != 0) {
String sensorData = WX_Utils::readDataSensor();
beaconPacket += sensorData;
secondaryBeaconPacket += sensorData;
} else if (Config.wxsensor.active && wxModuleType == 0) {
beaconPacket += ".../...g...t...";
secondaryBeaconPacket += ".../...g...t...";
}
beaconPacket += Config.beacon.comment;
secondaryBeaconPacket += Config.beacon.comment;
#if defined(BATTERY_PIN) || defined(HAS_AXP192) || defined(HAS_AXP2101)
if (Config.battery.sendInternalVoltage || Config.battery.monitorInternalVoltage) {
float internalVoltage = BATTERY_Utils::checkInternalVoltage();
if (Config.battery.monitorInternalVoltage && internalVoltage < Config.battery.internalSleepVoltage) {
beaconPacket += " **IntBatWarning:SLEEP**";
secondaryBeaconPacket += " **IntBatWarning:SLEEP**";
shouldSleepLowVoltage = true;
}
String internalVoltageInfo = String(internalVoltage,2) + "V";
if (Config.battery.sendInternalVoltage) {
sixthLine = " (Batt=";
sixthLine += internalVoltageInfo;
sixthLine += ")";
if (!Config.battery.sendVoltageAsTelemetry) {
beaconPacket += " Batt=";
beaconPacket += internalVoltageInfo;
secondaryBeaconPacket += " Batt=";
secondaryBeaconPacket += internalVoltageInfo;
}
}
}
#endif
#ifndef HELTEC_WP
if (Config.battery.sendExternalVoltage || Config.battery.monitorExternalVoltage) {
float externalVoltage = BATTERY_Utils::checkExternalVoltage();
if (Config.battery.monitorExternalVoltage && externalVoltage < Config.battery.externalSleepVoltage) {
beaconPacket += " **ExtBatWarning:SLEEP**";
secondaryBeaconPacket += " **ExtBatWarning:SLEEP**";
shouldSleepLowVoltage = true;
}
String externalVoltageInfo = String(externalVoltage,2) + "V";
if (Config.battery.sendExternalVoltage) {
sixthLine = " (Ext V=";
sixthLine += externalVoltageInfo;
sixthLine += ")";
if (!Config.battery.sendVoltageAsTelemetry) {
beaconPacket += " Ext=";
beaconPacket += externalVoltageInfo;
secondaryBeaconPacket += " Ext=";
secondaryBeaconPacket += externalVoltageInfo;
}
}
}
#endif
if (Config.battery.sendVoltageAsTelemetry && !Config.wxsensor.active && (Config.battery.sendInternalVoltage || Config.battery.sendExternalVoltage)){
String encodedTelemetry = BATTERY_Utils::generateEncodedTelemetry();
beaconPacket += encodedTelemetry;
secondaryBeaconPacket += encodedTelemetry;
}
if (Config.aprs_is.active && Config.beacon.sendViaAPRSIS) {
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, "SENDING IGATE BEACON", 0);
if (Config.aprs_is.active && Config.beacon.sendViaAPRSIS && !backUpDigiMode) {
Utils::println("-- Sending Beacon to APRSIS --");
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, "SENDING IGATE BEACON", 0);
seventhLine = " listening...";
APRS_IS_Utils::upload(beaconPacket);
#ifdef HAS_A7670
A7670_Utils::uploadToAPRSIS(beaconPacket);
#else
APRS_IS_Utils::upload(beaconPacket);
#endif
}
if (Config.beacon.sendViaRF) {
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, "SENDING DIGI BEACON", 0);
if (Config.beacon.sendViaRF || backUpDigiMode) {
Utils::println("-- Sending Beacon to RF --");
displayShow(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, "SENDING DIGI BEACON", 0);
seventhLine = " listening...";
LoRa_Utils::sendNewPacket("APRS", secondaryBeaconPacket);
STATION_Utils::addToOutputPacketBuffer(secondaryBeaconPacket);
}
lastBeaconTx = millis();
@@ -156,61 +314,59 @@ namespace Utils {
void checkDisplayInterval() {
uint32_t lastDisplayTime = millis() - lastScreenOn;
if (!Config.display.alwaysOn) {
if (lastDisplayTime >= Config.display.timeout*1000) {
display_toggle(false);
}
}
}
void checkWiFiInterval() {
uint32_t WiFiCheck = millis() - lastWiFiCheck;
if (WiFi.status() != WL_CONNECTED && WiFiCheck >= 15*60*1000) {
WiFiConnect = true;
}
if (WiFiConnect) {
Serial.println("\nConnecting to WiFi ...");
WIFI_Utils::startWiFi();
lastWiFiCheck = millis();
WiFiConnect = false;
if (!Config.display.alwaysOn && lastDisplayTime >= Config.display.timeout * 1000) {
displayToggle(false);
}
}
void validateFreqs() {
if (Config.loramodule.txFreq != Config.loramodule.rxFreq && abs(Config.loramodule.txFreq - Config.loramodule.rxFreq) < 125000) {
Serial.println("Tx Freq less than 125kHz from Rx Freq ---> NOT VALID");
show_display("Tx Freq is less than ", "125kHz from Rx Freq", "device will autofix", "and then reboot", 1000);
displayShow("Tx Freq is less than ", "125kHz from Rx Freq", "device will autofix", "and then reboot", 1000);
Config.loramodule.txFreq = Config.loramodule.rxFreq; // Inform about that but then change the TX QRG to RX QRG and reset the device
Config.writeFile();
ESP.restart();
}
}
void typeOfPacket(String packet, String packetType) {
String sender;
if (packetType == "LoRa-APRS") {
fifthLine = "LoRa Rx ----> APRS-IS";
sender = packet.substring(0,packet.indexOf(">"));
} else if (packetType == "APRS-LoRa") {
fifthLine = "APRS-IS ----> LoRa Tx";
sender = packet.substring(0,packet.indexOf(">"));
} else if (packetType == "Digi") {
fifthLine = "LoRa Rx ----> LoRa Tx";
sender = packet.substring(0,packet.indexOf(">"));
void typeOfPacket(const String& packet, const uint8_t packetType) {
String sender = packet.substring(0,packet.indexOf(">"));
switch (packetType) {
case 0: // LoRa-APRS
fifthLine = "LoRa Rx ----> APRS-IS";
break;
case 1: // APRS-LoRa
fifthLine = "APRS-IS ----> LoRa Tx";
break;
case 2: // Digi
fifthLine = "LoRa Rx ----> LoRa Tx";
break;
}
for (int i = sender.length(); i < 9; i++) {
sender += " ";
}
if (packet.indexOf("::") >= 10) {
sixthLine = sender + "> MESSAGE";
seventhLine = "RSSI:" + String(rssi) + "dBm SNR: " + String(snr) + "dBm";
} else if (packet.indexOf(":>") >= 10) {
sixthLine = sender + "> NEW STATUS";
seventhLine = "RSSI:" + String(rssi) + "dBm SNR: " + String(snr) + "dBm";
} else if (packet.indexOf(":!") >= 10 || packet.indexOf(":=") >= 10) {
sixthLine = sender + "> GPS BEACON";
GPS_Utils::getDistance(packet);
seventhLine = "RSSI:" + String(rssi) + "dBm";
sixthLine = sender;
String seventhLineHelper = "RSSI:";
seventhLineHelper += String(rssi);
seventhLineHelper += "dBm SNR: ";
seventhLineHelper += String(snr);
seventhLineHelper += "dBm";
int firstColonIndex = packet.indexOf(":");
if (packet[firstColonIndex + 1] == ':') {
sixthLine += "> MESSAGE";
seventhLine = seventhLineHelper;
} else if (packet[firstColonIndex + 1] == '>') {
sixthLine += "> NEW STATUS";
seventhLine = seventhLineHelper;
} else if (packet[firstColonIndex + 1] == '!' || packet[firstColonIndex + 1] == '=' || packet[firstColonIndex + 1] == '@') {
sixthLine += "> GPS BEACON";
if (!Config.syslog.active) {
GPS_Utils::getDistanceAndComment(packet); // to be checked!!!
}
seventhLine = "RSSI:";
seventhLine += String(rssi);
seventhLine += "dBm";
if (rssi <= -100) {
seventhLine += " ";
} else {
@@ -219,32 +375,114 @@ namespace Utils {
if (distance.indexOf(".") == 1) {
seventhLine += " ";
}
seventhLine += "D:" + distance + "km";
seventhLine += "D:";
seventhLine += distance;
seventhLine += "km";
} else if (packet[firstColonIndex + 1] == '`' || packet[firstColonIndex + 1] == '\'') {
sixthLine += "> MIC-E";
seventhLine = seventhLineHelper;
} else if (packet[firstColonIndex + 1] == ';') {
sixthLine += "> OBJECT";
seventhLine = seventhLineHelper;
} else if (packet.indexOf(":T#") >= 10 && packet.indexOf(":=/") == -1) {
sixthLine = sender + "> TELEMETRY";
seventhLine = "RSSI:" + String(rssi) + "dBm SNR: " + String(snr) + "dBm";
} else if (packet.indexOf(":`") >= 10) {
sixthLine = sender + "> MIC-E";
seventhLine = "RSSI:" + String(rssi) + "dBm SNR: " + String(snr) + "dBm";
} else if (packet.indexOf(":;") >= 10) {
sixthLine = sender + "> OBJECT";
seventhLine = "RSSI:" + String(rssi) + "dBm SNR: " + String(snr) + "dBm";
sixthLine += "> TELEMETRY";
seventhLine = seventhLineHelper;
} else {
sixthLine = sender + "> ??????????";
seventhLine = "RSSI:" + String(rssi) + "dBm SNR: " + String(snr) + "dBm";
sixthLine += "> ??????????";
seventhLine = seventhLineHelper;
}
}
void print(String text) {
void print(const String& text) {
if (!Config.tnc.enableSerial) {
Serial.print(text);
}
}
void println(String text) {
void println(const String& text) {
if (!Config.tnc.enableSerial) {
Serial.println(text);
}
}
void checkRebootMode() {
if (Config.rebootMode && Config.rebootModeTime > 0) {
Serial.println("(Reboot Time Set to " + String(Config.rebootModeTime) + " hours)");
}
}
void checkRebootTime() {
if (Config.rebootMode && Config.rebootModeTime > 0) {
if (millis() > Config.rebootModeTime * 60 * 60 * 1000) {
Serial.println("\n*** Automatic Reboot Time Restart! ****\n");
ESP.restart();
}
}
}
void checkSleepByLowBatteryVoltage(uint8_t mode) {
if (shouldSleepLowVoltage) {
if (mode == 0) { // at startup
delay(3000);
}
Serial.println("\n\n*** Sleeping Low Battey Voltage ***\n\n");
esp_sleep_enable_timer_wakeup(30 * 60 * 1000000); // sleep 30 min
if (mode == 1) { // low voltage detected after a while
displayToggle(false);
}
#ifdef VEXT_CTRL
#ifndef HELTEC_WSL_V3
digitalWrite(VEXT_CTRL, LOW);
#endif
#endif
LoRa_Utils::sleepRadio();
transmitFlag = true;
delay(100);
esp_deep_sleep_start();
}
}
bool checkValidCallsign(const String& callsign) {
if (callsign == "WLNK-1") return true;
String cleanCallsign;
if (callsign.indexOf("-") > 0) { // SSID Validation
cleanCallsign = callsign.substring(0, callsign.indexOf("-"));
String ssid = callsign.substring(callsign.indexOf("-") + 1);
if (ssid.indexOf("-") != -1 || ssid.length() > 2) return false;
for (int i = 0; i < ssid.length(); i++) {
if (!isAlphaNumeric(ssid[i])) return false;
}
} else {
cleanCallsign = callsign;
}
if (cleanCallsign.length() < 4 || cleanCallsign.length() > 6) return false;
if (cleanCallsign.length() < 6 && isAlpha(cleanCallsign[0]) && isDigit(cleanCallsign[1]) && isAlpha(cleanCallsign[2]) && isAlpha(cleanCallsign[3]) ) {
cleanCallsign = " " + cleanCallsign; // A0AA --> _A0AA
}
if (!isDigit(cleanCallsign[2]) || !isAlpha(cleanCallsign[3])) { // __0A__ must be validated
if (cleanCallsign[0] != 'R' && !isDigit(cleanCallsign[1]) && !isAlpha(cleanCallsign[2])) return false; // to accepto R0A___
}
bool isValid = false;
if ((isAlphaNumeric(cleanCallsign[0]) || cleanCallsign[0] == ' ') && isAlpha(cleanCallsign[1])) {
isValid = true; // AA0A (+A+A) + _A0AA (+A) + 0A0A (+A+A)
} else if (isAlpha(cleanCallsign[0]) && isDigit(cleanCallsign[1])) {
isValid = true; // A00A (+A+A)
} else if (cleanCallsign[0] == 'R' && cleanCallsign.length() == 6 && isDigit(cleanCallsign[1]) && isAlpha(cleanCallsign[2]) && isAlpha(cleanCallsign[3]) && isAlpha(cleanCallsign[4])) {
isValid = true; // R0AA (+A+A)
}
if (!isValid) return false; // also 00__ avoided
if (cleanCallsign.length() > 4) { // to validate ____AA
for (int i = 5; i <= cleanCallsign.length(); i++) {
if (!isAlpha(cleanCallsign[i - 1])) return false;
}
}
return true;
}
}

View File

@@ -5,25 +5,28 @@
class ReceivedPacket {
public:
long millis;
String rxTime;
String packet;
int RSSI;
float SNR;
float SNR;
};
namespace Utils {
void processStatus();
String getLocalIP();
void setupDisplay();
void activeStations();
void checkBeaconInterval();
void checkDisplayInterval();
void checkWiFiInterval();
void validateFreqs();
void typeOfPacket(String packet, String packetType);
void print(String text);
void println(String text);
void processStatus();
String getLocalIP();
void setupDisplay();
void activeStations();
void checkBeaconInterval();
void checkDisplayInterval();
void validateFreqs();
void typeOfPacket(const String& packet, const uint8_t packetType);
void print(const String& text);
void println(const String& text);
void checkRebootMode();
void checkRebootTime();
void checkSleepByLowBatteryVoltage(uint8_t mode);
bool checkValidCallsign(const String& callsign);
}

View File

@@ -2,10 +2,10 @@
#include "configuration.h"
#include "ota_utils.h"
#include "web_utils.h"
#include "display.h"
#include "utils.h"
extern Configuration Config;
extern uint32_t lastBeaconTx;
extern std::vector<ReceivedPacket> receivedPackets;
@@ -29,6 +29,10 @@ extern const char web_bootstrap_js[] asm("_binary_data_embed_bootstrap_js_gz_sta
extern const char web_bootstrap_js_end[] asm("_binary_data_embed_bootstrap_js_gz_end");
extern const size_t web_bootstrap_js_len = web_bootstrap_js_end - web_bootstrap_js;
// Declare external symbols for the embedded image data
extern const unsigned char favicon_data[] asm("_binary_data_embed_favicon_png_gz_start");
extern const unsigned char favicon_data_end[] asm("_binary_data_embed_favicon_png_gz_end");
extern const size_t favicon_data_len = favicon_data_end - favicon_data;
namespace WEB_Utils {
@@ -45,12 +49,24 @@ namespace WEB_Utils {
}
void handleHome(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", (const uint8_t*)web_index_html, web_index_html_len);
if(Config.webadmin.active && !request->authenticate(Config.webadmin.username.c_str(), Config.webadmin.password.c_str()))
return request->requestAuthentication();
AsyncWebServerResponse *response = request->beginResponse(200, "text/html", (const uint8_t*)web_index_html, web_index_html_len);
response->addHeader("Content-Encoding", "gzip");
request->send(response);
}
void handleFavicon(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response = request->beginResponse(200, "image/x-icon", (const uint8_t*)favicon_data, favicon_data_len);
response->addHeader("Content-Encoding", "gzip");
request->send(response);
}
void handleReadConfiguration(AsyncWebServerRequest *request) {
if(Config.webadmin.active && !request->authenticate(Config.webadmin.username.c_str(), Config.webadmin.password.c_str()))
return request->requestAuthentication();
File file = SPIFFS.open("/igate_conf.json");
String fileContent;
@@ -65,10 +81,10 @@ namespace WEB_Utils {
StaticJsonDocument<1536> data;
for (int i = 0; i < receivedPackets.size(); i++) {
data[i]["millis"] = receivedPackets[i].millis;
data[i]["packet"] = receivedPackets[i].packet;
data[i]["RSSI"] = receivedPackets[i].RSSI;
data[i]["SNR"] = receivedPackets[i].SNR;
data[i]["rxTime"] = receivedPackets[i].rxTime;
data[i]["packet"] = receivedPackets[i].packet;
data[i]["RSSI"] = receivedPackets[i].RSSI;
data[i]["SNR"] = receivedPackets[i].SNR;
}
String buffer;
@@ -89,106 +105,120 @@ namespace WEB_Utils {
WiFi_AP wifiap;
wifiap.ssid = request->getParam("wifi.AP." + String(i) + ".ssid", true)->value();
wifiap.password = request->getParam("wifi.AP." + String(i) + ".password", true)->value();
// wifiap.latitude = request->getParam("wifi.AP." + String(i) + ".latitude", true)->value().toDouble();
// wifiap.longitude = request->getParam("wifi.AP." + String(i) + ".longitude", true)->value().toDouble();
Config.wifiAPs.push_back(wifiap);
}
Config.callsign = request->getParam("callsign", true)->value();
// Config.iGateComment = request->getParam("iGateComment", true)->value();
Config.callsign = request->getParam("callsign", true)->value();
Config.wifiAutoAP.password = request->getParam("wifi.autoAP.password", true)->value();
Config.wifiAutoAP.timeout = request->getParam("wifi.autoAP.timeout", true)->value().toInt();
Config.wifiAutoAP.password = request->getParam("wifi.autoAP.password", true)->value();
Config.wifiAutoAP.powerOff = request->getParam("wifi.autoAP.powerOff", true)->value().toInt();
Config.digi.mode = request->getParam("digi.mode", true)->value().toInt();
// Config.digi.comment = request->getParam("digi.comment", true)->value();
// Config.digi.latitude = request->getParam("digi.latitude", true)->value().toDouble();
// Config.digi.longitude = request->getParam("digi.longitude", true)->value().toDouble();
Config.aprs_is.active = request->hasParam("aprs_is.active", true);
Config.aprs_is.passcode = request->getParam("aprs_is.passcode", true)->value();
Config.aprs_is.server = request->getParam("aprs_is.server", true)->value();
Config.aprs_is.port = request->getParam("aprs_is.port", true)->value().toInt();
Config.aprs_is.filter = request->getParam("aprs_is.filter", true)->value();
Config.aprs_is.messagesToRF = request->hasParam("aprs_is.messagesToRF", true);
Config.aprs_is.objectsToRF = request->hasParam("aprs_is.objectsToRF", true);
Config.tnc.enableServer = request->hasParam("tnc.enableServer", true);
Config.tnc.enableSerial = request->hasParam("tnc.enableSerial", true);
Config.tnc.acceptOwn = request->hasParam("tnc.acceptOwn", true);
Config.aprs_is.active = request->hasParam("aprs_is.active", true);
Config.aprs_is.passcode = request->getParam("aprs_is.passcode", true)->value();
Config.aprs_is.server = request->getParam("aprs_is.server", true)->value();
Config.aprs_is.port = request->getParam("aprs_is.port", true)->value().toInt();
// Config.aprs_is.reportingDistance = request->getParam("aprs_is.reportingDistance", true)->value().toInt();
Config.aprs_is.filter = request->getParam("aprs_is.filter", true)->value();
Config.aprs_is.toRF = request->hasParam("aprs_is.toRF", true);
Config.beacon.interval = request->getParam("beacon.interval", true)->value().toInt();
Config.beacon.sendViaAPRSIS = request->hasParam("beacon.sendViaAPRSIS", true);
Config.beacon.sendViaRF = request->hasParam("beacon.sendViaRF", true);
Config.beacon.latitude = request->getParam("beacon.latitude", true)->value().toDouble();
Config.beacon.longitude = request->getParam("beacon.longitude", true)->value().toDouble();
Config.beacon.comment = request->getParam("beacon.comment", true)->value();
Config.beacon.overlay = request->getParam("beacon.overlay", true)->value();
Config.beacon.symbol = request->getParam("beacon.symbol", true)->value();
Config.beacon.path = request->getParam("beacon.path", true)->value();
Config.beacon.gpsActive = request->hasParam("beacon.gpsActive", true);
Config.beacon.gpsAmbiguity = request->hasParam("beacon.gpsAmbiguity", true);
// Config.loramodule.iGateFreq = request->getParam("lora.iGateFreq", true)->value().toInt();
// if (request->hasParam("lora.digirepeaterTxFreq", true)) {
// Config.loramodule.digirepeaterTxFreq = request->getParam("lora.digirepeaterTxFreq", true)->value().toInt();
// }
// if (request->hasParam("lora.digirepeaterRxFreq", true)) {
// Config.loramodule.digirepeaterRxFreq = request->getParam("lora.digirepeaterRxFreq", true)->value().toInt();
// }
Config.loramodule.txFreq = request->getParam("lora.txFreq", true)->value().toInt();
Config.loramodule.rxFreq = request->getParam("lora.rxFreq", true)->value().toInt();
Config.loramodule.spreadingFactor = request->getParam("lora.spreadingFactor", true)->value().toInt();
Config.loramodule.signalBandwidth = request->getParam("lora.signalBandwidth", true)->value().toInt();
Config.loramodule.codingRate4 = request->getParam("lora.codingRate4", true)->value().toInt();
Config.loramodule.power = request->getParam("lora.power", true)->value().toInt();
Config.loramodule.txActive = request->hasParam("lora.txActive", true);
Config.loramodule.rxActive = request->hasParam("lora.rxActive", true);
Config.digi.mode = request->getParam("digi.mode", true)->value().toInt();
Config.digi.ecoMode = request->hasParam("digi.ecoMode", true);
Config.display.alwaysOn = request->hasParam("display.alwaysOn", true);
Config.loramodule.txFreq = request->getParam("lora.txFreq", true)->value().toInt();
Config.loramodule.rxFreq = request->getParam("lora.rxFreq", true)->value().toInt();
Config.loramodule.spreadingFactor = request->getParam("lora.spreadingFactor", true)->value().toInt();
Config.loramodule.signalBandwidth = request->getParam("lora.signalBandwidth", true)->value().toInt();
Config.loramodule.codingRate4 = request->getParam("lora.codingRate4", true)->value().toInt();
Config.loramodule.power = request->getParam("lora.power", true)->value().toInt();
Config.loramodule.txActive = request->hasParam("lora.txActive", true);
Config.loramodule.rxActive = request->hasParam("lora.rxActive", true);
Config.display.alwaysOn = request->hasParam("display.alwaysOn", true);
if (!Config.display.alwaysOn) {
Config.display.timeout = request->getParam("display.timeout", true)->value().toInt();
Config.display.timeout = request->getParam("display.timeout", true)->value().toInt();
}
Config.display.turn180 = request->hasParam("display.turn180", true);
Config.display.turn180 = request->hasParam("display.turn180", true);
Config.syslog.active = request->hasParam("syslog.active", true);
Config.battery.sendInternalVoltage = request->hasParam("battery.sendInternalVoltage", true);
Config.battery.monitorInternalVoltage = request->hasParam("battery.monitorInternalVoltage", true);
Config.battery.internalSleepVoltage = request->getParam("battery.internalSleepVoltage", true)->value().toFloat();
if (Config.syslog.active) {
Config.syslog.server = request->getParam("syslog.server", true)->value();
Config.syslog.port = request->getParam("syslog.port", true)->value().toInt();
Config.battery.sendExternalVoltage = request->hasParam("battery.sendExternalVoltage", true);
if (Config.battery.sendExternalVoltage) {
Config.battery.externalVoltagePin = request->getParam("battery.externalVoltagePin", true)->value().toInt();
Config.battery.voltageDividerR1 = request->getParam("battery.voltageDividerR1", true)->value().toFloat();
Config.battery.voltageDividerR2 = request->getParam("battery.voltageDividerR2", true)->value().toFloat();
}
Config.battery.monitorExternalVoltage = request->hasParam("battery.monitorExternalVoltage", true);
Config.battery.externalSleepVoltage = request->getParam("battery.externalSleepVoltage", true)->value().toFloat();
Config.bme.active = request->hasParam("bme.active", true);
Config.ota.username = request->getParam("ota.username", true)->value();
Config.ota.password = request->getParam("ota.password", true)->value();
Config.beacon.interval = request->getParam("beacon.interval", true)->value().toInt();
Config.beacon.sendViaAPRSIS = request->hasParam("beacon.sendViaAPRSIS", true);
Config.beacon.sendViaRF = request->hasParam("beacon.sendViaRF", true);
Config.beacon.latitude = request->getParam("beacon.latitude", true)->value().toDouble();
Config.beacon.longitude = request->getParam("beacon.longitude", true)->value().toDouble();
Config.beacon.comment = request->getParam("beacon.comment", true)->value();
Config.beacon.overlay = request->getParam("beacon.overlay", true)->value();
Config.beacon.symbol = request->getParam("beacon.symbol", true)->value();
Config.beacon.path = request->getParam("beacon.path", true)->value();
// Config.beaconInterval = request->getParam("other.beaconInterval", true)->value().toInt();
// Config.igateSendsLoRaBeacons = request->hasParam("other.igateSendsLoRaBeacons", true);
// Config.igateRepeatsLoRaPackets = request->hasParam("other.igateRepeatsLoRaPackets", true);
Config.rememberStationTime = request->getParam("other.rememberStationTime", true)->value().toInt();
Config.sendBatteryVoltage = request->hasParam("other.sendBatteryVoltage", true);
Config.externalVoltageMeasurement = request->hasParam("other.externalVoltageMeasurement", true);
if (Config.externalVoltageMeasurement) {
Config.externalVoltagePin = request->getParam("other.externalVoltagePin", true)->value().toInt();
}
Config.lowPowerMode = request->hasParam("other.lowPowerMode", true);
Config.lowVoltageCutOff = request->getParam("other.lowVoltageCutOff", true)->value().toDouble();
if (Config.bme.active) {
Config.battery.sendVoltageAsTelemetry = request->hasParam("battery.sendVoltageAsTelemetry", true);
Config.wxsensor.active = request->hasParam("wxsensor.active", true);
Config.wxsensor.heightCorrection = request->getParam("wxsensor.heightCorrection", true)->value().toInt();
Config.wxsensor.temperatureCorrection = request->getParam("wxsensor.temperatureCorrection", true)->value().toFloat();
if (Config.wxsensor.active) {
Config.beacon.symbol = "_";
}
Config.syslog.active = request->hasParam("syslog.active", true);
if (Config.syslog.active) {
Config.syslog.server = request->getParam("syslog.server", true)->value();
Config.syslog.port = request->getParam("syslog.port", true)->value().toInt();
}
Config.tnc.enableServer = request->hasParam("tnc.enableServer", true);
Config.tnc.enableSerial = request->hasParam("tnc.enableSerial", true);
Config.tnc.acceptOwn = request->hasParam("tnc.acceptOwn", true);
Config.rebootMode = request->hasParam("other.rebootMode", true);
Config.rebootModeTime = request->getParam("other.rebootModeTime", true)->value().toInt();
Config.ota.username = request->getParam("ota.username", true)->value();
Config.ota.password = request->getParam("ota.password", true)->value();
Config.rememberStationTime = request->getParam("other.rememberStationTime", true)->value().toInt();
Config.backupDigiMode = request->hasParam("other.backupDigiMode", true);
Config.lowPowerMode = request->hasParam("other.lowPowerMode", true);
Config.lowVoltageCutOff = request->getParam("other.lowVoltageCutOff", true)->value().toDouble();
Config.personalNote = request->getParam("personalNote", true)->value();
Config.webadmin.active = request->hasParam("webadmin.active", true);
if (Config.webadmin.active) {
Config.webadmin.username = request->getParam("webadmin.username", true)->value();
Config.webadmin.password = request->getParam("webadmin.password", true)->value();
}
Config.ntp.gmtCorrection = request->getParam("ntp.gmtCorrection", true)->value().toInt();
Config.writeFile();
AsyncWebServerResponse *response = request->beginResponse(302, "text/html", "");
AsyncWebServerResponse *response = request->beginResponse(302, "text/html", "");
response->addHeader("Location", "/");
request->send(response);
displayToggle(false);
ESP.restart();
}
@@ -200,6 +230,7 @@ namespace WEB_Utils {
request->send(200, "text/plain", "Beacon will be sent in a while");
} else if (type == "reboot") {
displayToggle(false);
ESP.restart();
} else {
request->send(404, "text/plain", "Not Found");
@@ -207,48 +238,51 @@ namespace WEB_Utils {
}
void handleStyle(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/css", (const uint8_t*)web_style_css, web_style_css_len);
AsyncWebServerResponse *response = request->beginResponse(200, "text/css", (const uint8_t*)web_style_css, web_style_css_len);
response->addHeader("Content-Encoding", "gzip");
request->send(response);
}
void handleScript(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/javascript", (const uint8_t*)web_script_js, web_script_js_len);
AsyncWebServerResponse *response = request->beginResponse(200, "text/javascript", (const uint8_t*)web_script_js, web_script_js_len);
response->addHeader("Content-Encoding", "gzip");
request->send(response);
}
void handleBootstrapStyle(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/css", (const uint8_t*)web_bootstrap_css, web_bootstrap_css_len);
AsyncWebServerResponse *response = request->beginResponse(200, "text/css", (const uint8_t*)web_bootstrap_css, web_bootstrap_css_len);
response->addHeader("Content-Encoding", "gzip");
response->addHeader("Cache-Control", "max-age=3600");
request->send(response);
}
void handleBootstrapScript(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/javascript", (const uint8_t*)web_bootstrap_js, web_bootstrap_js_len);
AsyncWebServerResponse *response = request->beginResponse(200, "text/javascript", (const uint8_t*)web_bootstrap_js, web_bootstrap_js_len);
response->addHeader("Content-Encoding", "gzip");
response->addHeader("Cache-Control", "max-age=3600");
request->send(response);
}
void setup() {
server.on("/", HTTP_GET, handleHome);
server.on("/status", HTTP_GET, handleStatus);
server.on("/received-packets.json", HTTP_GET, handleReceivedPackets);
server.on("/configuration.json", HTTP_GET, handleReadConfiguration);
server.on("/configuration.json", HTTP_POST, handleWriteConfiguration);
server.on("/action", HTTP_POST, handleAction);
server.on("/style.css", HTTP_GET, handleStyle);
server.on("/script.js", HTTP_GET, handleScript);
server.on("/bootstrap.css", HTTP_GET, handleBootstrapStyle);
server.on("/bootstrap.js", HTTP_GET, handleBootstrapScript);
if (!Config.digi.ecoMode) {
server.on("/", HTTP_GET, handleHome);
server.on("/status", HTTP_GET, handleStatus);
server.on("/received-packets.json", HTTP_GET, handleReceivedPackets);
server.on("/configuration.json", HTTP_GET, handleReadConfiguration);
server.on("/configuration.json", HTTP_POST, handleWriteConfiguration);
server.on("/action", HTTP_POST, handleAction);
server.on("/style.css", HTTP_GET, handleStyle);
server.on("/script.js", HTTP_GET, handleScript);
server.on("/bootstrap.css", HTTP_GET, handleBootstrapStyle);
server.on("/bootstrap.js", HTTP_GET, handleBootstrapScript);
server.on("/favicon.png", HTTP_GET, handleFavicon);
OTA_Utils::setup(&server); // Include OTA Updater for WebServer
OTA_Utils::setup(&server); // Include OTA Updater for WebServer
server.onNotFound(handleNotFound);
server.onNotFound(handleNotFound);
server.begin();
server.begin();
}
}
}

View File

@@ -1,29 +1,58 @@
#include <WiFi.h>
#include "configuration.h"
#include "pins_config.h"
#include "boards_pinout.h"
#include "wifi_utils.h"
#include "display.h"
#include "utils.h"
extern Configuration Config;
extern WiFi_AP *currentWiFi;
extern uint8_t myWiFiAPIndex;
extern int myWiFiAPSize;
extern uint32_t previousWiFiMillis;
extern bool WiFiConnected;
extern long WiFiAutoAPTime;
extern bool WiFiAutoAPStarted;
extern Configuration Config;
extern uint8_t myWiFiAPIndex;
extern int myWiFiAPSize;
extern WiFi_AP *currentWiFi;
extern bool backUpDigiMode;
bool WiFiConnected = false;
uint32_t WiFiAutoAPTime = millis();
bool WiFiAutoAPStarted = false;
uint32_t previousWiFiMillis = 0;
uint8_t wifiCounter = 0;
uint32_t lastBackupDigiTime = millis();
namespace WIFI_Utils {
void checkWiFi() {
if ((WiFi.status() != WL_CONNECTED) && ((millis() - previousWiFiMillis) >= 30*1000) && !WiFiAutoAPStarted) {
Serial.print(millis());
Serial.println("Reconnecting to WiFi...");
WiFi.disconnect();
WiFi.reconnect();
previousWiFiMillis = millis();
if (!Config.digi.ecoMode) {
if (backUpDigiMode) {
uint32_t WiFiCheck = millis() - lastBackupDigiTime;
if (WiFi.status() != WL_CONNECTED && WiFiCheck >= 15 * 60 * 1000) {
Serial.println("*** Stopping BackUp Digi Mode ***");
backUpDigiMode = false;
wifiCounter = 0;
} else if (WiFi.status() == WL_CONNECTED) {
Serial.println("*** WiFi Reconnect Success (Stopping Backup Digi Mode) ***");
backUpDigiMode = false;
wifiCounter = 0;
}
}
if (!backUpDigiMode && (WiFi.status() != WL_CONNECTED) && ((millis() - previousWiFiMillis) >= 30 * 1000) && !WiFiAutoAPStarted) {
Serial.print(millis());
Serial.println("Reconnecting to WiFi...");
WiFi.disconnect();
WIFI_Utils::startWiFi();//WiFi.reconnect();
previousWiFiMillis = millis();
if (Config.backupDigiMode) {
wifiCounter++;
}
if (wifiCounter >= 2) {
Serial.println("*** Starting BackUp Digi Mode ***");
backUpDigiMode = true;
lastBackupDigiTime = millis();
}
}
}
}
@@ -31,7 +60,7 @@ namespace WIFI_Utils {
WiFi.mode(WIFI_MODE_NULL);
WiFi.mode(WIFI_AP);
WiFi.softAP(Config.callsign + " AP", Config.wifiAutoAP.password);
WiFi.softAP(Config.callsign + "-AP", Config.wifiAutoAP.password);
WiFiAutoAPTime = millis();
WiFiAutoAPStarted = true;
@@ -43,22 +72,24 @@ namespace WIFI_Utils {
startAP = true;
} else {
uint8_t wifiCounter = 0;
String hostName = "iGATE-" + Config.callsign;
WiFi.setHostname(hostName.c_str());
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(500);
unsigned long start = millis();
show_display("", "", "Connecting to Wifi:", "", currentWiFi->ssid + " ...", 0);
displayShow("", "Connecting to WiFi:", "", currentWiFi->ssid + " ...", 0);
Serial.print("\nConnecting to WiFi '"); Serial.print(currentWiFi->ssid); Serial.println("' ...");
WiFi.begin(currentWiFi->ssid.c_str(), currentWiFi->password.c_str());
while (WiFi.status() != WL_CONNECTED && wifiCounter<myWiFiAPSize) {
delay(500);
#ifdef HAS_INTERNAL_LED
digitalWrite(internalLedPin,HIGH);
#ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN,HIGH);
#endif
Serial.print('.');
delay(500);
#ifdef HAS_INTERNAL_LED
digitalWrite(internalLedPin,LOW);
#ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN,LOW);
#endif
if ((millis() - start) > 10000){
delay(1000);
@@ -72,42 +103,44 @@ namespace WIFI_Utils {
currentWiFi = &Config.wifiAPs[myWiFiAPIndex];
start = millis();
Serial.print("\nConnecting to WiFi '"); Serial.print(currentWiFi->ssid); Serial.println("' ...");
show_display("", "", "Connecting to Wifi:", "", currentWiFi->ssid + " ...", 0);
displayShow("", "Connecting to WiFi:", "", currentWiFi->ssid + " ...", 0);
WiFi.disconnect();
WiFi.begin(currentWiFi->ssid.c_str(), currentWiFi->password.c_str());
}
}
}
#ifdef HAS_INTERNAL_LED
digitalWrite(internalLedPin,LOW);
#ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN,LOW);
#endif
if (WiFi.status() == WL_CONNECTED) {
Serial.print("Connected as ");
Serial.println(WiFi.localIP());
show_display("", "", " Connected!!", "" , " loading ...", 1000);
Serial.print(WiFi.localIP());
Serial.print(" / MAC Address: ");
Serial.println(WiFi.macAddress());
displayShow("", " Connected!!", "" , " loading ...", 1000);
} else if (WiFi.status() != WL_CONNECTED) {
startAP = true;
Serial.println("\nNot connected to WiFi! Starting Auto AP");
show_display("", "", " WiFi Not Connected!", "" , " loading ...", 1000);
displayShow("", " WiFi Not Connected!", "" , " loading ...", 1000);
}
WiFiConnected = !startAP;
if (startAP) {
Serial.println("\nNot connected to WiFi! Starting Auto AP");
show_display("", "", " Starting Auto AP", " Please connect to it " , " loading ...", 1000);
displayShow("", " Starting Auto AP", " Please connect to it " , " loading ...", 1000);
startAutoAP();
}
}
void checkIfAutoAPShouldPowerOff() {
if (WiFiAutoAPStarted && Config.wifiAutoAP.powerOff > 0) {
void checkAutoAPTimeout() {
if (WiFiAutoAPStarted && Config.wifiAutoAP.timeout > 0) {
if (WiFi.softAPgetStationNum() > 0) {
WiFiAutoAPTime = 0;
} else {
if (WiFiAutoAPTime == 0) {
WiFiAutoAPTime = millis();
} else if ((millis() - WiFiAutoAPTime) > Config.wifiAutoAP.powerOff * 60 * 1000) {
} else if ((millis() - WiFiAutoAPTime) > Config.wifiAutoAP.timeout * 60 * 1000) {
Serial.println("Stopping auto AP");
WiFiAutoAPStarted = false;
@@ -120,7 +153,7 @@ namespace WIFI_Utils {
}
void setup() {
startWiFi();
if (!Config.digi.ecoMode) startWiFi();
btStop();
}

View File

@@ -9,7 +9,7 @@ namespace WIFI_Utils {
void checkWiFi();
void startAutoAP();
void startWiFi();
void checkIfAutoAPShouldPowerOff();
void checkAutoAPTimeout();
void setup();
}

261
src/wx_utils.cpp Normal file
View File

@@ -0,0 +1,261 @@
#include "configuration.h"
#include "wx_utils.h"
#include "display.h"
#define SEALEVELPRESSURE_HPA (1013.25)
#define CORRECTION_FACTOR (8.2296) // for meters
extern Configuration Config;
extern String fifthLine;
int wxModuleType = 0;
uint8_t wxModuleAddress = 0x00;
float newHum, newTemp, newPress, newGas;
Adafruit_BME280 bme280;
#ifdef HELTEC_V3
Adafruit_BMP280 bmp280(&Wire1);
Adafruit_Si7021 sensor = Adafruit_Si7021();
#else
Adafruit_BMP280 bmp280;
Adafruit_BME680 bme680;
Adafruit_Si7021 sensor = Adafruit_Si7021();
#endif
namespace WX_Utils {
void getWxModuleAddres() {
uint8_t err, addr;
for(addr = 1; addr < 0x7F; addr++) {
#if defined(HELTEC_V3) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY)
Wire1.beginTransmission(addr);
err = Wire1.endTransmission();
#else
Wire.beginTransmission(addr);
err = Wire.endTransmission();
#endif
if (err == 0) {
//Serial.println(addr); this shows any connected board to I2C
if (addr == 0x76 || addr == 0x77) { // BME/BMP
wxModuleAddress = addr;
return;
} else if (addr == 0x40) { // Si7011
wxModuleAddress = addr;
return;
}
}
}
}
void setup() {
if (Config.wxsensor.active) {
getWxModuleAddres();
if (wxModuleAddress != 0x00) {
bool wxModuleFound = false;
if (wxModuleAddress == 0x76 || wxModuleAddress == 0x77) {
#if defined(HELTEC_V3) || defined(HELTEC_WSL_V3) || defined(HELTEC_WSL_V3_DISPLAY)
if (bme280.begin(wxModuleAddress, &Wire1)) {
Serial.println("BME280 sensor found");
wxModuleType = 1;
wxModuleFound = true;
}
#else
if (bme280.begin(wxModuleAddress)) {
Serial.println("BME280 sensor found");
wxModuleType = 1;
wxModuleFound = true;
}
if (!wxModuleFound) {
if (bme680.begin(wxModuleAddress)) {
Serial.println("BME680 sensor found");
wxModuleType = 3;
wxModuleFound = true;
}
}
#endif
if (!wxModuleFound) {
if (bmp280.begin(wxModuleAddress)) {
Serial.println("BMP280 sensor found");
wxModuleType = 2;
wxModuleFound = true;
}
}
} else if (wxModuleAddress == 0x40) {
if(sensor.begin()) {
Serial.println("Si7021 sensor found");
wxModuleType = 4;
wxModuleFound = true;
}
}
if (!wxModuleFound) {
displayShow("ERROR", "", "BME/BMP/Si7021 sensor active", "but no sensor found...", 2000);
Serial.println("BME/BMP/Si7021 sensor Active in config but not found! Check Wiring");
} else {
switch (wxModuleType) {
case 1:
bme280.setSampling(Adafruit_BME280::MODE_FORCED,
Adafruit_BME280::SAMPLING_X1,
Adafruit_BME280::SAMPLING_X1,
Adafruit_BME280::SAMPLING_X1,
Adafruit_BME280::FILTER_OFF
);
Serial.println("BME280 Module init done!");
break;
case 2:
bmp280.setSampling(Adafruit_BMP280::MODE_FORCED,
Adafruit_BMP280::SAMPLING_X1,
Adafruit_BMP280::SAMPLING_X1,
Adafruit_BMP280::FILTER_OFF
);
Serial.println("BMP280 Module init done!");
break;
case 3:
#ifndef HELTEC_V3
bme680.setTemperatureOversampling(BME680_OS_1X);
bme680.setHumidityOversampling(BME680_OS_1X);
bme680.setPressureOversampling(BME680_OS_1X);
bme680.setIIRFilterSize(BME680_FILTER_SIZE_0);
Serial.println("BMP680 Module init done!");
#endif
break;
}
}
}
}
}
String generateTempString(const float sensorTemp) {
String strTemp = String((int)sensorTemp);
switch (strTemp.length()) {
case 1:
return "00" + strTemp;
case 2:
return "0" + strTemp;
case 3:
return strTemp;
default:
return "-999";
}
}
String generateHumString(const float sensorHum) {
String strHum = String((int)sensorHum);
switch (strHum.length()) {
case 1:
return "0" + strHum;
case 2:
return strHum;
case 3:
if ((int)sensorHum == 100) {
return "00";
} else {
return "-99";
}
default:
return "-99";
}
}
String generatePresString(const float sensorPres) {
String strPress = String((int)sensorPres);
String decPress = String(int((sensorPres - int(sensorPres)) * 10));
switch (strPress.length()) {
case 1:
return "000" + strPress + decPress;
case 2:
return "00" + strPress + decPress;
case 3:
return "0" + strPress + decPress;
case 4:
return strPress + decPress;
case 5:
return strPress;
default:
return "-99999";
}
}
String readDataSensor() {
switch (wxModuleType) {
case 1: // BME280
bme280.takeForcedMeasurement();
newTemp = bme280.readTemperature();
newPress = (bme280.readPressure() / 100.0F);
newHum = bme280.readHumidity();
break;
case 2: // BMP280
bmp280.takeForcedMeasurement();
newTemp = bmp280.readTemperature();
newPress = (bmp280.readPressure() / 100.0F);
newHum = 0;
break;
case 3: // BME680
#ifndef HELTEC_V3
bme680.performReading();
delay(50);
if (bme680.endReading()) {
newTemp = bme680.temperature;
newPress = (bme680.pressure / 100.0F);
newHum = bme680.humidity;
newGas = bme680.gas_resistance / 1000.0; // in Kilo ohms
}
#endif
break;
case 4: // Si7021
newTemp = sensor.readTemperature();
newPress = 0;
newHum = sensor.readHumidity();
break;
}
if (isnan(newTemp) || isnan(newHum) || isnan(newPress)) {
Serial.println("BME/BMP/Si7021 Module data failed");
fifthLine = "";
return ".../...g...t...";
} else {
String tempStr = generateTempString(((newTemp + Config.wxsensor.temperatureCorrection) * 1.8) + 32);
String humStr;
if (wxModuleType == 1 || wxModuleType == 3 || wxModuleType == 4) {
humStr = generateHumString(newHum);
} else if (wxModuleType == 2) {
humStr = "..";
}
String presStr;
if (wxModuleAddress == 4) {
presStr = ".....";
} else {
presStr = generatePresString(newPress + (Config.wxsensor.heightCorrection/CORRECTION_FACTOR));
}
fifthLine = "BME-> ";
fifthLine += String(int(newTemp + Config.wxsensor.temperatureCorrection));
fifthLine += "C ";
fifthLine += humStr;
fifthLine += "% ";
fifthLine += presStr.substring(0,4);
fifthLine += "hPa";
String wxPayload = ".../...g...t";
wxPayload += tempStr;
wxPayload += "h";
wxPayload += humStr;
wxPayload += "b";
wxPayload += presStr;
if (wxModuleType == 3) {
wxPayload += "Gas: ";
wxPayload += String(newGas);
wxPayload += "Kohms";
}
return wxPayload;
}
}
}

23
src/wx_utils.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef WX_UTILS_H_
#define WX_UTILS_H_
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_BME680.h>
#include "Adafruit_Si7021.h"
#include <Arduino.h>
namespace WX_Utils {
void getWxModuleAddres();
void setup();
String generateTempString(const float sensorTemp);
String generateHumString(const float sensorHum);
String generatePresString(const float sensorPres);
String readDataSensor();
}
#endif

View File

@@ -9,8 +9,21 @@ files = [
'data_embed/style.css',
'data_embed/bootstrap.js',
'data_embed/bootstrap.css',
'data_embed/favicon.png',
]
string_to_find_str = "String"
string_to_find_ver = "versionDate"
with open('src/LoRa_APRS_iGate.cpp', encoding='utf-8') as cpp_file:
for line in cpp_file:
if string_to_find_str in line and string_to_find_ver in line:
start = line.find('"') + 1
end = line.find('"', start)
if start > 0 and end > start:
versionDate = line[start:end]
break
for src in files:
out = src + ".gz"
@@ -19,7 +32,7 @@ for src in files:
content = f.read()
if src == 'data_embed/index.html':
env_vars = env["BOARD"] + "<br>" + ','.join(env["BUILD_FLAGS"]).replace('-Werror -Wall,', '').replace(',-DELEGANTOTA_USE_ASYNC_WEBSERVER=1', '')
env_vars = env["BOARD"] + "<br>" + ','.join(env["BUILD_FLAGS"]).replace('-Werror -Wall,', '').replace(',-DELEGANTOTA_USE_ASYNC_WEBSERVER=1', '') + "<br>" + "Version date: " + versionDate
current_date = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S') + " UTC"
build_info = f'{env_vars}<br>Build date: {current_date}'.encode()