Compare commits

...

273 Commits

Author SHA1 Message Date
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
Ricardo Guzman (Richonguzman) b00b29a5da Merge pull request #76 from SQ2CPA/main
Merged bins for web flash
2024-04-16 15:25:52 -04:00
SQ2CPA a64899d44c chore: workflow for merged bins 2024-04-16 21:16:28 +02:00
richonguzman af9f3fd09b json memory fix 2024-04-16 15:01:53 -04:00
richonguzman 0fb2c95338 just small typo 2024-04-15 11:00:35 -04:00
richonguzman 3885a43324 update 2024-04-13 13:06:13 -04:00
Ricardo Guzman (Richonguzman) 0695e6643e Merge pull request #74 from SQ2CPA/main
Received packets list
2024-04-13 12:48:54 -04:00
SQ2CPA 71473164f4 feat: received packets list 2024-04-13 18:20:10 +02:00
richonguzman 8e505df768 duplicated comment fix 2024-04-11 11:07:28 -04:00
richonguzman 81295bc3e2 removing LoRa dot h library 2024-04-10 09:13:56 -04:00
richonguzman 16f5338953 testing syslog 2024-04-09 12:51:51 -04:00
richonguzman 0b22d27b40 status mod for TCPIP and RF 2024-04-09 12:20:31 -04:00
richonguzman aea0aa21af rx Fix 2024-04-09 11:20:09 -04:00
richonguzman a6ce44f8d3 new Compressed GPS data instead of classic NMEA 2024-04-09 11:08:23 -04:00
richonguzman 3ce5d08c44 typeOfPacket fix 2024-04-09 10:01:44 -04:00
richonguzman 51b59ab555 crc mismatch fix 2024-04-07 08:16:28 -04:00
richonguzman b9024d34cb RFONLY coma fix 2024-04-05 12:10:12 -03:00
richonguzman e4bc8eecbe RFONLY update 2024-04-04 15:54:49 -03:00
Ricardo Guzman (Richonguzman) c10645c2c0 Merge pull request #68 from SQ2CPA/main
Migrate from LoRa.h into RadioLib and more
2024-04-04 14:09:13 -03:00
SQ2CPA 0d64c65aa5 feat: add build env and date to web ui footer 2024-04-04 18:28:38 +02:00
SQ2CPA d16e407269 improvement: use LoRa WX icon when using BME 2024-04-04 17:58:07 +02:00
SQ2CPA c8cde0a404 fix: use path from config everywhere 2024-04-04 17:56:37 +02:00
SQ2CPA c1cc7c9ab0 fix: use battery settings for comment in low power mode 2024-04-04 17:55:20 +02:00
SQ2CPA 4d23681935 improvement: migrate from lora.h to radiolib 2024-04-04 17:42:36 +02:00
richonguzman 1bcb119cad 1 2024-03-29 10:35:49 -03:00
richonguzman 43c0021ba7 supported boards text add and link 2024-03-29 10:35:09 -03:00
richonguzman daa245ff7c supported boards add 2024-03-29 10:33:45 -03:00
richonguzman e52ac86e3e sender vs Sender fix 2024-03-28 16:28:14 -03:00
Ricardo Guzman (Richonguzman) c1bb6e39ef Merge pull request #64 from SQ2CPA/main
Experimental Low power mode and Low voltage cut off
2024-03-28 16:20:08 -03:00
SQ2CPA 0e94444198 fix: rename heltec wireless lite to ht-ct62 2024-03-28 18:33:11 +01:00
SQ2CPA 968d9188be improvement: low voltage cut off as web ui option 2024-03-28 18:28:31 +01:00
SQ2CPA db21a08904 chore: ota update binary in installer zip 2024-03-28 18:01:42 +01:00
SQ2CPA 14999d1b66 feat: low power mode 2024-03-28 18:01:42 +01:00
SQ2CPA a8a7c3e3a3 fix: missing sender variable 2024-03-28 18:01:42 +01:00
richonguzman ca3c1eaf9f uint8_t update 2024-03-28 10:22:54 -03:00
richonguzman dec018f232 new picture 2024-03-28 00:11:36 -03:00
richonguzman f49472efd1 new igate picture 2024-03-28 00:05:46 -03:00
richonguzman df3b15ff35 just small code cleaning 2024-03-27 15:28:27 -03:00
richonguzman d004efb193 version Update 2024-03-27 13:12:47 -03:00
richonguzman d98334a489 preparing for Notification LowVoltBattery 2024-03-27 11:42:04 -03:00
richonguzman 1365ae67a1 update in APRS listening 2024-03-27 11:26:02 -03:00
richonguzman 110c6d600b esp32 super mini killed 2024-03-26 17:43:50 -03:00
richonguzman 9557df983b test1 2024-03-26 16:43:17 -03:00
richonguzman 0e9dba76a8 low_voltage_cutoff settings 2024-03-24 10:01:54 -03:00
richonguzman caa48694b4 new date 2024-03-23 23:48:32 -03:00
Ricardo Guzman (Richonguzman) 0ac2705609 fix lora problem 2024-03-23 23:36:18 -03:00
Ricardo Guzman (Richonguzman) ed9d80fd78 Add files via upload 2024-03-23 09:48:12 -03:00
Ricardo Guzman (Richonguzman) cb7e9f3235 Merge pull request #57 from SQ2CPA/main
Hotfix TNC config only if available
2024-03-22 16:45:54 -03:00
SQ2CPA 8fdab82684 fix: tnc config only if available 2024-03-22 20:42:55 +01:00
Ricardo Guzman (Richonguzman) 0d1162786c Merge pull request #56 from SQ2CPA/main
TNC and few more changes and fixes
2024-03-22 15:28:14 -03:00
SQ2CPA 0b40cb0889 fix: path is not required 2024-03-22 19:07:35 +01:00
SQ2CPA e33b639f12 fix: saving empty APs 2024-03-22 19:07:35 +01:00
SQ2CPA 15be5fc611 feat: battery voltage cutoff monitor 2024-03-22 19:07:35 +01:00
SQ2CPA a44c6ca96c chore: commit test build workflow 2024-03-22 19:07:35 +01:00
SQ2CPA 7897e9a5be feat: heltec wireless stick lite board 2024-03-22 19:07:35 +01:00
SQ2CPA a33875a608 fix: send battery voltage as separate 2024-03-22 19:07:35 +01:00
SQ2CPA 5337cb2d46 feat: send beacon and reboot buttons 2024-03-22 19:07:35 +01:00
SQ2CPA 67e1c528f3 refactor: tnc handle input data 2024-03-22 19:07:35 +01:00
SQ2CPA 9f617c406e feat: new navbar 2024-03-22 19:07:35 +01:00
SQ2CPA d9629d0929 feat: serial kiss 2024-03-22 19:07:32 +01:00
SQ2CPA 2a5cc33711 feat: tnc server 2024-03-22 19:05:09 +01:00
richonguzman 6bd6cce82b digiMode self hearing fix 2024-03-21 15:21:29 -03:00
richonguzman 54bbede56c digimode fix 2024-03-21 15:19:30 -03:00
richonguzman 85b7596cbb minor code update 2024-03-21 00:09:35 -03:00
richonguzman fb4b6a25bd signalBandwidth fixed 2024-03-19 22:41:07 -03:00
richonguzman 4c30422635 refactor queries 2024-03-18 14:48:56 -03:00
richonguzman e059c65a99 testing Queries for DigiMode 2024-03-18 10:38:16 -03:00
richonguzman 3fda399ecf OE5HWN_MeshCom readme update 2024-03-18 09:40:57 -03:00
richonguzman 492f571183 OE5HWN_MeshCom added 2024-03-18 09:40:05 -03:00
richonguzman b287704293 start 2024-03-18 08:42:18 -03:00
richonguzman d802fb4c91 readme update 2024-03-12 16:45:22 -03:00
richonguzman 4247d00be4 TNC Text cleaning 2024-03-10 12:16:08 -03:00
richonguzman 7401c36fdf readme update 2024-03-10 09:32:50 -03:00
Ricardo Guzman (Richonguzman) cc2d4a669d Merge pull request #44 from richonguzman/adding-HELTEC-Wireless-Stick
Adding heltec wireless stick
2024-03-09 20:18:51 -03:00
richonguzman 706d84cf07 adding WebUI pics 2024-03-09 20:14:24 -03:00
richonguzman 4ae33a8362 first Test Heltec WS 2024-03-09 09:43:51 -03:00
79 changed files with 4451 additions and 2352 deletions
+85 -17
View File
@@ -11,16 +11,44 @@ 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_lite" # NOT FULLY TESTED
- name: ttgo-lora32-v21
chip: esp32
- 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: ESP32_DIY_LoRa
chip: esp32
- name: ESP32_DIY_1W_LoRa
chip: esp32
- name: ttgo-t-beam-v1_2
chip: esp32
- name: ttgo-t-beam-v1
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: heltec_wireless_tracker
chip: esp32s3
- name: OE5HWN_MeshCom
chip: esp32
- name: WEMOS-LOLIN32-OLED-DIY
chip: esp32
- name: WEMOS-D1-R32-RA02
chip: esp32
- name: ttgo-lora32-v21-915
chip: esp32
- name: heltec_ht-ct62
chip: esp32c3
- name: esp32c3_DIY_1W_LoRa
chip: esp32c3
steps:
- uses: actions/checkout@v3
@@ -32,19 +60,59 @@ 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/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: |
if [ "${{ matrix.target.chip }}" == "esp32" ]; then
python installer/bin/esptool/esptool.py --chip esp32 merge_bin \
-o installer/web_factory_${{ matrix.target.name }}.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_${{ matrix.target.name }}.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_${{ matrix.target.name }}.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
@@ -59,5 +127,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
+31
View File
@@ -0,0 +1,31 @@
name: Commit Test Build
on:
push:
branches:
- '*'
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
target:
- name: ttgo-lora32-v21
chip: esp32
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.9"
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- name: Build target
run: pio run -e ${{ matrix.target.name }}
- name: Build FS
run: pio run --target buildfs -e ${{ matrix.target.name }}
+2 -2
View File
@@ -1,4 +1,4 @@
{
"editor.tabSize": 4,
"editor.formatOnSave": true
}
"editor.formatOnSave": false
}
+48 -78
View File
@@ -2,7 +2,7 @@
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/OledScreen.jpeg)
![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>)__
@@ -14,64 +14,82 @@ ___________________________________________________
____________________________________________________
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.
# WEB INSTALLER
In all configurations the display shows the current stationMode, heard packets and events the iGate is currently performing.
As easy as it gets, the new <a href="https://sq2cpa.github.io/lora-flasher/ca2rxu.html" target="_blank">Web Installer</a> (thanks Damian SQ2CPA)
But under the hood is much more:
[<img src="https://github.com/richonguzman/LoRa_APRS_iGate/blob/main/images/WebFlasher.png">](https://sq2cpa.github.io/lora-flasher/ca2rxu.html)
- 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
# SUPPORTED BOARDS
- TTGO Lilygo LoRa32 v2.1 / v1.6 (they work the same)
- TTGO T-Beam v1.0 , v1.1, v1.2 (also variations with SX1262 and SX1268 LoRa Modules)
- HELTEC V2, V3 , Wireless Stick, HT-CT62, Wireless Tracker
- ESP32 Wroom + SX1278 LoRa Module or 400M30S 1W LoRa Module for a DIY Versions.
- ESP32 + 4G/LTE A7670 Modem + SX1278 DIY Version.
- Wemos Lolin32 Oled + SX1278 DIY Version.
### Buying links --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/Z.-------Supported-Boards-and-Buying-Links" target="_blank">here</a>.
____________________________________________________
# WIKI
### 1. Installation Guide --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/1.-Installation-Guide" target="_blank">here</a>.
### Installation Guide --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/01.-Installation-Guide" target="_blank">here</a>.
### 2. iGate Configuration and Explanation for each setting --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/2.-iGate-Configuration" target="_blank">here</a>.
### 3. Supported Boards and Environment Selection --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/3.-Supported-Boards-and-Environment-Selection" target="_blank">here</a>.
### 4. Upload Firmware and Filesystem --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/4.-Upload-Firmware-and-Filesystem" target="_blank">here</a>.
### 5. Adding BME280 Module --> <a href="https://github.com/richonguzman/LoRa_APRS_iGate/wiki/5.-Adding-BME280-Module" target="_blank">here</a>.
*(Wiki has all configuration explanation, supported boards list, adding BME/BMP Wx modules and more)*
____________________________________________________
## Timeline (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 Rx and Tx 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.
- 2024.02.25 New Web Configuration UI with WiFi AP (thanks Damian SQ2CPA).
- 2023.01.28 Updated to ElegantOTA v.3 (AsyncElegantOTA was deprecated).
- 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.
@@ -83,54 +101,6 @@ ____________________________________________________
- 2023.02.17 Receiving Feed from APRS-IS.
- 2023.02.10 First Beta (receiving LoRa Beacon/Packets and uploading to APRS-IS).
____________________________________________________
Instructions (add your information into the '/data/igate_conf.json'):
a) Change _callsign_ from "NOCALL-10" to your CALLSIGN + SSID.
b) Choose _stationMode_:
1 = RX iGate, black "L" as symbol
2 = Rx + TX iGate, red "L" as symbol, HAM only. RX will be sent to APRS-IS, Messages will be sent via Lora. Same frequency for RX and TX. By using this feature you have comply with the regulations of your country.
3 = Digipeater simplex, green "L" as symbol, HAM only. Received packets containing WIDEx-x in path will be digipeated on the same frequency. By using this feature you have comply with the regulations of your country.
4 = Digipeater split frequency, green "L" as symbol, HAM only. Received packets will be digipeated on a different frequency. Frequency separation must be 125kHz or more. By using this feature you have comply with the regulations of your country.
IgateComment and DigirepeaterComment will be sent to APRS-IS or via RF, depending on your stationmode
c) WiFi section:
adjust SSID and Password to you WiFi, add the GPS to "Latitude" and "Longitude" (info from GoogleMaps) of your new LoRa iGate. (If stationMode 3 or 4 selected, add also GPS info to Digirepeater Section).
d) APRS_IS section:
change "passcode" from "VWXYZ" to yours (remember that is 5 digits integer) and choose a server close to your location (see https://www.aprs2.net/)
e) LORA section:
adjust TX frequency and RX frequency matching your stationmode and country. Remember,
at stationmode 1, 2, and 3, RX and TX frequency shall be set to 433775000 (443.775MHz, deviations possible, depending on your country)
at stationmode 4, RX frequency shall be set to 433775000, TX frequency shall be set to 433900000 (deviations possible, depending on your country). There must be a frequency separation of 125kHz or more.
adjust power to your need, valid values are from 1 to 20
f) Syslog section:
adjust server and port to a suitable value if needed.
g) BME section:
adjust to "active" if BME280 sensor connected through I2C pins
__________________________________________
Special Thanks to the help in testing and developing to Manfred (DC2MH) , for showing me the "way of good coding" to Tihomir (CA3TSK) and much more Ham Licence Ops all over the world.
# Hope You Enjoy this, 73 !! CA2RXU , Valparaiso, Chile
+30 -11
View File
@@ -13,21 +13,22 @@
"comment": "LoRa APRS",
"interval": 15,
"overlay": "L",
"symbol": "#",
"symbol": "a",
"path": "WIDE1-1",
"sendViaAPRSIS": false,
"sendViaRF": false
},
"digi": {
"mode": 0
},
"aprs_is": {
"active": false,
"passcode": "XYZVW",
"server": "rotate.aprs2.net",
"port": 14580,
"filter": "m/10",
"toRF": false
"messagesToRF": false,
"objectsToRF": false
},
"digi": {
"mode": 0
},
"lora": {
"txFreq": 433775000,
@@ -44,13 +45,29 @@
"timeout": 4,
"turn180": false
},
"battery": {
"sendInternalVoltage": false,
"monitorInternalVoltage": false,
"internalSleepVoltage": 3.0,
"sendExternalVoltage": false,
"externalVoltagePin": 34,
"monitorExternalVoltage": false,
"externalSleepVoltage": 10.9
},
"bme": {
"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": "",
@@ -58,8 +75,10 @@
},
"other": {
"rememberStationTime": 30,
"sendBatteryVoltage": false,
"externalVoltageMeasurement": false,
"externalVoltagePin": 34
"lowPowerMode": false,
"lowVoltageCutOff": 0,
"backupDigiMode": false,
"rebootMode": false,
"rebootModeTime": 6
}
}
}
+877 -536
View File
File diff suppressed because it is too large Load Diff
+170 -102
View File
@@ -74,19 +74,18 @@ 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("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;
const wifiNetworks = settings.wifi.AP || [];
const networksContainer = document.querySelector(".list-networks");
let networkCount = 0;
@@ -119,96 +118,122 @@ 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;
// Digi
document.getElementById("digi.mode").value = settings.digi.mode;
// 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;
// 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.monitorExternalVoltage").checked = settings.battery.monitorExternalVoltage;
document.getElementById("battery.externalSleepVoltage").value = settings.battery.externalSleepVoltage.toFixed(1);
// TELEMETRY BME/WX
document.getElementById("bme.active").checked = settings.bme.active;
document.getElementById("bme.heightCorrection").value = settings.bme.heightCorrection;
document.getElementById("bme.temperatureCorrection").value = settings.bme.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.powerOff").value = settings.wifi.autoAP.powerOff;
// OTA
document.getElementById("ota.username").value = settings.ota.username;
document.getElementById("ota.password").value = settings.ota.password;
// Experimental
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();
toggleFields();
}
function showToast(message) {
const el = document.querySelector('#toast');
el.querySelector('.toast-body').innerHTML = message;
(new bootstrap.Toast(el)).show();
}
document.getElementById('send-beacon').addEventListener('click', function (e) {
e.preventDefault();
fetch("/action?type=send-beacon", { method: "POST" });
showToast("Your beacon will be sent in a moment. <br> <u>This action will be ignored if you have APRSIS and LoRa TX disabled!</u>");
});
document.getElementById('reboot').addEventListener('click', function (e) {
e.preventDefault();
fetch("/action?type=reboot", { method: "POST" });
showToast("Your device will be rebooted in a while");
});
const bmeCheckbox = document.querySelector("input[name='bme.active']");
const stationModeSelect = document.querySelector("select[name='stationMode']");
@@ -239,36 +264,26 @@ function updateImage() {
}
function toggleFields() {
const sendBatteryVoltageCheckbox = document.querySelector(
'input[name="other.sendBatteryVoltage"]'
);
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.disabled =
!sendBatteryVoltageCheckbox.checked;
externalVoltagePinInput.disabled =
!externalVoltageMeasurementCheckbox.checked;
!sendExternalVoltageCheckbox.checked;
}
const sendBatteryVoltageCheckbox = document.querySelector(
'input[name="other.sendBatteryVoltage"]'
);
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"]'
);
sendBatteryVoltageCheckbox.addEventListener("change", function () {
externalVoltageMeasurementCheckbox.disabled = !this.checked;
externalVoltagePinInput.disabled =
!externalVoltageMeasurementCheckbox.checked;
sendExternalVoltageCheckbox.addEventListener("change", function () {
externalVoltagePinInput.disabled = !this.checked;
});
document.querySelector(".new button").addEventListener("click", function () {
@@ -378,8 +393,6 @@ document.getElementById("action.speed").addEventListener("change", function () {
}
});
toggleFields();
const form = document.querySelector("form");
const saveModal = new bootstrap.Modal(document.getElementById("saveModal"), {
@@ -431,3 +444,58 @@ form.addEventListener("submit", async (event) => {
});
fetchSettings();
function loadReceivedPackets(packets) {
if (packets) {
document.querySelector('#received-packets tbody').innerHTML = '';
const container = document.querySelector("#received-packets tbody");
container.innerHTML = '';
const date = new Date();
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.packet}</td>
<td>${packet.RSSI}</td>
<td>${packet.SNR}</td>
`;
container.appendChild(element);
})
}
setTimeout(fetchReceivedPackets, 15000);
}
function fetchReceivedPackets() {
fetch("/received-packets.json")
.then((response) => response.json())
.then((packets) => {
loadReceivedPackets(packets);
})
.catch((err) => {
console.error(err);
console.error(`Failed to load received packets`);
});
}
document.querySelector('a[href="/received-packets"]').addEventListener('click', function (e) {
e.preventDefault();
document.getElementById('received-packets').classList.remove('d-none');
document.getElementById('configuration').classList.add('d-none');
document.querySelector('button[type=submit]').remove();
fetchReceivedPackets();
})
+8
View File
@@ -0,0 +1,8 @@
.alert-fixed {
position:fixed;
top: 0px;
left: 0px;
width: 100%;
z-index:9999;
border-radius:0px
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 KiB

+255 -32
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,67 +22,289 @@ 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
sandeepmistry/LoRa@^0.8.0
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
extra_scripts =
pre:tools/compress.py
debug_tool = esp-prog
[common]
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.1
ottowinter/ESPAsyncWebServer-esphome @ 3.2.2
esphome/AsyncTCP-esphome @ 2.1.1
[env:ttgo-lora32-v21]
board = ttgo-lora32-v21
build_flags = -Werror -Wall -DTTGO_T_LORA32_V2_1 -DELEGANTOTA_USE_ASYNC_WEBSERVER=1
build_flags =
-Werror -Wall
-DTTGO_T_LORA32_V2_1
-DHAS_SX1278
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:heltec-lora32-v2]
board = ttgo-lora32-v21
build_flags = -Werror -Wall -DHELTEC_V2 -DELEGANTOTA_USE_ASYNC_WEBSERVER=1
build_flags =
-Werror -Wall
-DHELTEC_V2
-DHAS_SX1278
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:heltec_wifi_lora_32_V3]
board = heltec_wifi_lora_32_V3
build_flags = -Werror -Wall -DHELTEC_V3 -DELEGANTOTA_USE_ASYNC_WEBSERVER=1
board_build.mcu = esp32s3
build_flags =
-Werror -Wall
-DHELTEC_V3
-DHAS_SX1262
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:heltec_wireless_stick]
board = heltec_wifi_lora_32_V3
board_build.mcu = esp32s3
build_flags =
-Werror -Wall
-DHELTEC_WS
-DHAS_SX1262
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:heltec_wireless_stick_lite_v3]
board = esp32-s3-devkitc-1
board_build.mcu = esp32s3
build_flags =
-Werror -Wall
-DHELTEC_WSL_V3
-DHAS_SX1262
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
[env:heltec_ht-ct62]
board = heltec_wireless_stick_lite
board_build.mcu = esp32c3
build_flags =
-Werror -Wall
-DHELTEC_HTCT62
-DHAS_SX1262
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:ESP32_DIY_LoRa]
board = esp32dev
build_flags = -Werror -Wall -DESP32_DIY_LoRa -DELEGANTOTA_USE_ASYNC_WEBSERVER=1
build_flags =
-Werror -Wall
-DESP32_DIY_LoRa
-DHAS_SX1278
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:ESP32_DIY_1W_LoRa]
board = esp32dev
build_flags = -Werror -Wall -DESP32_DIY_1W_LoRa -DELEGANTOTA_USE_ASYNC_WEBSERVER=1
build_flags =
-Werror -Wall
-DESP32_DIY_1W_LoRa
-DHAS_SX1268
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:ttgo-t-beam-v1_2]
board = ttgo-t-beam
build_flags = -Werror -Wall -DTTGO_T_Beam_V1_2 -DELEGANTOTA_USE_ASYNC_WEBSERVER=1
build_flags =
-Werror -Wall
-DTTGO_T_Beam_V1_2
-DHAS_SX1278
-DHAS_AXP2101
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
lewisxhe/XPowersLib @ 0.2.4
[env:ttgo-t-beam-v1]
board = ttgo-t-beam
build_flags = -Werror -Wall -DTTGO_T_Beam_V1_0 -DELEGANTOTA_USE_ASYNC_WEBSERVER=1
build_flags =
-Werror -Wall
-DTTGO_T_Beam_V1_0
-DHAS_SX1278
-DHAS_AXP192
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
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 -DELEGANTOTA_USE_ASYNC_WEBSERVER=1
build_flags =
-Werror -Wall
-DTTGO_T_Beam_V1_0_SX1268
-DHAS_SX1268
-DHAS_AXP192
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
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 -DELEGANTOTA_USE_ASYNC_WEBSERVER=1
build_flags =
-Werror -Wall
-DTTGO_T_Beam_V1_2_SX1262
-DHAS_SX1262
-DHAS_AXP2101
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
lewisxhe/XPowersLib @ 0.2.4
[env:heltec_wireless_stick_lite]
platform = espressif32
board = heltec_wireless_stick_lite
[env:ESP32_DIY_LoRa_A7670]
board = esp32dev
build_flags =
-Werror -Wall
-DESP32_DIY_LoRa_A7670
-DHAS_SX1278
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
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_WIRELESS_TRACKER
-DHAS_SX1262
-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
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
bodmer/TFT_eSPI @ 2.5.43
[env:OE5HWN_MeshCom]
board = esp32dev
build_flags =
-Werror -Wall
-DOE5HWN_MeshCom
-DHAS_SX1268
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:WEMOS-LOLIN32-OLED-DIY]
board = lolin32
build_flags =
-Werror -Wall
-DWEMOS_LOLIN32_OLED_DIY_LoRa
-DHAS_SX1278
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:WEMOS-D1-R32-RA02]
board = wemos_d1_uno32
build_flags =
-Werror -Wall
-DWEMOS_D1_R32_RA02
-DHAS_SX1278
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:ttgo-lora32-v21-915]
board = ttgo-lora32-v21
build_flags =
-Werror -Wall
-DTTGO_T_LORA32_V2_1_915
-DHAS_SX1276
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
[env:esp32c3_DIY_1W_LoRa]
extends = env:esp32
board = esp32-c3-devkitm-1
board_build.mcu = esp32c3
board_build.f_cpu = 240000000L
build_flags = -Werror -Wall -DHELTEC_CT62 -DELEGANTOTA_USE_ASYNC_WEBSERVER=1
build_flags =
-Werror -Wall
-DESP32C3_DIY_1W_LoRa
-DHAS_SX1268
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1
-DELEGANTOTA_USE_ASYNC_WEBSERVER=1
lib_deps =
${common.lib_deps}
adafruit/Adafruit GFX Library @ 1.11.9
adafruit/Adafruit SSD1306 @ 2.5.10
+200
View File
@@ -0,0 +1,200 @@
#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"
#if defined(ESP32_DIY_LoRa_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 ... ");
show_display(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");
show_display(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 {
show_display(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");
show_display(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!");
show_display(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)");
show_display(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!");
show_display(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 " + Config.callsign + " pass " + String(Config.aprs_is.passcode) + " vers CA2RXU_LoRa_iGate 1.3 filter " + Config.aprs_is.filter;
Serial.println("-----> Connecting to APRS IS");
while (!modemStartUp) {
Serial.print("Opening Port... ");
show_display(firstLine, "Opening Port...", " ", " ", 0);
modemStartUp = checkATResponse("AT+NETOPEN");
delay(2000);
} while (!serverStartUp) {
Serial.print("Connecting APRS-IS Server... ");
show_display(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 ");
show_display(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
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
+118 -56
View File
@@ -1,11 +1,27 @@
/*______________________________________________________________________________________________________________
██╗ ██████╗ ██████╗ █████╗ █████╗ ██████╗ ██████╗ ███████╗ ██╗ ██████╗ █████╗ ████████╗███████╗
██║ ██╔═══██╗██╔══██╗██╔══██╗ ██╔══██╗██╔══██╗██╔══██╗██╔════╝ ██║██╔════╝ ██╔══██╗╚══██╔══╝██╔════╝
██║ ██║ ██║██████╔╝███████║ ███████║██████╔╝██████╔╝███████╗ ██║██║ ███╗███████║ ██║ █████╗
██║ ██║ ██║██╔══██╗██╔══██║ ██╔══██║██╔═══╝ ██╔══██╗╚════██║ ██║██║ ██║██╔══██║ ██║ ██╔══╝
███████╗╚██████╔╝██║ ██║██║ ██║ ██║ ██║██║ ██║ ██║███████║ ██║╚██████╔╝██║ ██║ ██║ ███████╗
╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝
Ricardo Guzman - CA2RXU
https://github.com/richonguzman/LoRa_APRS_Tracker
(donations : http://paypal.me/richonguzman)
______________________________________________________________________________________________________________*/
#include <ElegantOTA.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 "syslog_utils.h"
#include "pins_config.h"
#include "query_utils.h"
#include "power_utils.h"
#include "lora_utils.h"
@@ -14,74 +30,96 @@
#include "gps_utils.h"
#include "bme_utils.h"
#include "web_utils.h"
#include "tnc_utils.h"
#include "display.h"
#include "utils.h"
#include <ElegantOTA.h>
#ifdef ESP32_DIY_LoRa_A7670
#include "A7670_utils.h"
#endif
String versionDate = "2024.06.15";
Configuration Config;
WiFiClient espClient;
String versionDate = "2024.03.08";
int 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 backUpDigiMode = false;
bool modemLoggedToAPRSIS = false;
bool WiFiAutoAPStarted = false;
long WiFiAutoAPTime = false;
std::vector<ReceivedPacket> receivedPackets;
uint32_t bmeLastReading = -60000;
String firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine;
String batteryVoltage;
std::vector<String> lastHeardStation;
std::vector<String> lastHeardStation_temp;
std::vector<String> packetBuffer;
std::vector<String> packetBuffer_temp;
String firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, iGateBeaconPacket, iGateLoRaBeaconPacket;
//#define STARTUP_DELAY 5 //min
void setup() {
Serial.begin(115200);
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2)
pinMode(batteryPin, INPUT);
#endif
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
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();
WIFI_Utils::setup();
LoRa_Utils::setup();
Utils::validateFreqs();
GPS_Utils::generateBeacons();
iGateBeaconPacket = GPS_Utils::generateBeacon();
iGateLoRaBeaconPacket = GPS_Utils::generateiGateLoRaBeacon();
#ifdef STARTUP_DELAY // (TEST) just to wait for WiFi init of Routers
show_display("", " 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);
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";
STATION_Utils::addToOutputPacketBuffer(GPS_Utils::getiGateLoRaBeaconPacket() + comment);
lastBeacon = time;
}
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;
}
#endif
WIFI_Utils::setup();
SYSLOG_Utils::setup();
BME_Utils::setup();
WEB_Utils::setup();
TNC_Utils::setup();
#ifdef ESP32_DIY_LoRa_A7670
A7670_Utils::setup();
#endif
Utils::checkRebootMode();
}
void loop() {
@@ -92,33 +130,57 @@ void loop() {
return; // Don't process IGate and Digi during OTA update
}
if (Config.lowVoltageCutOff > 0) {
BATTERY_Utils::checkIfShouldSleep();
}
thirdLine = Utils::getLocalIP();
WIFI_Utils::checkWiFi(); // Always use WiFi, not related to IGate/Digi mode
// Utils::checkWiFiInterval();
if (Config.aprs_is.active && !espClient.connected()) {
APRS_IS_Utils::connect();
}
#ifdef ESP32_DIY_LoRa_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
TNC_Utils::loop();
Utils::checkDisplayInterval();
Utils::checkBeaconInterval();
String packet;
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
}
APRS_IS_Utils::checkStatus(); // Need that to update display, maybe split this and send APRSIS status to display func?
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 || backUpDigiMode) { // If Digi enabled
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
}
}
if (Config.aprs_is.active) { // If APRSIS enabled
APRS_IS_Utils::loop(packet); // Send received packet to APRSIS
APRS_IS_Utils::listenAPRSIS(); // listen received packet from APRSIS
}
if (Config.digi.mode == 2) { // If Digi enabled
DIGI_Utils::loop(packet); // Send received packet to Digi
}
STATION_Utils::processOutputPacketBuffer();
STATION_Utils::clean25SegBuffer();
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
Utils::checkRebootTime();
Utils::checkSleepByLowBatteryVoltage(1);
}
+254 -168
View File
@@ -4,32 +4,39 @@
#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 int internalLedPin;
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 ESP32_DIY_LoRa_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(){
int count = 0;
void connect() {
uint8_t count = 0;
String aprsauth;
Serial.print("Connecting to APRS-IS ... ");
while (!espClient.connect(Config.aprs_is.server.c_str(), Config.aprs_is.port) && count < 20) {
@@ -44,12 +51,13 @@ namespace APRS_IS_Utils {
}
if (count == 20) {
Serial.println("Tried: " + String(count) + " FAILED!");
} else {
Serial.println("Connected!\n(Server: " + String(Config.aprs_is.server) + " / Port: " + String(Config.aprs_is.port) +")");
}
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;// + "\r\n";
aprsauth = "user " + Config.callsign + " pass " + Config.aprs_is.passcode + " vers CA2RXU_LoRa_iGate 1.3 filter " + Config.aprs_is.filter;
upload(aprsauth);
delay(200);
}
@@ -58,182 +66,260 @@ namespace APRS_IS_Utils {
void checkStatus() {
String wifiState, aprsisState;
if (WiFi.status() == WL_CONNECTED) {
wifiState = "OK";
wifiState = "OK";
} else {
wifiState = "AP";
if (!Config.display.alwaysOn) {
if (backUpDigiMode) {
wifiState = "--";
} else {
wifiState = "AP";
}
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
display_toggle(true);
}
lastScreenOn = millis();
}
if (!Config.aprs_is.active) {
aprsisState = "OFF";
} else if (espClient.connected()) {
aprsisState = "OK";
aprsisState = "OFF";
} else {
aprsisState = "--";
#ifdef ESP32_DIY_LoRa_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) {
display_toggle(true);
lastScreenOn = millis();
}
}
secondLine = "WiFi: ";
secondLine += wifiState;
secondLine += " APRS-IS: ";
secondLine += aprsisState;
}
if (!Config.display.alwaysOn) {
String buildPacketToUpload(const String& packet) {
String payload = packet.substring(packet.indexOf(":"));
if (payload.indexOf("\x3c\xff\x01") != -1) {
payload = payload.substring(0, payload.indexOf("\x3c\xff\x01"));
}
if (!(Config.aprs_is.active && Config.digi.mode == 0)) { // Check if NOT only IGate
return packet.substring(3, packet.indexOf(":")) + ",qAR," + Config.callsign + payload;
} else {
return packet.substring(3, packet.indexOf(":")) + ",qAO," + Config.callsign + payload;
}
}
String buildPacketToTx(const String& aprsisPacket, uint8_t packetType) {
String packet = aprsisPacket;
packet.trim();
String outputPacket = packet.substring(0, packet.indexOf(","));
outputPacket.concat(",TCPIP,WIDE1-1,");
outputPacket.concat(Config.callsign);
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;
}
bool processReceivedLoRaMessage(const String& sender, const String& packet) {
String receivedMessage;
if (packet.indexOf("{") > 0) { // ack?
String ackMessage = "ack";
ackMessage.concat(packet.substring(packet.indexOf("{") + 1));
ackMessage.trim();
//Serial.println(ackMessage);
String processedSender = sender;
for (int i = sender.length(); i < 9; i++) {
processedSender += ' ';
}
if (Config.beacon.path == "") {
STATION_Utils::addToOutputPacketBuffer(Config.callsign + ">APLRG1,RFONLY::" + processedSender + ":" + ackMessage);
} else {
STATION_Utils::addToOutputPacketBuffer(Config.callsign + ">APLRG1,RFONLY," + Config.beacon.path + "::" + processedSender + ":" + ackMessage);
}
receivedMessage = packet.substring(packet.indexOf(":") + 1, packet.indexOf("{"));
} else {
receivedMessage = packet.substring(packet.indexOf(":") + 1);
}
if (receivedMessage.indexOf("?") == 0) {
delay(2000);
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
display_toggle(true);
}
STATION_Utils::addToOutputPacketBuffer(QUERY_Utils::process(receivedMessage, sender, 0)); // LoRa
lastScreenOn = millis();
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, "Callsign = " + sender, "TYPE --> QUERY", 0);
return true;
}
secondLine = "WiFi: " + wifiState + " APRS-IS: " + aprsisState;
}
String createPacket(String packet) {
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(":"));// + "\n";
} else {
return packet.substring(3, packet.indexOf(":")) + ",qAO," + Config.callsign + packet.substring(packet.indexOf(":"));// + "\n";
else {
return false;
}
}
void processLoRaPacket(String packet) {
bool queryMessage = false;
String aprsPacket, Sender, AddresseeAndMessage, Addressee, ackMessage, receivedMessage;
if (packet != "") {
#ifdef TextSerialOutputForApp
Serial.println(packet.substring(3));
#else
Serial.print("Received Lora Packet : " + String(packet));
#endif
if ((packet.substring(0,3) == "\x3c\xff\x01") && (packet.indexOf("TCPIP") == -1) && (packet.indexOf("NOGATE") == -1) && (packet.indexOf("RFONLY") == -1)) {
#ifndef TextSerialOutputForApp
Serial.print(" ---> APRS LoRa Packet!");
#endif
Sender = packet.substring(3,packet.indexOf(">"));
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!
if (AddresseeAndMessage.indexOf("{")>0) { // ack?
ackMessage = "ack" + AddresseeAndMessage.substring(AddresseeAndMessage.indexOf("{")+1);
ackMessage.trim();
delay(4000);
//Serial.println(ackMessage);
for(int i = Sender.length(); i < 9; i++) {
Sender += ' ';
void processLoRaPacket(const String& packet) {
if (espClient.connected() || modemLoggedToAPRSIS) {
bool queryMessage = false;
String aprsPacket, Sender, AddresseeAndMessage, Addressee;
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(">"));
if (Sender != Config.callsign && Utils::checkValidCallsign(Sender)) {
if (STATION_Utils::check25SegBuffer(Sender, packet.substring(packet.indexOf(":")+2))) {
STATION_Utils::updateLastHeard(Sender);
Utils::typeOfPacket(packet.substring(3), 0); // LoRa-APRS
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!
if (AddresseeAndMessage.indexOf("\x3c\xff\x01") != -1) {
AddresseeAndMessage = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf("\x3c\xff\x01"));
}
queryMessage = processReceivedLoRaMessage(Sender, AddresseeAndMessage);
}
LoRa_Utils::sendNewPacket("APRS", Config.callsign + ">APLRG1,RFONLY,WIDE1-1::" + Sender + ":" + ackMessage);
receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":")+1, AddresseeAndMessage.indexOf("{"));
} else {
receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":")+1);
}
if (receivedMessage.indexOf("?") == 0) {
queryMessage = true;
delay(2000);
if (!Config.display.alwaysOn) {
display_toggle(true);
if (!queryMessage) {
aprsPacket = buildPacketToUpload(packet);
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
display_toggle(true);
}
lastScreenOn = millis();
#ifdef ESP32_DIY_LoRa_A7670
stationBeacon = true;
A7670_Utils::uploadToAPRSIS(aprsPacket);
stationBeacon = false;
#else
upload(aprsPacket);
#endif
Utils::println("---> Uploaded to APRS-IS");
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
}
LoRa_Utils::sendNewPacket("APRS", QUERY_Utils::process(receivedMessage, Sender, "LoRa"));
lastScreenOn = millis();
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, "Callsign = " + Sender, "TYPE --> QUERY", 0);
}
}
if (!queryMessage) {
aprsPacket = createPacket(packet);
if (!Config.display.alwaysOn) {
display_toggle(true);
}
lastScreenOn = millis();
upload(aprsPacket);
#ifndef TextSerialOutputForApp
Serial.println(" ---> Uploaded to APRS-IS");
#endif
STATION_Utils::updateLastHeard(Sender);
Utils::typeOfPacket(aprsPacket, "LoRa-APRS");
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
}
}
} else {
#ifndef TextSerialOutputForApp
Serial.println(" ---> LoRa Packet Ignored (first 3 bytes or TCPIP/NOGATE/RFONLY)\n");
#endif
}
}
}
void processAPRSISPacket(String packet) {
String Sender, AddresseeAndMessage, Addressee, receivedMessage;
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(":"));
Addressee.trim();
if (Addressee == Config.callsign) { // its for me!
if (AddresseeAndMessage.indexOf("{")>0) { // ack?
String ackMessage = "ack" + AddresseeAndMessage.substring(AddresseeAndMessage.indexOf("{")+1);
ackMessage.trim();
delay(4000);
//Serial.println(ackMessage);
for(int i = Sender.length(); i < 9; i++) {
Sender += ' ';
}
String ackPacket = Config.callsign + ">APLRG1,TCPIP,qAC::" + Sender + ":" + ackMessage;// + "\n";
upload(ackPacket);
receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":")+1, AddresseeAndMessage.indexOf("{"));
} else {
receivedMessage = AddresseeAndMessage.substring(AddresseeAndMessage.indexOf(":")+1);
}
if (receivedMessage.indexOf("?") == 0) {
#ifndef TextSerialOutputForApp
Serial.println("Received Query APRS-IS : " + packet);
#endif
String queryAnswer = QUERY_Utils::process(receivedMessage, Sender, "APRSIS");
//Serial.println("---> QUERY Answer : " + queryAnswer.substring(0,queryAnswer.indexOf("\n")));
if (!Config.display.alwaysOn) {
display_toggle(true);
}
lastScreenOn = millis();
delay(500);
upload(queryAnswer);
SYSLOG_Utils::log("APRSIS Tx", queryAnswer,0,0,0);
fifthLine = "APRS-IS ----> APRS-IS";
sixthLine = Config.callsign;
for (int j=sixthLine.length();j<9;j++) {
sixthLine += " ";
}
sixthLine += "> " + Sender;
seventhLine = "QUERY = " + receivedMessage;
}
} else {
#ifndef TextSerialOutputForApp
Serial.print("Received from APRS-IS : " + packet);
#endif
if (Config.aprs_is.toRF && STATION_Utils::wasHeard(Addressee)) {
LoRa_Utils::sendNewPacket("APRS", LoRa_Utils::generatePacket(packet));
display_toggle(true);
lastScreenOn = millis();
Utils::typeOfPacket(packet, "APRS-LoRa");
}
}
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, seventhLine, 0);
}
}
}
}
void loop(String packet) {
if (espClient.connected()) {
processLoRaPacket(packet);
if (espClient.available()) {
String aprsisPacket = espClient.readStringUntil('\r');
// Serial.println(aprsisPacket);
processAPRSISPacket(aprsisPacket);
void processAPRSISPacket(const String& packet) {
String Sender, AddresseeAndMessage, Addressee, receivedMessage;
if (!packet.startsWith("#")) {
if (Config.aprs_is.messagesToRF && packet.indexOf("::") > 0) {
Sender = packet.substring(0, packet.indexOf(">"));
if (Utils::checkValidCallsign(Sender)) {
AddresseeAndMessage = packet.substring(packet.indexOf("::") + 2);
Addressee = AddresseeAndMessage.substring(0, AddresseeAndMessage.indexOf(":"));
Addressee.trim();
if (Addressee == Config.callsign) { // its for me!
if (AddresseeAndMessage.indexOf("{") > 0) { // ack?
String ackMessage = "ack" + 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;
#ifdef ESP32_DIY_LoRa_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, 1); // APRSIS
//Serial.println("---> QUERY Answer : " + queryAnswer.substring(0,queryAnswer.indexOf("\n")));
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
display_toggle(true);
}
lastScreenOn = millis();
delay(500);
#ifdef ESP32_DIY_LoRa_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 += "> ";
sixthLine += Sender;
seventhLine = "QUERY = ";
seventhLine += receivedMessage;
}
} else {
Utils::print("Received Message from APRS-IS : " + packet);
if (STATION_Utils::wasHeard(Addressee) && Utils::checkValidCallsign(Addressee)) {
STATION_Utils::addToOutputPacketBuffer(buildPacketToTx(packet, 1));
display_toggle(true);
lastScreenOn = millis();
Utils::typeOfPacket(packet, 1); // APRS-LoRa
}
}
show_display(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));
display_toggle(true);
lastScreenOn = millis();
Utils::typeOfPacket(packet, 1); // APRS-LoRa
}
}
}
void listenAPRSIS() {
#ifdef ESP32_DIY_LoRa_A7670
A7670_Utils::listenAPRSIS();
#else
if (espClient.connected()) {
if (espClient.available()) {
String aprsisPacket = espClient.readStringUntil('\r');
// Serial.println(aprsisPacket);
processAPRSISPacket(aprsisPacket);
lastRxTime = millis();
}
}
#endif
}
}
+9 -14
View File
@@ -4,22 +4,17 @@
#include <Arduino.h>
//#define TextSerialOutputForApp
/* uncomment the previous line to get text from Serial-Output over USB into PC for:
- PinPoint App ( https://www.pinpointaprs.com )
- APRSIS32 App ( http://aprsisce.wikidot.com )
*/
namespace APRS_IS_Utils {
void upload(String line);
void connect();
void checkStatus();
String createPacket(String unprocessedPacket);
void processLoRaPacket(String packet);
void processAPRSISPacket(String packet);
void loop(String packet);
void upload(const String& line);
void connect();
void checkStatus();
String buildPacketToUpload(const String& packet);
String buildPacketToTx(const String& aprsisPacket, uint8_t packetType);
bool processReceivedLoRaMessage(const String& sender, const String& packet);
void processLoRaPacket(const String& packet);
void processAPRSISPacket(const String& packet);
void listenAPRSIS();
}
+91 -19
View File
@@ -1,11 +1,17 @@
#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 Configuration Config;
extern uint32_t lastBatteryCheck;
float adcReadingTransformation = (3.3/4095);
float voltageDividerCorrection = 0.288;
bool shouldSleepLowVoltage = false;
float adcReadingTransformation = (3.3/4095);
float voltageDividerCorrection = 0.288;
// for External Voltage Measurment (MAX = 15Volts !!!)
float R1 = 100.000; //in Kilo-Ohms
@@ -16,31 +22,97 @@ float multiplyCorrection = 0.035;
namespace BATTERY_Utils {
float checkBattery() {
int sample;
int sampleSum = 0;
for (int i=0; i<100; i++) {
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2)
sample = analogRead(batteryPin);
float mapVoltage(float voltage, float in_min, float in_max, float out_min, float out_max) {
return (voltage - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
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_WSL_V3) || defined(HELTEC_WIRELESS_TRACKER)
digitalWrite(ADC_CTRL, HIGH);
#endif
#if defined(HELTEC_V3) || defined(HELTEC_V2)
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++) {
#ifdef BATTERY_PIN
sample = analogRead(BATTERY_PIN);
#endif
#if defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
sample = 0;
#endif
sampleSum += sample;
delayMicroseconds(50);
}
#ifdef ADC_CTRL
#if defined(HELTEC_WSL_V3) || defined(HELTEC_WIRELESS_TRACKER)
digitalWrite(ADC_CTRL, LOW);
#endif
#if defined(HELTEC_V3) || defined(HELTEC_V2)
digitalWrite(ADC_CTRL, HIGH);
#endif
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.
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
return (2 * (sampleSum/100) * adcReadingTransformation) + voltageDividerCorrection; // raw voltage without mapping
#endif
sampleSum += sample;
delayMicroseconds(50);
}
return (2 * (sampleSum/100) * adcReadingTransformation) + voltageDividerCorrection;
// 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);
for (int i = 0; i < 100; i++) {
sample = analogRead(Config.battery.externalVoltagePin);
sampleSum += sample;
delayMicroseconds(50);
}
return ((((sampleSum/100)* adcReadingTransformation) + readingCorrection) * ((R1+R2)/R2)) - multiplyCorrection;
float voltage = ((((sampleSum/100)* adcReadingTransformation) + readingCorrection) * ((R1+R2)/R2)) - multiplyCorrection;
return voltage; // 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 = checkInternalVoltage();
if (voltage < 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
if (Config.battery.monitorExternalVoltage && checkExternalVoltage() < Config.battery.externalSleepVoltage + 0.1) {
shouldSleepLowVoltage = true;
}
if (shouldSleepLowVoltage) {
Utils::checkSleepByLowBatteryVoltage(0);
}
}
}
+4 -2
View File
@@ -6,8 +6,10 @@
namespace BATTERY_Utils {
float checkBattery();
float checkExternalVoltage();
float checkInternalVoltage();
float checkExternalVoltage();
void checkIfShouldSleep(); // ????
void startupBatteryHealth();
}
+190 -112
View File
@@ -4,126 +4,179 @@
#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;
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 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
void getWxModuleAddres() {
uint8_t err, addr;
for(addr = 1; addr < 0x7F; addr++) {
#ifdef HELTEC_V3
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;
}
}
} else {
Serial.println("(BME/BMP sensor not 'active' in 'igate_conf.json')");
}
}
String generateTempString(float bmeTemp) {
void setup() {
if (Config.bme.active) {
getWxModuleAddres();
if (wxModuleAddress != 0x00) {
bool wxModuleFound = false;
if (wxModuleAddress == 0x76 || wxModuleAddress == 0x77) {
#ifdef HELTEC_V3
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) {
show_display("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 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 generateHumString(const 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";
return "00";
} else {
return "-99";
return "-99";
}
break;
default:
return "-99";
}
}
String generatePresString(float bmePress) {
String strPress;
strPress = String((int)bmePress);
String generatePresString(const float bmePress) {
String strPress = String((int)bmePress);
String decPress = String(int((bmePress - int(bmePress)) * 10));
switch (strPress.length()) {
case 1:
return "000" + strPress + "0";
break;
return "000" + strPress + decPress;
case 2:
return "00" + strPress + "0";
break;
return "00" + strPress + decPress;
case 3:
return "0" + strPress + "0";
break;
return "0" + strPress + decPress;
case 4:
return strPress + "0";
break;
return strPress + decPress;
case 5:
return strPress;
break;
default:
return "-99999";
}
@@ -131,53 +184,78 @@ namespace BME_Utils {
String readDataSensor() {
String wx, tempStr, humStr, presStr;
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;
}
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");
Serial.println("BME/BMP/Si7021 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
tempStr = generateTempString(((newTemp + Config.bme.temperatureCorrection) * 1.8) + 32);
if (wxModuleType == 1 || wxModuleType == 3 || wxModuleType == 4) {
humStr = generateHumString(newHum);
} else if (wxModuleType == 2) {
humStr = "..";
}
if (wxModuleAddress == 4) {
presStr = ".....";
} else {
presStr = generatePresString(newPress + (Config.bme.heightCorrection/CORRECTION_FACTOR));
}
fifthLine = "BME-> ";
fifthLine += String(int(newTemp + Config.bme.temperatureCorrection));
fifthLine += "C ";
fifthLine += humStr;
fifthLine += "% ";
fifthLine += presStr.substring(0,4);
fifthLine += "hPa";
wx = ".../...g...t";
wx += tempStr;
wx += "r...p...P...h";
wx += humStr;
wx += "b";
wx += presStr;
if (wxModuleType == 3) {
wx += "Gas: ";
wx += String(newGas);
wx += "Kohms";
}
return wx;
}
}
+7 -17
View File
@@ -1,31 +1,21 @@
#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
#include "Adafruit_Si7021.h"
#include <Arduino.h>
namespace BME_Utils {
void setup();
String generateTempString(float bmeTemp);
String generateHumString(float bmeHum);
String generatePresString(float bmePress);
void getWxModuleAddres();
void setup();
String generateTempString(const float bmeTemp);
String generateHumString(const float bmeHum);
String generatePresString(const float bmePress);
String readDataSensor();
}
+218
View File
@@ -0,0 +1,218 @@
#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) || defined(TTGO_T_LORA32_V2_1_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_WIRELESS_TRACKER) || 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
#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
#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
#ifdef ESP32_DIY_LoRa_A7670
#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
// 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) || defined(ESP32_DIY_LoRa_A7670) || defined(TTGO_T_LORA32_V2_1_915)
#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
#ifdef WEMOS_LOLIN32_OLED_DIY_LoRa
#define OLED_SDA 5
#define OLED_SCL 4
#define OLED_RST -1
#endif
#if !defined(HELTEC_HTCT62) && !defined(HELTEC_WSL_V3) && !defined(ESP32C3_DIY_1W_LoRa)
#define HAS_DISPLAY
#endif
// Leds and other stuff
#ifdef HELTEC_HTCT62
#define BATTERY_PIN 1
#endif
#if defined(TTGO_T_LORA32_V2_1) || defined(TTGO_T_LORA32_V2_1_915)
#define INTERNAL_LED_PIN 25 // Green Led
#define BATTERY_PIN 35 // es 35 el led y 1 bateria?
#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_WS)
#define INTERNAL_LED_PIN 35
#define BATTERY_PIN 1
#define VEXT_CTRL 36
#define ADC_CTRL 37 // Heltec WSL_V3 just like Heltec WT
#define BOARD_I2C_SDA 41
#define BOARD_I2C_SCL 42
#endif
#if defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
#define INTERNAL_LED_PIN 2
#endif
#if defined(ESP32_DIY_LoRa_A7670)
#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 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
#ifdef ESP32C3_DIY_1W_LoRa
#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
/* (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
+157 -126
View File
@@ -3,6 +3,7 @@
#include "configuration.h"
#include "display.h"
void Configuration::check() {
if (reload) {
show_display("------- UPDATE ------", "config is old", "device will update", "and then reboot", 1000);
@@ -16,81 +17,87 @@ void Configuration::check() {
void Configuration::writeFile() {
Serial.println("Saving config..");
StaticJsonDocument<1536> 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"]["powerOff"] = wifiAutoAP.powerOff;
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["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["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["bme"]["active"] = bme.active;
data["bme"]["active"] = bme.active;
data["bme"]["heightCorrection"] = bme.heightCorrection;
data["bme"]["temperatureCorrection"] = bme.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["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;
serializeJson(data, configFile);
@@ -105,7 +112,7 @@ bool Configuration::readFile() {
File configFile = SPIFFS.open("/igate_conf.json", "r");
if (configFile) {
StaticJsonDocument<1536> data;
StaticJsonDocument<2560> data;
DeserializationError error = deserializeJson(data, configFile);
if (error) {
@@ -126,9 +133,15 @@ bool Configuration::readFile() {
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>();
battery.sendInternalVoltage = data["battery"]["sendInternalVoltage"].as<bool>();
battery.monitorInternalVoltage = data["battery"]["monitorInternalVoltage"].as<bool>();
battery.internalSleepVoltage = data["battery"]["internalSleepVoltage"].as<float>();
battery.sendExternalVoltage = data["battery"]["sendExternalVoltage"].as<bool>();
battery.externalVoltagePin = data["battery"]["externalVoltagePin"].as<int>();
battery.monitorExternalVoltage = data["battery"]["monitorExternalVoltage"].as<bool>();
battery.externalSleepVoltage = data["battery"]["externalSleepVoltage"].as<float>();
aprs_is.passcode = data["aprs_is"]["passcode"].as<String>();
aprs_is.server = data["aprs_is"]["server"].as<String>();
@@ -148,11 +161,25 @@ bool Configuration::readFile() {
syslog.port = data["syslog"]["port"].as<int>();
bme.active = data["bme"]["active"].as<bool>();
bme.heightCorrection = data["bme"]["heightCorrection"].as<int>();
bme.temperatureCorrection = data["bme"]["temperatureCorrection"].as<float>();
ota.username = data["ota"]["username"].as<String>();
ota.password = data["ota"]["password"].as<String>();
int stationMode = data["stationMode"].as<int>(); // deprecated but need to specify config version
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>();
backupDigiMode = data["other"]["backupDigiMode"].as<bool>();
rebootMode = data["other"]["rebootMode"].as<bool>();
rebootModeTime = data["other"]["rebootModeTime"].as<int>();
int stationMode = data["stationMode"].as<int>(); // deprecated but need to specify config version
if (stationMode == 0) {
// Load new settings
@@ -163,8 +190,6 @@ bool Configuration::readFile() {
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>();
@@ -173,7 +198,8 @@ bool Configuration::readFile() {
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>();
aprs_is.messagesToRF = data["aprs_is"]["messagesToRF"].as<bool>();
aprs_is.objectsToRF = data["aprs_is"]["objectsToRF"].as<bool>();
loramodule.txFreq = data["lora"]["txFreq"].as<long>();
loramodule.rxFreq = data["lora"]["rxFreq"].as<long>();
@@ -184,8 +210,6 @@ bool Configuration::readFile() {
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>();
@@ -198,8 +222,7 @@ bool Configuration::readFile() {
beacon.latitude = digiLatitude;
beacon.longitude = digiLongitude;
beacon.interval = beaconInterval;
// beacon.igateSendsLoRaBeacons = igateSendsLoRaBeacons;
// beacon.igateRepeatsLoRaPackets = igateRepeatsLoRaPackets;
loramodule.txFreq = digirepeaterTxFreq;
loramodule.rxFreq = digirepeaterRxFreq;
loramodule.rxActive = true;
@@ -249,77 +272,85 @@ 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.powerOff = 15;
callsign = "N0CALL";
// stationMode = 1; // deprecated
// iGateComment = "LoRa_APRS_iGate Development"; // deprecated
callsign = "N0CALL";
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"; // new
beacon.latitude = 0.0; // new
beacon.longitude = 0.0; // new
beacon.interval = 15; // new
beacon.overlay = "L"; // new
beacon.symbol = "#"; // new
beacon.sendViaAPRSIS = true; // new
beacon.sendViaRF = false; // new
beacon.path = "WIDE1-1"; // new
digi.mode = 0; // new
// digi.comment = "LoRa_APRS_iGate Development"; // deprecated
// digi.latitude = 0.0; // deprecated
// digi.longitude = 0.0; // deprecated
digi.mode = 0;
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
tnc.enableServer = false;
tnc.enableSerial = false;
tnc.acceptOwn = 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
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.messagesToRF = false;
aprs_is.objectsToRF = false;
display.alwaysOn = true;
display.timeout = 4;
display.turn180 = false;
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
syslog.active = false;
syslog.server = "192.168.0.100";
syslog.port = 514;
display.alwaysOn = true;
display.timeout = 4;
display.turn180 = false;
bme.active = false;
syslog.active = false;
syslog.server = "192.168.0.100";
syslog.port = 514;
ota.username = "";
ota.password = "";
bme.active = false;
bme.heightCorrection = 0;
bme.temperatureCorrection = 0.0;
// beaconInterval = 15; // deprecated
// igateSendsLoRaBeacons = false; // deprecated
// igateRepeatsLoRaPackets = false; // deprecated
rememberStationTime = 30;
sendBatteryVoltage = false;
externalVoltageMeasurement = false;
externalVoltagePin = 34;
ota.username = "";
ota.password = "";
Serial.println("todo escrito");
rememberStationTime = 30;
battery.sendInternalVoltage = false;
battery.monitorInternalVoltage = false;
battery.internalSleepVoltage = 3.0;
battery.sendExternalVoltage = false;
battery.externalVoltagePin = 34;
battery.monitorExternalVoltage = false;
battery.externalSleepVoltage = 3.0;
lowPowerMode = false;
lowVoltageCutOff = 0;
backupDigiMode = false;
rebootMode = false;
rebootModeTime = 0;
Serial.println("All is Written!");
}
Configuration::Configuration() {
+66 -57
View File
@@ -9,8 +9,6 @@ class WiFi_AP {
public:
String ssid;
String password;
// double latitude; // deprecated
// double longitude; // deprecated
};
class WiFi_Auto_AP {
@@ -19,47 +17,42 @@ public:
int powerOff;
};
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;
};
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;
};
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,6 +66,24 @@ public:
bool turn180;
};
class BATTERY {
public:
bool sendInternalVoltage;
bool monitorInternalVoltage;
float internalSleepVoltage;
bool sendExternalVoltage;
int externalVoltagePin;
bool monitorExternalVoltage;
float externalSleepVoltage;
};
class BME {
public:
bool active;
int heightCorrection;
float temperatureCorrection;
};
class SYSLOG {
public:
bool active;
@@ -80,9 +91,11 @@ public:
int port;
};
class BME {
class TNC {
public:
bool active;
bool enableServer;
bool enableSerial;
bool acceptOwn;
};
class OTA {
@@ -91,32 +104,28 @@ public:
String password;
};
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;
std::vector<WiFi_AP> wifiAPs;
WiFi_Auto_AP wifiAutoAP;
Beacon beacon; // new
DIGI digi;
APRS_IS aprs_is;
LoraModule loramodule;
Display display;
SYSLOG syslog;
BME bme;
OTA ota;
bool reload; // ?
String callsign;
int rememberStationTime;
bool lowPowerMode;
double lowVoltageCutOff;
bool backupDigiMode;
bool rebootMode;
int rebootModeTime;
std::vector<WiFi_AP> wifiAPs;
WiFi_Auto_AP wifiAutoAP;
BEACON beacon;
APRS_IS aprs_is;
DIGI digi;
LoraModule loramodule;
Display display;
BATTERY battery;
BME bme;
SYSLOG syslog;
TNC tnc;
OTA ota;
void init();
void writeFile();
+46 -36
View File
@@ -2,7 +2,7 @@
#include "configuration.h"
#include "station_utils.h"
#include "aprs_is_utils.h"
#include "lora_utils.h"
#include "query_utils.h"
#include "digi_utils.h"
#include "wifi_utils.h"
#include "gps_utils.h"
@@ -19,26 +19,36 @@ 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(":"));
String generateDigiRepeatedPacket(const String& packet){
String temp0, path;
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 + "*");
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", Config.callsign + "*");
} else {
path.replace("WIDE1-" + hop , callsign + "*,WIDE1-" + String(hop.toInt()-1));
path.replace("WIDE1-" + hop, Config.callsign + "*,WIDE1-" + String(hop.toInt() - 1));
}
String repeatedPacket = sender + ">" + tocall + "," + path + packet.substring(packet.indexOf(":"));
String repeatedPacket = packet.substring(0, packet.indexOf(">")); // sender
repeatedPacket += ">";
repeatedPacket += temp0.substring(0, temp0.indexOf(",")); // tocall
repeatedPacket += ",";
repeatedPacket += path;
String payload = packet.substring(packet.indexOf(":"));
if (payload.indexOf("\x3c\xff\x01") != -1) {
payload = payload.substring(0, payload.indexOf("\x3c\xff\x01"));
}
repeatedPacket += payload;
return repeatedPacket;
} else {
return "";
@@ -51,34 +61,34 @@ namespace DIGI_Utils {
}
}
void processPacket(String packet) {
String loraPacket;
void processLoRaPacket(const String& packet) {
bool queryMessage = false;
String loraPacket, Sender, AddresseeAndMessage, Addressee;
if (packet != "") {
Serial.print("Received Lora Packet : " + String(packet));
if ((packet.substring(0, 3) == "\x3c\xff\x01") && (packet.indexOf("NOGATE") == -1)) {
Serial.println(" ---> APRS LoRa Packet");
String sender = packet.substring(3,packet.indexOf(">"));
STATION_Utils::updateLastHeard(sender);
STATION_Utils::updatePacketBuffer(packet);
Utils::typeOfPacket(packet.substring(3), "Digi");
if (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);
Serial.println(loraPacket);
LoRa_Utils::sendNewPacket("APRS", loraPacket);
display_toggle(true);
lastScreenOn = millis();
Sender = packet.substring(3, packet.indexOf(">"));
if (Sender != Config.callsign && Utils::checkValidCallsign(Sender)) {
if (STATION_Utils::check25SegBuffer(Sender, packet.substring(packet.indexOf(":") + 2))) {
STATION_Utils::updateLastHeard(Sender);
Utils::typeOfPacket(packet.substring(3), 2); // 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);
}
if (!queryMessage && packet.indexOf("WIDE1-") > 10 && (Config.digi.mode == 2 || backUpDigiMode)) { // If should repeat packet (WIDE1 Digi)
loraPacket = generateDigiRepeatedPacket(packet.substring(3));
if (loraPacket != "") {
STATION_Utils::addToOutputPacketBuffer(loraPacket);
display_toggle(true);
lastScreenOn = millis();
}
}
}
}
} else {
Serial.println(" ---> LoRa Packet Ignored (first 3 bytes or NOGATE)\n");
}
}
}
void loop(String packet) {
processPacket(packet);
}
}
+2 -3
View File
@@ -6,9 +6,8 @@
namespace DIGI_Utils {
String generateDigiRepeatedPacket(String packet, String callsign);
void processPacket(String packet);
void loop(String packet);
String generateDigiRepeatedPacket(const String& packet);
void processLoRaPacket(const String& packet);
}
+171 -145
View File
@@ -1,165 +1,191 @@
#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"
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#ifdef HAS_DISPLAY
#ifdef HAS_TFT
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
#ifdef HELTEC_WIRELESS_TRACKER
#define bigSizeFont 2
#define smallSizeFont 1
#define lineSpacing 9
#endif
#else
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#if defined(HELTEC_V3)
#define OLED_DISPLAY_HAS_RST_PIN
#endif
Adafruit_SSD1306 display(128, 64, &Wire, OLED_RST);
#endif
#endif
extern Configuration Config;
void setup_display() {
Wire.begin(OLED_SDA, OLED_SCL);
String oldHeader, oldFirstLine, oldSecondLine, oldThirdLine, oldFourthLine, oldFifthLine, oldSixthLine;
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 setup_display() {
#ifdef HAS_DISPLAY
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
#ifdef OLED_DISPLAY_HAS_RST_PIN
pinMode(OLED_RST, OUTPUT);
digitalWrite(OLED_RST, LOW);
delay(20);
digitalWrite(OLED_RST, HIGH);
#endif
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();
#endif
delay(1000);
#endif
}
void display_toggle(bool toggle) {
if (toggle) {
display.ssd1306_command(SSD1306_DISPLAYON);
#ifdef HAS_DISPLAY
if (toggle) {
#ifdef HAS_TFT
digitalWrite(TFT_BL, HIGH);
#else
display.ssd1306_command(SSD1306_DISPLAYON);
#endif
} else {
#ifdef HAS_TFT
digitalWrite(TFT_BL, LOW);
#else
display.ssd1306_command(SSD1306_DISPLAYOFF);
#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;
}
}
void show_display(String line1, int wait) {
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);
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 show_display(String line1, String line2, int wait) {
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);
void show_display(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
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
delay(wait);
#endif
}
void show_display(String line1, String line2, String line3, int wait) {
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);
}
void show_display(String line1, String line2, String line3, String line4, int wait) {
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);
}
void show_display(String line1, String line2, String line3, String line4, String line5, int wait) {
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);
}
void show_display(String line1, String line2, String line3, String line4, String line5, String line6, int wait) {
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);
}
void show_display(String line1, String line2, String line3, String line4, String line5, String line6, String line7, int wait) {
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);
void show_display(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
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
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
delay(wait);
#endif
}
+6 -10
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 setup_display();
void display_toggle(bool toggle);
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);
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(const String& header, const String& line1, const String& line2, const String& line3, int wait = 0);
void show_display(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
+85 -101
View File
@@ -2,114 +2,88 @@
#include <WiFi.h>
#include "configuration.h"
#include "gps_utils.h"
#include "display.h"
#include "utils.h"
extern Configuration Config;
extern WiFiClient espClient;
String distance;
String distance, iGateBeaconPacket, iGateLoRaBeaconPacket;
namespace GPS_Utils {
String double2string(double n, int ndec) {
String r = "";
if (n>-1 && n<0) {
r = "-";
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;
v /= 91;
}
return(s);
}
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;
aprs_lat = aprs_lat / 26 - aprs_lat / 2710 + aprs_lat / 15384615;
aprs_lon = 900000000 + longitude * 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(longitude < 0) { Ew = "W"; } else { Ew = "E"; }
if(longitude < 0) { longitude= -longitude; }
char helper_base91[] = {"0000\0"};
int i;
ax25_base91enc(helper_base91, 4, aprs_lat);
for (i = 0; i < 4; i++) {
encodedData += helper_base91[i];
}
ax25_base91enc(helper_base91, 4, aprs_lon);
for (i = 0; i < 4; i++) {
encodedData += helper_base91[i];
}
encodedData += symbol + " x" + "\x47";
return encodedData;
}
void generateBeacons() {
if (Config.callsign.indexOf("NOCALL-10") != 0 && !Utils::checkValidCallsign(Config.callsign)) {
show_display("***** ERROR ******", "CALLSIGN = NOT VALID!", " Use SSID 0-15", " Or Valid Callsign", 0);
while (true) {}
}
int v = n;
r += v;
r += '.';
for (int i=0;i<ndec;i++) {
n -= v;
n = 10 * abs(n);
v = n;
r += v;
String beaconPacket = Config.callsign;
beaconPacket += ">APLRG1";
if (Config.beacon.path.indexOf("WIDE") == 0) {
beaconPacket += ",";
beaconPacket += Config.beacon.path;
}
return r;
}
String processLatitudeAPRS(double lat) {
String degrees = double2string(lat,6);
String north_south, latitude, convDeg3;
float convDeg, convDeg2;
iGateBeaconPacket = beaconPacket;
iGateBeaconPacket += ",qAC:!";
iGateLoRaBeaconPacket = beaconPacket;
iGateLoRaBeaconPacket += ":!";
if (abs(degrees.toFloat()) < 10) {
latitude += "0";
}
Serial.println(latitude);
if (degrees.indexOf("-") == 0) {
north_south = "S";
latitude += degrees.substring(1,degrees.indexOf("."));
} else {
north_south = "N";
latitude += degrees.substring(0,degrees.indexOf("."));
}
convDeg = abs(degrees.toFloat()) - abs(int(degrees.toFloat()));
convDeg2 = (convDeg * 60)/100;
convDeg3 = String(convDeg2,6);
latitude += convDeg3.substring(convDeg3.indexOf(".")+1,convDeg3.indexOf(".")+3) + "." + convDeg3.substring(convDeg3.indexOf(".")+3,convDeg3.indexOf(".")+5);
latitude += north_south;
return latitude;
}
String processLongitudeAPRS(double lon) {
String degrees = double2string(lon,6);
String east_west, longitude, convDeg3;
float convDeg, convDeg2;
if (abs(degrees.toFloat()) < 100) {
longitude += "0";
}
if (abs(degrees.toFloat()) < 10) {
longitude += "0";
}
if (degrees.indexOf("-") == 0) {
east_west = "W";
longitude += degrees.substring(1,degrees.indexOf("."));
} else {
east_west = "E";
longitude += degrees.substring(0,degrees.indexOf("."));
}
convDeg = abs(degrees.toFloat()) - abs(int(degrees.toFloat()));
convDeg2 = (convDeg * 60)/100;
convDeg3 = String(convDeg2,6);
longitude += convDeg3.substring(convDeg3.indexOf(".")+1,convDeg3.indexOf(".")+3) + "." + convDeg3.substring(convDeg3.indexOf(".")+3,convDeg3.indexOf(".")+5);
longitude += east_west;
return longitude;
}
String generateBeacon() {
String stationLatitude = processLatitudeAPRS(Config.beacon.latitude);
String stationLongitude = processLongitudeAPRS(Config.beacon.longitude);
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";
} else {}
beaconPacket += ":=" + stationLatitude + Config.beacon.overlay + stationLongitude + Config.beacon.symbol;
beaconPacket += Config.beacon.comment;
return beaconPacket;
}
String generateiGateLoRaBeacon() {
String stationLatitude = processLatitudeAPRS(Config.beacon.latitude);
String stationLongitude = processLongitudeAPRS(Config.beacon.longitude);
String beaconPacket = Config.callsign + ">APLRG1," + Config.beacon.path + ":=" + stationLatitude + Config.beacon.overlay + stationLongitude + Config.beacon.symbol;
return beaconPacket;
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) {
String GPSPacket = packet.substring(packet.indexOf(":!")+3);
String encodedLatitude = GPSPacket.substring(0,4);
String encodedLongtitude = GPSPacket.substring(4,8);
String comment = GPSPacket.substring(12);
int Y1 = int(encodedLatitude[0]);
int Y2 = int(encodedLatitude[1]);
@@ -123,26 +97,32 @@ namespace GPS_Utils {
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";
if (comment != "") {
return String(decodedLatitude,5) + "N / " + String(decodedLongitude,5) + "E / " + distance + "km / " + comment;
} else {
return String(decodedLatitude,5) + "N / " + String(decodedLongitude,5) + "E / " + distance + "km";
}
}
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);
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 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);
String thirdLngPart = Longitude.substring(Longitude.indexOf(".") + 1, Longitude.indexOf(".") + 3);
convertedLatitude = firstLatPart.toFloat() + (secondLatPart.toFloat()/60) + (thirdLatPart.toFloat()/(60*100));
convertedLongitude = firstLngPart.toFloat() + (secondLngPart.toFloat()/60) + (thirdLngPart.toFloat()/(60*100));
@@ -155,11 +135,15 @@ namespace GPS_Utils {
convertedLongitude = -convertedLongitude;
}
distance = String(calculateDistanceTo(convertedLatitude, convertedLongitude),1);
return String(convertedLatitude,5) + "N / " + String(convertedLongitude,5) + "E / " + distance + "km";
}
if (comment != "") {
return String(convertedLatitude,5) + "N / " + String(convertedLongitude,5) + "E / " + distance + "km / " + comment;
} else {
return String(convertedLatitude,5) + "N / " + String(convertedLongitude,5) + "E / " + distance + "km";
}
}
String getDistance(String packet) {
int encodedBytePosition = 0;
String getDistanceAndComment(const String& packet) {
uint8_t encodedBytePosition = 0;
if (packet.indexOf(":!") > 10) {
encodedBytePosition = packet.indexOf(":!") + 14;
}
+8 -9
View File
@@ -6,15 +6,14 @@
namespace GPS_Utils {
String double2string(double n, int ndec);
String processLatitudeAPRS();
String processLongitudeAPRS();
String generateBeacon();
String generateiGateLoRaBeacon();
double calculateDistanceCourse(double latitude, double longitude);
String decodeEncodedGPS(String packet);
String getReceivedGPS(String packet);
String getDistance(String packet);
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 generateBeacons();
double calculateDistanceCourse(double latitude, double longitude);
String decodeEncodedGPS(const String& packet);
String getReceivedGPS(const String& packet);
String getDistanceAndComment(const String& packet);
}
+23
View File
@@ -0,0 +1,23 @@
#define DCD_ON 0x03
#define FEND 0xC0
#define FESC 0xDB
#define TFEND 0xDC
#define TFESC 0xDD
#define CMD_UNKNOWN 0xFE
#define CMD_DATA 0x00
#define CMD_HARDWARE 0x06
#define HW_RSSI 0x21
#define CMD_ERROR 0x90
#define ERROR_INITRADIO 0x01
#define ERROR_TXFAILED 0x02
#define ERROR_QUEUE_FULL 0x04
#define APRS_CONTROL_FIELD 0x03
#define APRS_INFORMATION_FIELD 0xf0
#define HAS_BEEN_DIGIPITED_MASK 0b10000000
#define IS_LAST_ADDRESS_POSITION_MASK 0b1
+170
View File
@@ -0,0 +1,170 @@
#include <Arduino.h>
#include "kiss_protocol.h"
bool validateTNC2Frame(const String& tnc2FormattedFrame) {
return (tnc2FormattedFrame.indexOf(':') != -1) && (tnc2FormattedFrame.indexOf('>') != -1);
}
bool validateKISSFrame(const String& kissFormattedFrame) {
return kissFormattedFrame.charAt(0) == (char)FEND && kissFormattedFrame.charAt(kissFormattedFrame.length() - 1) == (char)FEND;
}
String encodeAddressAX25(String tnc2Address) {
bool hasBeenDigipited = tnc2Address.indexOf('*') != -1;
if (tnc2Address.indexOf('-') == -1) {
if (hasBeenDigipited) {
tnc2Address = tnc2Address.substring(0, tnc2Address.length() - 1);
}
tnc2Address += "-0";
}
int separatorIndex = tnc2Address.indexOf('-');
int ssid = tnc2Address.substring(separatorIndex + 1).toInt();
String kissAddress = "";
for (int i = 0; i < 6; ++i) {
char addressChar;
if (tnc2Address.length() > i && i < separatorIndex) {
addressChar = tnc2Address.charAt(i);
} else {
addressChar = ' ';
}
kissAddress += (char)(addressChar << 1);
}
kissAddress += (char)((ssid << 1) | 0b01100000 | (hasBeenDigipited ? HAS_BEEN_DIGIPITED_MASK : 0));
return kissAddress;
}
String decodeAddressAX25(const String& ax25Address, bool& isLast, bool isRelay) {
String address = "";
for (int i = 0; i < 6; ++i) {
uint8_t currentCharacter = ax25Address.charAt(i);
currentCharacter >>= 1;
if (currentCharacter != ' ') {
address += (char)currentCharacter;
}
}
auto ssidChar = (uint8_t)ax25Address.charAt(6);
bool hasBeenDigipited = ssidChar & HAS_BEEN_DIGIPITED_MASK;
isLast = ssidChar & IS_LAST_ADDRESS_POSITION_MASK;
ssidChar >>= 1;
int ssid = 0b1111 & ssidChar;
if (ssid) {
address += '-';
address += ssid;
}
if (isRelay && hasBeenDigipited) {
address += '*';
}
return address;
}
String encapsulateKISS(const String& ax25Frame, uint8_t cmd) {
String kissFrame = "";
kissFrame += (char)FEND;
kissFrame += (char)(0x0f & cmd);
for (int i = 0; i < ax25Frame.length(); ++i) {
char currentChar = ax25Frame.charAt(i);
if (currentChar == (char)FEND) {
kissFrame += (char)FESC;
kissFrame += (char)TFEND;
} else if (currentChar == (char)FESC) {
kissFrame += (char)FESC;
kissFrame += (char)TFESC;
} else {
kissFrame += currentChar;
}
}
kissFrame += (char)FEND; // end of frame
return kissFrame;
}
String decapsulateKISS(const String& frame) {
String ax25Frame = "";
for (int i = 2; i < frame.length() - 1; ++i) {
char currentChar = frame.charAt(i);
if (currentChar == (char)FESC) {
char nextChar = frame.charAt(i + 1);
if (nextChar == (char)TFEND) {
ax25Frame += (char)FEND;
} else if (nextChar == (char)TFESC) {
ax25Frame += (char)FESC;
}
i++;
} else {
ax25Frame += currentChar;
}
}
return ax25Frame;
}
String encodeKISS(const String& frame) {
String ax25Frame = "";
if (validateTNC2Frame(frame)) {
String address = "";
bool dstAddresWritten = false;
for (int p = 0; p <= frame.indexOf(':'); p++) {
char currentChar = frame.charAt(p);
if (currentChar == ':' || currentChar == '>' || currentChar == ',') {
if (!dstAddresWritten && (currentChar == ',' || currentChar == ':')) {
ax25Frame = encodeAddressAX25(address) + ax25Frame;
dstAddresWritten = true;
} else {
ax25Frame += encodeAddressAX25(address);
}
address = "";
} else {
address += currentChar;
}
}
auto lastAddressChar = (uint8_t)ax25Frame.charAt(ax25Frame.length() - 1);
ax25Frame.setCharAt(ax25Frame.length() - 1, (char)(lastAddressChar | IS_LAST_ADDRESS_POSITION_MASK));
ax25Frame += (char)APRS_CONTROL_FIELD;
ax25Frame += (char)APRS_INFORMATION_FIELD;
ax25Frame += frame.substring(frame.indexOf(':') + 1);
}
String kissFrame = encapsulateKISS(ax25Frame, CMD_DATA);
return kissFrame;
}
String decodeKISS(const String& inputFrame, bool& dataFrame) {
String frame = "";
if (validateKISSFrame(inputFrame)) {
dataFrame = inputFrame.charAt(1) == CMD_DATA;
if (dataFrame) {
String ax25Frame = decapsulateKISS(inputFrame);
bool isLast = false;
String dstAddr = decodeAddressAX25(ax25Frame.substring(0, 7), isLast, false);
String srcAddr = decodeAddressAX25(ax25Frame.substring(7, 14), isLast, false);
frame = srcAddr + ">" + dstAddr;
int digiInfoIndex = 14;
while (!isLast && digiInfoIndex + 7 < ax25Frame.length()) {
String digiAddr = decodeAddressAX25(ax25Frame.substring(digiInfoIndex, digiInfoIndex + 7), isLast, true);
frame += ',' + digiAddr;
digiInfoIndex += 7;
}
frame += ':';
frame += ax25Frame.substring(digiInfoIndex + 2);
} else {
frame += inputFrame;
}
}
return frame;
}
+15
View File
@@ -0,0 +1,15 @@
#ifndef KISS_UTILS_H_
#define KISS_UTILS_H_
#include <Arduino.h>
String encodeAddressAX25(String tnc2Address);
String decodeAddressAX25(const String& ax25Address, bool& isLast, bool isRelay);
String encapsulateKISS(const String& ax25Frame, uint8_t cmd);
String decapsulateKISS(const String& frame);
String encodeKISS(const String& frame);
String decodeKISS(const String& inputFrame, bool& dataFrame);
#endif
+153 -166
View File
@@ -1,229 +1,216 @@
#include <RadioLib.h>
#include <LoRa.h>
#include <WiFi.h>
#include "configuration.h"
#include "aprs_is_utils.h"
#include "boards_pinout.h"
#include "syslog_utils.h"
#include "pins_config.h"
#include "display.h"
#include "utils.h"
extern Configuration Config;
extern Configuration Config;
extern uint32_t lastRxTime;
#if defined(HELTEC_V3) || defined(TTGO_T_Beam_V1_2_SX1262)
SX1262 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN);
bool transmissionFlag = true;
bool enableInterrupt = true;
extern std::vector<ReceivedPacket> receivedPackets;
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);
#endif
#if defined(ESP32_DIY_1W_LoRa) || defined(TTGO_T_Beam_V1_0_SX1268)
SX1268 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN);
bool transmissionFlag = true;
bool enableInterrupt = true;
#ifdef HAS_SX1268
SX1268 radio = new Module(RADIO_CS_PIN, RADIO_DIO1_PIN, RADIO_RST_PIN, RADIO_BUSY_PIN);
#endif
#ifdef HAS_SX1278
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
int rssi, freqError;
float snr;
namespace LoRa_Utils {
void setFlag(void) {
#ifdef HAS_SX126X
transmissionFlag = true;
#endif
operationDone = true;
}
void setup() {
#ifdef HAS_SX127X
SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
LoRa.setPins(LORA_CS, LORA_RST, LORA_IRQ);
long freq = Config.loramodule.rxFreq;
if (!LoRa.begin(freq)) {
Serial.println("Starting LoRa failed!");
show_display("ERROR", "Starting LoRa failed!");
while (true) {
delay(1000);
}
}
LoRa.setSpreadingFactor(Config.loramodule.spreadingFactor);
LoRa.setSignalBandwidth(Config.loramodule.signalBandwidth);
LoRa.setCodingRate4(Config.loramodule.codingRate4);
LoRa.enableCrc();
LoRa.setTxPower(Config.loramodule.power);
Serial.print("init : LoRa Module ... done!");
#endif
#ifdef HAS_SX126X
SPI.begin(RADIO_SCLK_PIN, RADIO_MISO_PIN, RADIO_MOSI_PIN);
float freq = (float)Config.loramodule.rxFreq/1000000;
float freq = (float)Config.loramodule.rxFreq / 1000000;
int state = radio.begin(freq);
if (state == RADIOLIB_ERR_NONE) {
Serial.print("Initializing SX126X LoRa Module");
Utils::println("Initializing LoRa Module");
} else {
Serial.println("Starting LoRa failed!");
while (true);
}
radio.setDio1Action(setFlag);
radio.setSpreadingFactor(Config.loramodule.spreadingFactor);
radio.setBandwidth(Config.loramodule.signalBandwidth);
radio.setCodingRate(Config.loramodule.codingRate4);
radio.setCRC(true);
#if defined(ESP32_DIY_1W_LoRa)
radio.setRfSwitchPins(RADIO_RXEN, RADIO_TXEN);
#endif
#if defined(HELTEC_V3) || 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.
#endif
#ifdef ESP32_DIY_1W_LoRa_GPS
state = radio.setOutputPower(Config.loramodule.power); // max value 20 (when 20dB in setup 30dB in output as 400M30S has Low Noise Amp)
#endif
if (state == RADIOLIB_ERR_NONE) {
Serial.println("init : LoRa Module ... done!");
} else {
Serial.println("Starting LoRa failed!");
Utils::println("Starting LoRa failed!");
while (true);
}
#if defined(HAS_SX1262) || defined(HAS_SX1268)
if (!Config.lowPowerMode) {
radio.setDio1Action(setFlag);
} else {
radio.setDIOMapping(1, RADIOLIB_SX126X_IRQ_RX_DONE);
}
#endif
#if defined(HAS_SX1278) || defined(HAS_SX1276)
radio.setDio0Action(setFlag, RISING);
#endif
radio.setSpreadingFactor(Config.loramodule.spreadingFactor);
float signalBandwidth = Config.loramodule.signalBandwidth/1000;
radio.setBandwidth(signalBandwidth);
radio.setCodingRate(Config.loramodule.codingRate4);
radio.setCRC(true);
#if defined(RADIO_RXEN) && defined(RADIO_TXEN)
radio.setRfSwitchPins(RADIO_RXEN, RADIO_TXEN);
#endif
#if defined(ESP32_DIY_1W_LoRa) || defined(OE5HWN_MeshCom) || defined(ESP32C3_DIY_1W_LoRa)
state = radio.setOutputPower(Config.loramodule.power); // max value 20dB for 400M30S as it has 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(HELTEC_V3) || defined(HELTEC_WSL_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.
radio.setCurrentLimit(140);
#endif
#if defined(HAS_SX1262) || defined(HAS_SX1268)
radio.setRxBoostedGainMode(true);
#endif
if (state == RADIOLIB_ERR_NONE) {
Utils::println("init : LoRa Module ... done!");
} else {
Utils::println("Starting LoRa failed!");
while (true);
}
}
void changeFreqTx() {
delay(500);
#ifdef HAS_SX127X
LoRa.setFrequency(Config.loramodule.txFreq);
#endif
#ifdef HAS_SX126X
float freq = (float)Config.loramodule.txFreq/1000000;
float freq = (float)Config.loramodule.txFreq / 1000000;
radio.setFrequency(freq);
#endif
}
void changeFreqRx() {
delay(500);
#ifdef HAS_SX127X
LoRa.setFrequency(Config.loramodule.rxFreq);
#endif
#ifdef HAS_SX126X
float freq = (float)Config.loramodule.rxFreq/1000000;
float freq = (float)Config.loramodule.rxFreq / 1000000;
radio.setFrequency(freq);
#endif
}
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();
changeFreqTx();
}
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
digitalWrite(internalLedPin,HIGH);
#ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN, HIGH);
#endif
#ifdef HAS_SX127X
LoRa.beginPacket();
LoRa.write('<');
if (typeOfMessage == "APRS") {
LoRa.write(0xFF);
} else if (typeOfMessage == "LoRa") {
LoRa.write(0xF8);
}
LoRa.write(0x01);
LoRa.write((const uint8_t *)newPacket.c_str(), newPacket.length());
LoRa.endPacket();
#endif
#ifdef HAS_SX126X
int state = radio.transmit("\x3c\xff\x01" + newPacket);
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE) {
//Serial.println(F("success!"));
} else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) {
Serial.println(F("too long!"));
} else if (state == RADIOLIB_ERR_TX_TIMEOUT) {
Serial.println(F("timeout!"));
if (Config.syslog.active && WiFi.status() == WL_CONNECTED) {
SYSLOG_Utils::log(3, newPacket, 0, 0.0, 0); // TX
}
Utils::print("---> LoRa Packet Tx : ");
Utils::println(newPacket);
} else {
Serial.print(F("failed, code "));
Serial.println(state);
Utils::print(F("failed, code "));
Utils::println(String(state));
}
#ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN, LOW);
#endif
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
digitalWrite(internalLedPin,LOW);
#endif
SYSLOG_Utils::log("Tx", newPacket,0,0,0);
Serial.print("---> LoRa Packet Tx : ");
Serial.println(newPacket);
if (Config.loramodule.txFreq != Config.loramodule.rxFreq) {
changeFreqRx();
}
}
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(const String& packet) {
String sanitizedPacket = packet;
if (packet.indexOf("\0") > 0) {
sanitizedPacket.replace("\0", "");
}
if (packet.indexOf("\r") > 0) {
sanitizedPacket.replace("\r", "");
}
if (packet.indexOf("\n") > 0) {
sanitizedPacket.replace("\n", "");
}
return sanitizedPacket;
}*/
void startReceive() {
radio.startReceive();
}
String packetSanitization(String packet) {
Serial.println(packet);
if (packet.indexOf("\0")>0) {
packet.replace("\0","");
}
if (packet.indexOf("\r")>0) {
packet.replace("\r","");
}
if (packet.indexOf("\n")>0) {
packet.replace("\n","");
String receivePacket() {
String packet = "";
if (operationDone) {
operationDone = false;
if (transmitFlag) {
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) + ")");
if (!Config.lowPowerMode) {
ReceivedPacket receivedPacket;
receivedPacket.millis = millis();
receivedPacket.packet = packet.substring(3);
receivedPacket.RSSI = rssi;
receivedPacket.SNR = snr;
if (receivedPackets.size() >= 20) {
receivedPackets.erase(receivedPackets.begin());
}
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(0, packet, rssi, snr, freqError); // CRC
}
packet = "";
} else {
Utils::print(F("failed, code "));
Utils::println(String(state));
packet = "";
}
}
}
return packet;
}
String receivePacket() {
String loraPacket = "";
#ifdef HAS_SX127X
int packetSize = LoRa.parsePacket();
if (packetSize) {
while (LoRa.available()) {
int inChar = LoRa.read();
loraPacket += (char)inChar;
}
rssi = LoRa.packetRssi();
snr = LoRa.packetSnr();
freqError = LoRa.packetFrequencyError();
}
#endif
#ifdef HAS_SX126X
if (transmissionFlag) {
transmissionFlag = false;
radio.startReceive();
int state = radio.readData(loraPacket);
if (state == RADIOLIB_ERR_NONE) {
Serial.println("LoRa Rx ---> " + loraPacket);
rssi = radio.getRSSI();
snr = radio.getSNR();
freqError = radio.getFrequencyError();
} else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
// timeout occurred while waiting for a packet
} else if (state == RADIOLIB_ERR_CRC_MISMATCH) {
Serial.println(F("CRC error!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
}
}
#endif
if ((loraPacket.indexOf("\0")!=-1) || (loraPacket.indexOf("\r")!=-1) || (loraPacket.indexOf("\n")!=-1)) {
loraPacket = packetSanitization(loraPacket);
}
#ifndef TextSerialOutputForApp
if (loraPacket!="") {
Serial.println("(RSSI:" +String(rssi) + " / SNR:" + String(snr) + " / FreqErr:" + String(freqError) + ")");
}
#endif
if (Config.syslog.active && WiFi.status() == WL_CONNECTED && loraPacket != "") {
SYSLOG_Utils::log("Rx", loraPacket, rssi, snr, freqError);
}
return loraPacket;
void sleepRadio() {
radio.sleep();
}
}
+8 -7
View File
@@ -6,13 +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 setup();
void sendNewPacket(const String& newPacket);
//String packetSanitization(const String& packet);
String receivePacket();
void changeFreqTx();
void changeFreqRx();
void startReceive(); // ???
void sleepRadio();
}
-118
View File
@@ -1,118 +0,0 @@
#ifndef PINS_CONFIG_H_
#define PINS_CONFIG_H_
#include <Arduino.h>
#undef OLED_SDA
#undef OLED_SCL
#undef OLED_RST
#if defined(HELTEC_V3) || defined(ESP32_DIY_1W_LoRa) || defined(TTGO_T_Beam_V1_0_SX1268) || defined(TTGO_T_Beam_V1_2_SX1262)
#define HAS_SX126X
#endif
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(ESP32_DIY_LoRa) || defined(TTGO_T_Beam_V1_0) || defined(TTGO_T_Beam_V1_2)
#define HAS_SX127X
#endif
#if defined(TTGO_T_Beam_V1_0) || defined(TTGO_T_Beam_V1_0_SX1268)
#define HAS_AXP192
#endif
#if defined(TTGO_T_Beam_V1_2) || defined(TTGO_T_Beam_V1_2_SX1262)
#define HAS_AXP2101
#endif
// LORA MODULES
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(ESP32_DIY_LoRa)
#undef LORA_RST
#define LORA_SCK 5 // GPIO5 - SX1276 SCK
#define LORA_MISO 19 // GPIO19 - SX1276 MISO
#define LORA_MOSI 27 // GPIO27 - SX1276 MOSI
#define LORA_CS 18 // GPIO18 - SX1276 CS ---> NSS
#define LORA_RST 14 // GPIO14 - SX1276 RST
#define LORA_IRQ 26 // GPIO26 - SX1276 IRQ ---->DIO0
#endif
#ifdef HELTEC_V3
#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
// 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)
#define OLED_SDA 21
#define OLED_SCL 22
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#endif
#ifdef HELTEC_V2
#define OLED_SDA 4
#define OLED_SCL 15
#define OLED_RESET 16
#endif
#ifdef HELTEC_V3
#define OLED_SDA 17
#define OLED_SCL 18
#define OLED_RESET 21
#endif
// Leds and other stuff
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2)
#define internalLedPin 25 // Green Led
#define batteryPin 35
#endif
#ifdef HELTEC_V3
#define internalLedPin 35
#endif
#if defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
#define internalLedPin 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
+124 -78
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,156 @@ 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 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
#endif
#ifdef ADC_CTRL
pinMode(ADC_CTRL, OUTPUT);
#endif
#ifdef HELTEC_WIRELESS_TRACKER
Wire.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif
#ifdef HELTEC_V3
Wire1.begin(BOARD_I2C_SDA, BOARD_I2C_SCL);
#endif
delay(1000);
BATTERY_Utils::startupBatteryHealth();
}
}
+12 -6
View File
@@ -2,16 +2,22 @@
#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 activateLoRa();
void deactivateLoRa();
bool begin(TwoWire &port);
void setup();
}
+30 -12
View File
@@ -1,47 +1,65 @@
#include "configuration.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 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, const uint8_t queryOrigin) {
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;
answer = "CA2RXU_LoRa_iGate 1.3 v";
answer.concat(versionDate);
} else if (query=="?APRSP" || query=="?aprsp" || query=="?Aprsp") {
answer = "iGate QTH: " + String(Config.beacon.latitude,2) + " " + String(Config.beacon.longitude,2);
answer = "iGate QTH: ";
answer.concat(String(Config.beacon.latitude,2));
answer.concat(" ");
answer.concat(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.";
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(",")) + " ";
}
answer.trim();
}
} else if (query=="?APRSSR" || query=="?aprssr" || query=="?Aprssr") {
char signalData[35];
snprintf(signalData, sizeof(signalData), " %ddBm / %.2fdB / %dHz", rssi, snr, freqError);
answer.concat(signalData);
} else if (query.indexOf("?APRSH") == 0 || query.indexOf("?aprsh") == 0 || query.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!";
answer = "?APRSH on development 73!";
} else if (query.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!";
}
for(int i = station.length(); i < 9; i++) {
station += ' ';
String processedStation = station;
for (int i = station.length(); i < 9; i++) {
processedStation += ' ';
}
if (queryOrigin == "APRSIS") {
return Config.callsign + ">APLRG1,TCPIP,qAC::" + station + ":" + answer;// + "\n";
} else { //} if (queryOrigin == "LoRa") {
return Config.callsign + ">APLRG1,RFONLY,WIDE1-1::" + station + ":" + answer;
if (queryOrigin == 1) { // from APRS-IS
return Config.callsign + ">APLRG1,TCPIP,qAC::" + processedStation + ":" + answer;
} else { // else == 0 , from LoRa
if (Config.beacon.path == "") {
return Config.callsign + ">APLRG1,RFONLY::" + processedStation + ":" + answer;
} else {
return Config.callsign + ">APLRG1,RFONLY," + Config.beacon.path + "::" + processedStation + ":" + answer;
}
}
}
+1 -1
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, const uint8_t queryOrigin);
}
+67 -54
View File
@@ -1,38 +1,43 @@
#include "station_utils.h"
#include "aprs_is_utils.h"
#include "configuration.h"
#include "lora_utils.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;
uint32_t lastTxTime = millis();
std::vector<String> lastHeardStation;
std::vector<String> outputPacketBuffer;
std::vector<String> packet25SegBuffer;
namespace STATION_Utils {
void deleteNotHeard() {
for (int i=0; i<lastHeardStation.size(); i++) {
String deltaTimeString = lastHeardStation[i].substring(lastHeardStation[i].indexOf(",")+1);
std::vector<String> lastHeardStation_temp;
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) {
if ((millis() - deltaTime) < Config.rememberStationTime * 60 * 1000) {
lastHeardStation_temp.push_back(lastHeardStation[i]);
}
}
lastHeardStation.clear();
for (int j=0; j<lastHeardStation_temp.size(); j++) {
for (int j = 0; j < lastHeardStation_temp.size(); j++) {
lastHeardStation.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) {
for (int i = 0; i < lastHeardStation.size(); i++) {
if (lastHeardStation[i].substring(0, lastHeardStation[i].indexOf(",")) == station) {
lastHeardStation[i] = station + "," + String(millis());
stationHeard = true;
}
@@ -41,65 +46,73 @@ namespace STATION_Utils {
lastHeardStation.push_back(station + "," + String(millis()));
}
fourthLine = "Stations (" + String(Config.rememberStationTime) + "min) = ";
fourthLine = "Stations (";
fourthLine += String(Config.rememberStationTime);
fourthLine += "min) = ";
if (lastHeardStation.size() < 10) {
fourthLine += " ";
}
fourthLine += String(lastHeardStation.size());
#ifndef TextSerialOutputForApp ////// This is just for debugging
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("");
#endif
}
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) {
Serial.println(" ---> Listened Station");
for (int i = 0; i < lastHeardStation.size(); i++) {
if (lastHeardStation[i].substring(0, lastHeardStation[i].indexOf(",")) == station) {
Utils::println(" ---> Listened Station");
return true;
}
}
}
Serial.println(" ---> Station not Heard for last 30 min (Not Tx)\n");
Utils::println(" ---> Station not Heard for last 30 min (Not Tx)\n");
return false;
}
void checkBuffer() {
for (int i=0; i<packetBuffer.size(); i++) {
String deltaTimeString = packetBuffer[i].substring(0,packetBuffer[i].indexOf(","));
void clean25SegBuffer() {
if (!packet25SegBuffer.empty()) {
String deltaTimeString = packet25SegBuffer[0].substring(0, packet25SegBuffer[0].indexOf(","));
uint32_t deltaTime = deltaTimeString.toInt();
if ((millis() - deltaTime) < 60*1000) { // cambiar a 15 segundos?
packetBuffer_temp.push_back(packetBuffer[i]);
if ((millis() - deltaTime) > 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();
// BORRAR ESTO !!
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) {
if (!packet25SegBuffer.empty()) {
bool shouldBeIgnored = false;
for (int i = 0; i < packet25SegBuffer.size(); i++) {
String temp = packet25SegBuffer[i].substring(packet25SegBuffer[i].indexOf(",") + 1);
String bufferStation = temp.substring(0, temp.indexOf(","));
String bufferMessage = temp.substring(temp.indexOf(",") + 1);
if (bufferStation == station && bufferMessage == textMessage) {
shouldBeIgnored = true;
}
}
if (shouldBeIgnored) {
return false;
} else {
packet25SegBuffer.push_back(String(millis()) + "," + station + "," + textMessage);
return true;
}
} else {
packet25SegBuffer.push_back(String(millis()) + "," + station + "," + textMessage);
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;
if (outputPacketBuffer.size() > 0 && lastTx > timeToWait && lastRx > timeToWait) {
LoRa_Utils::sendNewPacket(outputPacketBuffer[0]);
outputPacketBuffer.erase(outputPacketBuffer.begin());
lastTxTime = millis();
}
}
void addToOutputPacketBuffer(const String& packet) {
outputPacketBuffer.push_back(packet);
}
}
+6 -4
View File
@@ -7,10 +7,12 @@
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);
}
+89 -44
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.2" + " - - - "; //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());
+1 -1
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();
}
+144
View File
@@ -0,0 +1,144 @@
#include <WiFi.h>
#include "kiss_utils.h"
#include "kiss_protocol.h"
#include "configuration.h"
#include "station_utils.h"
#include "utils.h"
extern Configuration Config;
#define MAX_CLIENTS 4
#define INPUT_BUFFER_SIZE (2 + MAX_CLIENTS)
#define TNC_PORT 8001
WiFiClient* clients[MAX_CLIENTS];
WiFiServer tncServer(TNC_PORT);
String inputServerBuffer[INPUT_BUFFER_SIZE];
String inputSerialBuffer = "";
namespace TNC_Utils {
void setup() {
if (Config.tnc.enableServer) {
tncServer.stop();
tncServer.begin();
}
}
void checkNewClients() {
WiFiClient new_client = tncServer.available();
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;
}
}
}
}
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;
}
data->concat(character);
if (character == (char)FEND && data->length() > 3) {
bool isDataFrame = false;
const String& frame = decodeKISS(*data, isDataFrame);
if (isDataFrame) {
if (bufferIndex != -1) {
Utils::print("<--- Got from TNC : ");
Utils::println(frame);
}
String sender = frame.substring(0,frame.indexOf(">"));
if (Config.tnc.acceptOwn || sender != Config.callsign) {
STATION_Utils::addToOutputPacketBuffer(frame);
} else {
Utils::println("Ignored own frame from KISS");
}
}
data->clear();
}
if (data->length() > 255) {
data->clear();
}
}
void readFromClients() {
for (int i = 0; i < MAX_CLIENTS; i++) {
auto client = clients[i];
if (client != nullptr) {
if (client->connected()) {
while (client->available() > 0) {
char character = client->read();
handleInputData(character, 2 + i);
}
} else {
delete client;
clients[i] = nullptr;
}
}
}
}
void readFromSerial() {
while (Serial.available() > 0) {
char character = Serial.read();
handleInputData(character, -1);
}
}
void sendToClients(const String& packet) {
String cleanPacket = packet.substring(3);
const String kissEncoded = encodeKISS(cleanPacket);
for (int i = 0; i < MAX_CLIENTS; i++) {
auto client = clients[i];
if (client != nullptr) {
if (client->connected()) {
client->print(kissEncoded);
client->flush();
} else {
delete client;
clients[i] = nullptr;
}
}
}
Utils::print("---> Sent to TNC : ");
Utils::println(cleanPacket);
}
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();
}
}
}
+16
View File
@@ -0,0 +1,16 @@
#ifndef TNC_UTILS_H_
#define TNC_UTILS_H_
#include <Arduino.h>
namespace TNC_Utils {
void setup();
void loop();
void sendToClients(const String& packet);
void sendToSerial(const String& packet);
}
#endif
+236 -107
View File
@@ -3,19 +3,19 @@
#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 "display.h"
#include "utils.h"
extern WiFiClient espClient;
extern Configuration Config;
extern WiFiClient espClient;
extern String versionDate;
extern bool statusAfterBoot;
extern String firstLine;
extern String secondLine;
extern String thirdLine;
@@ -23,9 +23,6 @@ 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;
@@ -33,35 +30,49 @@ 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;
bool statusAfterBoot = true;
bool beaconUpdate = true;
uint32_t lastBeaconTx = 0;
uint32_t lastScreenOn = millis();
namespace Utils {
void processStatus() {
String status = Config.callsign + ">APLRG1," + Config.beacon.path;
if (Config.aprs_is.active && Config.digi.mode == 0) { // If only IGate
delay(1000);
status += ",qAC:>https://github.com/richonguzman/LoRa_APRS_iGate " + versionDate;
APRS_IS_Utils::upload(status);
SYSLOG_Utils::log("APRSIS Tx", status,0,0,0);
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.concat(",qAC:>https://github.com/richonguzman/LoRa_APRS_iGate ");
status.concat(versionDate);
APRS_IS_Utils::upload(status);
SYSLOG_Utils::log(2, status, 0, 0.0, 0); // APRSIS TX
statusAfterBoot = false;
}
if (statusAfterBoot && !Config.beacon.sendViaAPRSIS && Config.beacon.sendViaRF) {
delay(2000);
status.concat(":>https://github.com/richonguzman/LoRa_APRS_iGate ");
status.concat(versionDate);
STATION_Utils::addToOutputPacketBuffer(status);
statusAfterBoot = false;
}
// Comment this for now we will need this in the future
// } else if (Config.digi.mode == 2) {
// delay(5000);
// status += ":>https://github.com/richonguzman/LoRa_APRS_iGate " + versionDate;
// LoRa_Utils::sendNewPacket("APRS", status);
// }
statusAfterBoot = false;
}
String getLocalIP() {
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]);
}
@@ -69,76 +80,112 @@ namespace Utils {
void setupDisplay() {
setup_display();
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
digitalWrite(internalLedPin,HIGH);
#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);
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
digitalWrite(internalLedPin,LOW);
#ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN,LOW);
#endif
firstLine = Config.callsign;
seventhLine = " listening...";
}
void activeStations() {
fourthLine = "Stations (" + String(Config.rememberStationTime) + "min) = ";
fourthLine = "Stations (";
fourthLine.concat(String(Config.rememberStationTime));
fourthLine.concat("min) = ");
if (lastHeardStation.size() < 10) {
fourthLine += " ";
}
fourthLine += String(lastHeardStation.size());
fourthLine.concat(String(lastHeardStation.size()));
}
void checkBeaconInterval() {
uint32_t lastTx = millis() - lastBeaconTx;
String beaconPacket, secondaryBeaconPacket;
String beaconPacket = iGateBeaconPacket;
String secondaryBeaconPacket = iGateLoRaBeaconPacket;
if (lastTx >= Config.beacon.interval*60*1000) {
if (lastBeaconTx == 0 || lastTx >= Config.beacon.interval * 60 * 1000) {
beaconUpdate = true;
}
if (beaconUpdate) {
display_toggle(true);
Serial.println("-- Sending Beacon to APRSIS --");
if (!Config.display.alwaysOn && Config.display.timeout != 0) {
display_toggle(true);
}
Utils::println("-- Sending Beacon to APRSIS --");
STATION_Utils::deleteNotHeard();
activeStations();
if (Config.bme.active) {
if (Config.bme.active && wxModuleType != 0) {
String sensorData = BME_Utils::readDataSensor();
beaconPacket = iGateBeaconPacket.substring(0,iGateBeaconPacket.indexOf(":=")+20) + "_" + sensorData + iGateBeaconPacket.substring(iGateBeaconPacket.indexOf(":=")+21);
secondaryBeaconPacket = iGateLoRaBeaconPacket + sensorData + Config.beacon.comment;
} else {
beaconPacket = iGateBeaconPacket;
secondaryBeaconPacket = iGateLoRaBeaconPacket + Config.beacon.comment;
beaconPacket += sensorData;
secondaryBeaconPacket += sensorData;
} else if (Config.bme.active && wxModuleType == 0) {
beaconPacket += ".../...g...t...r...p...P...h..b.....";
secondaryBeaconPacket += ".../...g...t...r...p...P...h..b.....";
}
beaconPacket += Config.beacon.comment;
secondaryBeaconPacket += Config.beacon.comment;
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2)
if (Config.sendBatteryVoltage) {
beaconPacket += " (Batt=" + String(BATTERY_Utils::checkBattery(),2) + "V)";
sixthLine = " (Batt=" + String(BATTERY_Utils::checkBattery(),2) + "V)";
}
#if defined(BATTERY_PIN) || defined(HAS_AXP192) || defined(HAS_AXP2101)
if (Config.battery.sendInternalVoltage || Config.battery.monitorInternalVoltage) {
float internalVoltage = BATTERY_Utils::checkInternalVoltage();
String internalVoltageInfo = String(internalVoltage,2) + "V";
if (Config.battery.sendInternalVoltage) {
beaconPacket += " Batt=";
beaconPacket += internalVoltageInfo;
secondaryBeaconPacket += " Batt=";
secondaryBeaconPacket += internalVoltageInfo;
sixthLine = " (Batt=";
sixthLine += internalVoltageInfo;
sixthLine += ")";
}
if (Config.battery.monitorInternalVoltage && internalVoltage < Config.battery.internalSleepVoltage) {
beaconPacket += " **IntBatWarning:SLEEP**";
secondaryBeaconPacket += " **IntBatWarning:SLEEP**";
shouldSleepLowVoltage = true;
}
}
#endif
if (Config.externalVoltageMeasurement) {
beaconPacket += " (Ext V=" + String(BATTERY_Utils::checkExternalVoltage(),2) + "V)";
sixthLine = " (Ext V=" + String(BATTERY_Utils::checkExternalVoltage(),2) + "V)";
if (Config.battery.sendExternalVoltage || Config.battery.monitorExternalVoltage) {
float externalVoltage = BATTERY_Utils::checkExternalVoltage();
String externalVoltageInfo = String(externalVoltage,2) + "V";
if (Config.battery.sendExternalVoltage) {
beaconPacket += " Ext=";
beaconPacket += externalVoltageInfo;
secondaryBeaconPacket += " Ext=";
secondaryBeaconPacket += externalVoltageInfo;
sixthLine = " (Ext V=";
sixthLine += externalVoltageInfo;
sixthLine += ")";
}
if (Config.battery.monitorExternalVoltage && externalVoltage < Config.battery.externalSleepVoltage) {
beaconPacket += " **ExtBatWarning:SLEEP**";
secondaryBeaconPacket += " **ExtBatWarning:SLEEP**";
shouldSleepLowVoltage = true;
}
}
if (Config.aprs_is.active && Config.beacon.sendViaAPRSIS) {
if (Config.aprs_is.active && Config.beacon.sendViaAPRSIS && !backUpDigiMode) {
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, "SENDING IGATE BEACON", 0);
seventhLine = " listening...";
APRS_IS_Utils::upload(beaconPacket);
#ifdef ESP32_DIY_LoRa_A7670
A7670_Utils::uploadToAPRSIS(beaconPacket);
#else
APRS_IS_Utils::upload(beaconPacket);
#endif
}
if (Config.beacon.sendViaRF) {
if (Config.beacon.sendViaRF || backUpDigiMode) {
show_display(firstLine, secondLine, thirdLine, fourthLine, fifthLine, sixthLine, "SENDING DIGI BEACON", 0);
seventhLine = " listening...";
LoRa_Utils::sendNewPacket("APRS", secondaryBeaconPacket);
STATION_Utils::addToOutputPacketBuffer(secondaryBeaconPacket);
}
lastBeaconTx = millis();
@@ -153,23 +200,8 @@ 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) {
display_toggle(false);
}
}
@@ -183,39 +215,43 @@ namespace Utils {
}
}
void typeOfPacket(String packet, String packetType) {
String sender;
if (WiFi.status() == WL_CONNECTED) { // If mode 1 2 5
if (packetType == "LoRa-APRS") {
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";
} else if (packetType == "APRS-LoRa") {
break;
case 1: // APRS-LoRa
fifthLine = "APRS-IS ----> LoRa Tx";
}
sender = packet.substring(0,packet.indexOf(">"));
} else {
fifthLine = "LoRa Rx ----> LoRa Tx";
sender = packet.substring(3,packet.indexOf(">"));
break;
case 2: // Digi
fifthLine = "LoRa Rx ----> LoRa Tx";
break;
}
for (int i=sender.length();i<9;i++) {
for (int i = sender.length(); i < 9; i++) {
sender += " ";
}
sixthLine = sender;
String seventhLineHelper = "RSSI:";
seventhLineHelper += String(rssi);
seventhLineHelper += "dBm SNR: ";
seventhLineHelper += String(snr);
seventhLineHelper += "dBm";
if (packet.indexOf("::") >= 10) {
if (packetType == "APRS-LoRa") {
String addresseeAndMessage = packet.substring(packet.indexOf("::")+2);
String addressee = addresseeAndMessage.substring(0, addresseeAndMessage.indexOf(":"));
addressee.trim();
sixthLine = sender + " > " + addressee;
} else {
sixthLine = sender + "> MESSAGE";
}
seventhLine = "RSSI:" + String(rssi) + "dBm SNR: " + String(snr) + "dBm";
sixthLine += "> MESSAGE";
seventhLine = seventhLineHelper;
} else if (packet.indexOf(":>") >= 10) {
sixthLine = sender + "> NEW STATUS";
seventhLine = "RSSI:" + String(rssi) + "dBm SNR: " + String(snr) + "dBm";
sixthLine += "> NEW STATUS";
seventhLine = seventhLineHelper;
} else if (packet.indexOf(":!") >= 10 || packet.indexOf(":=") >= 10) {
sixthLine = sender + "> GPS BEACON";
GPS_Utils::getDistance(packet);
seventhLine = "RSSI:" + String(rssi) + "dBm";
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 {
@@ -224,20 +260,113 @@ namespace Utils {
if (distance.indexOf(".") == 1) {
seventhLine += " ";
}
seventhLine += "D:" + distance + "km";
seventhLine += "D:";
seventhLine += distance;
seventhLine += "km";
} else if (packet.indexOf(":T#") >= 10 && packet.indexOf(":=/") == -1) {
sixthLine = sender + "> TELEMETRY";
seventhLine = "RSSI:" + String(rssi) + "dBm SNR: " + String(snr) + "dBm";
sixthLine += "> TELEMETRY";
seventhLine = seventhLineHelper;
} else if (packet.indexOf(":`") >= 10) {
sixthLine = sender + "> MIC-E";
seventhLine = "RSSI:" + String(rssi) + "dBm SNR: " + String(snr) + "dBm";
sixthLine += "> MIC-E";
seventhLine = seventhLineHelper;
} else if (packet.indexOf(":;") >= 10) {
sixthLine = sender + "> OBJECT";
seventhLine = "RSSI:" + String(rssi) + "dBm SNR: " + String(snr) + "dBm";
sixthLine += "> OBJECT";
seventhLine = seventhLineHelper;
} else {
sixthLine = sender + "> ??????????";
seventhLine = "RSSI:" + String(rssi) + "dBm SNR: " + String(snr) + "dBm";
sixthLine += "> ??????????";
seventhLine = seventhLineHelper;
}
}
void print(const String& text) {
if (!Config.tnc.enableSerial) {
Serial.print(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) {
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) {
display_toggle(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("-")) { // SSID Validation
cleanCallsign = callsign.substring(0, callsign.indexOf("-"));
String ssid = callsign.substring(callsign.indexOf("-") + 1);
int ssidInt = ssid.toInt();
if (ssidInt == 0 && ssid != "0") {
return false;
} else if (ssidInt < 0 || ssidInt > 15) {
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])) return false; // __0A must be validated
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)
}
if (!isValid) return false; // also 00__ avoided
if (cleanCallsign.length() > 4) {
for (int i = 5; i <= cleanCallsign.length(); i++) {
if (!isAlpha(cleanCallsign[i - 1])) return false;
}
}
return true;
}
}
+21 -12
View File
@@ -3,21 +3,30 @@
#include <Arduino.h>
class ReceivedPacket {
public:
long millis;
String packet;
int RSSI;
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 onOTAStart();
void onOTAProgress(size_t current, size_t final);
void onOTAEnd(bool success);
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);
}
+120 -65
View File
@@ -1,8 +1,13 @@
#include <ArduinoJson.h>
#include "configuration.h"
#include "ota_utils.h"
#include "web_utils.h"
#include "display.h"
#include "utils.h"
extern Configuration Config;
extern Configuration Config;
extern uint32_t lastBeaconTx;
extern std::vector<ReceivedPacket> receivedPackets;
extern const char web_index_html[] asm("_binary_data_embed_index_html_gz_start");
extern const char web_index_html_end[] asm("_binary_data_embed_index_html_gz_end");
@@ -56,6 +61,23 @@ namespace WEB_Utils {
request->send(200, "application/json", fileContent);
}
void handleReceivedPackets(AsyncWebServerRequest *request) {
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;
}
String buffer;
serializeJson(data, buffer);
request->send(200, "application/json", buffer);
}
void handleWriteConfiguration(AsyncWebServerRequest *request) {
Serial.println("Got new config from www");
@@ -67,98 +89,129 @@ 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.wifiAutoAP.password = request->getParam("wifi.autoAP.password", true)->value();
Config.wifiAutoAP.powerOff = request->getParam("wifi.autoAP.powerOff", true)->value().toInt();
Config.callsign = request->getParam("callsign", true)->value();
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.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.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.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.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);
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.digi.mode = request->getParam("digi.mode", 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.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.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();
Config.battery.sendExternalVoltage = request->hasParam("battery.sendExternalVoltage", true);
if (Config.battery.sendExternalVoltage) {
Config.battery.externalVoltagePin = request->getParam("battery.externalVoltagePin", true)->value().toInt();
}
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.bme.heightCorrection = request->getParam("bme.heightCorrection", true)->value().toInt();
Config.bme.temperatureCorrection = request->getParam("bme.temperatureCorrection", true)->value().toFloat();
if (Config.bme.active) {
Config.beacon.symbol = "_";
}
Config.display.turn180 = request->hasParam("display.turn180", true);
Config.syslog.active = request->hasParam("syslog.active", true);
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.syslog.server = request->getParam("syslog.server", true)->value();
Config.syslog.port = request->getParam("syslog.port", true)->value().toInt();
}
Config.bme.active = request->hasParam("bme.active", 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.ota.username = request->getParam("ota.username", true)->value();
Config.ota.password = request->getParam("ota.password", true)->value();
Config.rebootMode = request->hasParam("other.rebootMode", true);
Config.rebootModeTime = request->getParam("other.rebootModeTime", true)->value().toInt();
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.ota.username = request->getParam("ota.username", true)->value();
Config.ota.password = request->getParam("ota.password", 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.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.writeFile();
AsyncWebServerResponse *response = request->beginResponse(302, "text/html", "");
AsyncWebServerResponse *response = request->beginResponse(302, "text/html", "");
response->addHeader("Location", "/");
request->send(response);
display_toggle(false);
ESP.restart();
}
void handleAction(AsyncWebServerRequest *request) {
String type = request->getParam("type", false)->value();
if (type == "send-beacon") {
lastBeaconTx = 0;
request->send(200, "text/plain", "Beacon will be sent in a while");
} else if (type == "reboot") {
display_toggle(false);
ESP.restart();
} else {
request->send(404, "text/plain", "Not Found");
}
}
void handleStyle(AsyncWebServerRequest *request) {
AsyncWebServerResponse *response = request->beginResponse_P(200, "text/css", (const uint8_t*)web_style_css, web_style_css_len);
response->addHeader("Content-Encoding", "gzip");
@@ -188,8 +241,10 @@ namespace WEB_Utils {
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);
+50 -23
View File
@@ -1,29 +1,56 @@
#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 int 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) {
if (backUpDigiMode) {
uint32_t WiFiCheck = millis() - lastBackupDigiTime;
if (WiFi.status() != WL_CONNECTED && WiFiCheck >= 15 * 60 * 1000) {
Serial.println("*** Stoping BackUp Digi Mode ***");
backUpDigiMode = false;
wifiCounter = 0;
} else if (WiFi.status() == WL_CONNECTED) {
Serial.println("*** WiFi Reconnect Success (Stoping 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.reconnect();
previousWiFiMillis = millis();
if (Config.backupDigiMode) {
wifiCounter++;
}
if (wifiCounter >= 2) {
Serial.println("*** Starting BackUp Digi Mode ***");
backUpDigiMode = true;
lastBackupDigiTime = millis();
}
}
}
@@ -42,27 +69,27 @@ namespace WIFI_Utils {
if (currentWiFi->ssid == "") {
startAP = true;
} else {
int wifiCounter = 0;
uint8_t wifiCounter = 0;
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(500);
unsigned long start = millis();
show_display("", "", "Connecting to Wifi:", "", currentWiFi->ssid + " ...", 0);
show_display("", "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);
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
digitalWrite(internalLedPin,HIGH);
#ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN,HIGH);
#endif
Serial.print('.');
delay(500);
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
digitalWrite(internalLedPin,LOW);
#ifdef INTERNAL_LED_PIN
digitalWrite(INTERNAL_LED_PIN,LOW);
#endif
if ((millis() - start) > 10000){
delay(1000);
if(myWiFiAPIndex >= (myWiFiAPSize-1)) {
if(myWiFiAPIndex >= (myWiFiAPSize - 1)) {
myWiFiAPIndex = 0;
wifiCounter++;
} else {
@@ -72,29 +99,29 @@ 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);
show_display("", "Connecting to Wifi:", "", currentWiFi->ssid + " ...", 0);
WiFi.disconnect();
WiFi.begin(currentWiFi->ssid.c_str(), currentWiFi->password.c_str());
}
}
}
#if defined(TTGO_T_LORA32_V2_1) || defined(HELTEC_V2) || defined(HELTEC_V3) || defined(ESP32_DIY_LoRa) || defined(ESP32_DIY_1W_LoRa)
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);
show_display("", " 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);
show_display("", " 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);
show_display("", " Starting Auto AP", " Please connect to it " , " loading ...", 1000);
startAutoAP();
}
+10 -1
View File
@@ -1,4 +1,7 @@
import gzip
import os
import datetime
Import("env")
files = [
'data_embed/index.html',
@@ -8,13 +11,19 @@ files = [
'data_embed/bootstrap.css',
]
for src in files:
out = src + ".gz"
with open(src, 'rb') as f:
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', '')
current_date = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S') + " UTC"
build_info = f'{env_vars}<br>Build date: {current_date}'.encode()
content = content.replace(b'%BUILD_INFO%', build_info)
with open(out, 'wb') as f:
f.write(gzip.compress(content, compresslevel=9))